1

I'm using Microsoft-Graph API version 1.4 and trying to send mail with multiple attachments (with size greater then 4MB) using following code..

val address = EmailAddress()
address.address = "vivek@domain.com"
val recipient = Recipient()
recipient.emailAddress = address

val message = MyMessage()
message.subject = "Test E-Mail"
message.body = getItemBody()
message.toRecipients = Collections.singletonList(recipient)

val att = FileAttachment()
att.contentBytes = File("/home/user/file.pdf").readBytes()
att.contentType = "text/pdf"
att.name = "file.pdf"
att.oDataType = "#microsoft.graph.fileAttachment"

val att2 = FileAttachment()
att2.contentBytes = "hello there! from second file".toByteArray(StandardCharsets.UTF_8)
att2.contentType = "text/plain"
att2.name = "hi2.txt"
att2.oDataType = "#microsoft.graph.fileAttachment"

message.addAttachment(att)
message.addAttachment(att2)

graphClient.me()
.sendMail(message,false)
.buildRequest()
.post();

In response, I'm getting following error..

{
    "status": "INTERNAL_SERVER_ERROR",
    "exception": "GraphServiceException",
    "message": "Error code: BadRequest\nError message: The maximum request length supported is 4MB.\n\nPOST https://graph.microsoft.com/v1.0/me/microsoft.graph.sendMail\nSdkVersion : graph-java-v1.4.0\nAuthorization : Bearer eyJ0eXAiOiJKV1QiLCJub25jZSI[...]\n{\"message\":{\"attachments\":[{\"contentBytes\":\"JVBERi[...]\n\n413 : Request Entity Too Large\n[...]\n\n[Some information was truncated for brevity, enable debug logging for more details]",
    "existing": null,
    "errorData": null,
    "tenant": null
}

Can anyone help me to send a mail with multiple attachment with size greater then 4MB.

Thanks

Vivek Buddhadev
  • 197
  • 1
  • 22

1 Answers1

4

In order to add multiple attachments at once when their total size exceeds 4MB, you need:

  1. create the message (as a draft)
  2. create the attachment with an upload session
  3. upload the attachment using the session you just created (repeat for each attachment)
  4. send the draft email

Here is a code sample that does something along those lines

    String draftSubject = "Draft Test Message " + Double.toString(Math.random()*1000);
    User me = graphClient.me().buildRequest().get();
    Recipient r = new Recipient();
    EmailAddress address = new EmailAddress();
    address.address = me.mail;
    r.emailAddress = address;
    Message message = new Message();
    message.subject = draftSubject;
    ArrayList<Recipient> recipients = new ArrayList<Recipient>();
    recipients.add(r);
    message.toRecipients = recipients;
    message.isDraft = true;
    
    //Save the message as a draft
    Message newMessage = graphClient.me().messages().buildRequest().post(message);

    File file = new File("src/test/resources/largefile10M.blob");

    AttachmentItem attachmentItem = new AttachmentItem();
    attachmentItem.attachmentType = AttachmentType.FILE;
    attachmentItem.name = file.getName();
    attachmentItem.size = file.length();
    attachmentItem.contentType = "application/octet-stream";

    InputStream fileStream = OutlookTests.class.getClassLoader().getResourceAsStream("largefile10M.blob");

    long streamSize = attachmentItem.size;

    UploadSession uploadSession = graphClient.me()
                                .messages(newMessage.id)
                                .attachments()
                                .createUploadSession(attachmentItem)
                                .buildRequest()
                                .post();

    ChunkedUploadProvider<AttachmentItem> chunkedUploadProvider = new ChunkedUploadProvider<>(uploadSession, testBase.graphClient, fileStream,
            streamSize, AttachmentItem.class);
    
    // Do the upload
    chunkedUploadProvider.upload(callback);

    //Send the drafted message
    graphClient.me().mailFolders("Drafts").messages(newMessage.id).send().buildRequest().post();

Here is a sample implementation for the callback.

    IProgressCallback<AttachmentItem> callback = new IProgressCallback<AttachmentItem> () {
        @Override
        public void progress(final long current, final long max) {
            //Check progress
        }
        @Override
        public void success(final AttachmentItem result) {
            //Handle the successful response
        }
        
        @Override
        public void failure(final ClientException ex) {
            //Handle the failed upload
        }
    };
baywet
  • 4,377
  • 4
  • 20
  • 49
  • I've upgraded the graph version from 1.4 to 2.3 in order to execute your given example. Now could you please let me know that what could be the callback in chunkedUploadProvider.upload(callback)? – Vivek Buddhadev Oct 08 '20 at 17:33
  • Thanks for the update. Now I've tried exactly same code you have provided. just updated the file path with my blob file. The mail sent and received successfully but without attachment. is there anything we are missing? – Vivek Buddhadev Oct 09 '20 at 07:39
  • I've printout the exception logs in the failure function. it looks like following.. com.microsoft.graph.core.ClientException: Upload session failed. at com.microsoft.graph.requests.extensions.ChunkedUploadRequest.upload(ChunkedUploadRequest.java:115) at com.microsoft.graph.concurrency.ChunkedUploadProvider.upload(ChunkedUploadProvider.java:186) at com.microsoft.graph.concurrency.ChunkedUploadProvider.upload(ChunkedUploadProvider.java:214) – Vivek Buddhadev Oct 09 '20 at 08:35
  • 1
    There's currently a service behavior that's making the SDK fail. We have implemented the fix and it'll be released with the next version 2.3.1 https://github.com/microsoftgraph/msgraph-sdk-java/issues/529 – baywet Oct 09 '20 at 11:14
  • I've used recently released version 2.3.1. But problem is still the same. To double check the version upgrade. I've refresh the dependency and verify that the application uses 2.3.1 version or not. It uses the same 2.3.1 version. – Vivek Buddhadev Oct 11 '20 at 06:12
  • The problem of Upload session failed is due authentication provider I've used for the access token which was adding the authorization token in the chunk upload. As per the suggestion by @baywet in https://github.com/microsoftgraph/msgraph-sdk-java/issues/537 The issue is resolved. Thanks baywet – Vivek Buddhadev Oct 17 '20 at 06:50
  • You may find this works for you https://learn.microsoft.com/en-us/graph/sdks/large-file-upload?context=graph%2Fapi%2F1.0&view=graph-rest-1.0&tabs=csharp – Sn3akyP3t3 Aug 20 '21 at 02:21