Is the 3 MB limit for attachments in Microsoft Graph API mail messages cumulative?

5.4k views Asked by At

I have been using Microsoft Graph .NET Client Library to send mail messages for quite a while and it's been working great but today I noticed a very strange problem.

As of today here are the basic rules for attachments...

  • If the file size is under 3 MB, do a single POST on the attachments navigation property of the Outlook item; see how to do this for a message or for an event. The successful POST response includes the ID of the file attachment.
  • If the file size is between 3MB and 150MB, create an upload session, and iteratively use PUT to upload ranges of bytes of the file until you have uploaded the entire file. A header in the final successful PUT response includes a URL with the attachment ID.

https://learn.microsoft.com/en-us/graph/outlook-large-attachments?tabs=http

So pretty simple. If the attachment is less than 3 MB I simply include it with the message. If it's more then I create an upload session.

Now for the problem. If there are multiple attachments that add up to a total size that is over that limit I receive the following message...

The maximum request length supported is 4MB.

To try and work around this I started upload sessions for the rest of the files after the cumulative limit was hit. However, I then received the following error message...

Message: Attachment size must be greater than the minimum size.

This is because there is a minimum size for upload sessions.

Quick recap: I cannot upload multiple small attachments when the total exceeds the maximum limit. I can't upload them with a session because it is less than the minimum limit. Has anyone noticed this problem?

Using Microsoft Graph Client Library v3.6

2

There are 2 answers

0
NickSas On

Not sure if this will work. But you could try to save the email as a template and use the API to add the attachments to the template. Then send the template.

It looks like the limit is a limit on the size for a call, not the size of the email.

3
SyLaDe On

The below code works for the total > 4 Mb:

Message draft = await _GraphClient
                        .Users[UserPrincipalNameOrId]
                        .MailFolders
                        .Drafts
                        .Messages
                        .Request()
                        //.WithMaxRetry(5)
                        .AddAsync(emailToSend);

foreach (var attachment in Attachments)
{
    if (attachment.FullPath != null)
    {
        FileInfo f = new FileInfo(attachment.FullPath);
        if (f.Length < MINIMUM_SIZE_FOR_UPLOAD_SESSION) // 3 Mo
        {
            string mimeType = MimeTypes.MimeTypeMap.GetMimeType(f.Extension); 
            FileAttachment fileAttachment = new FileAttachment
            {
                ODataType = "#microsoft.graph.fileAttachment",
                ContentBytes = System.IO.File.ReadAllBytes(attachment.FullPath),
                ContentType = mimeType,
                ContentId = f.Name, 
                Name = f.Name
            };
            await _GraphClient
                    .Users[UserPrincipalNameOrId]
                    .Messages[draft.Id]
                    .Attachments
                    .Request()
                    .AddAsync(fileAttachment);
        }
        else
        {
            // Attachments >= 3 Mb
            using (var filestream = System.IO.File.Open(attachment.FullPath, System.IO.FileMode.Open, FileAccess.Read, FileShare.None))
            {
                var attachmentItem = new AttachmentItem
                {
                    AttachmentType = AttachmentType.File,
                    Name = Path.GetFileName(filestream.Name),
                    Size = filestream.Length
                };

                var uploadSession = await _GraphClient
                        .Users[UserPrincipalNameOrId]
                        .Messages[draft.Id]
                        .Attachments
                        .CreateUploadSession(attachmentItem)
                        .Request()
                        .PostAsync();

                var maxSliceSize = 320 * 1024; // 320 KB - Change this to your slice size. 5MB is the default.
                var largeFileUploadTask = new LargeFileUploadTask<FileAttachment>(uploadSession, filestream, maxSliceSize);

                // upload away with relevant callback
                IProgress<long> progressCallback = new Progress<long>(prog => { });
                try
                {
                    var uploadResult = await largeFileUploadTask.UploadAsync(progressCallback);
                    if (!uploadResult.UploadSucceeded)
                    {
                        // error
                    }
                }
                catch (ServiceException e)
                {
                    // exception
                }
            } // using()
        }
    }
}

await _GraphClient
        .Users[UserPrincipalNameOrId]
        .Messages[draft.Id]
        .Send()
        .Request()
        .WithMaxRetry(5)
        .PostAsync();