Search code examples
c#microsoft-graph-sdksmicrosoft-graph-mail

Microsoft.Graph: How to set ContentId of large embedded inline attachment/image


To send email using Microsoft.Graph, I use code like the following (simplified):

var recipientList = new List<Recipient>
{
    new Recipient { EmailAddress = new EmailAddress {Address = "recipient@example.com"}}
};

var email = new Message
{
    Body = new ItemBody
    {
        Content = "<html> ... <img src='cid:CID12345@example.com'> ... </html>",  
        ContentType = BodyType.Html,
    },
    Subject = "Message containing inline image",
    ToRecipients = recipientList,
};

Message draft = await graphClient.Me
.MailFolders
.Drafts
.Messages
.Request()
.AddAsync(email);


byte[] contentBytes = ...;

if (contentBytes.Length < 3 * 1024 * 1024)
{
    // Small Attachments

    var fileAttachment = new FileAttachment
    {
        Name = "Image.png",
        ContentBytes = contentBytes,
        ContentId = "CID12345@example.com",
        IsInline = true,
        Size = contentBytes.Length
    };

    Attachment uploadedFileAttachment = await graphClient.Me.Messages[draft.Id].Attachments
        .Request()
        .AddAsync(fileAttachment);
}
else
{
    // Large Attachments

    var contentStream = new MemoryStream(contentBytes);

    var attachmentItem = new AttachmentItem
    {
#warning TODO: How to set ContentId?

        AttachmentType = AttachmentType.File,
        Name = "Image.png",
        Size = contentStream.Length,
        IsInline = true,
    };

    UploadSession uploadSession = await graphClient.Me.Messages[draft.Id].Attachments
        .CreateUploadSession(attachmentItem)
        .Request()
        .PostAsync();

    var maxSliceSize = 320 * 1024;  // Must be a multiple of 320KiB.
    var largeFileUploadTask = new LargeFileUploadTask<FileAttachment>(uploadSession, contentStream, maxSliceSize);

    UploadResult<FileAttachment> uploadResult = await largeFileUploadTask.UploadAsync();

await graphClient.Me.Messages[draft.Id].Send().Request().PostAsync();
}

The email contains an inline image. The image file is added as an attachment. To link this attachment to an HTML img element, I set FileAttachment.ContentId to a value which I also set in the HTML image element's src attribute.

This works as long as the image is smaller than 3 MB. For larger attachments, we have to add the attachment differently - which is also shown in the code above. Instead of a FileAttachment, an AttachmentItem is used, which has an IsInline-Property like FileAttachment. Unfortunately, unlike FileAttachment, AttachmentItem does not have a ContentId property.

https://learn.microsoft.com/en-us/graph/api/resources/fileattachment?view=graph-rest-1.0 https://learn.microsoft.com/en-us/graph/api/resources/attachmentitem?view=graph-rest-1.0

How can I set a ContentId on large attachments?


Solution

  • In the meantime, a ContentId property was added to Microsoft.Graph.Models.AttachmentItem (similar to FileAttachment.ContentId). Tested ok with Microsoft Graph 5.56.0.

    See: https://learn.microsoft.com/en-us/graph/api/attachment-createuploadsession?view=graph-rest-1.0&tabs=csharp

    Chapter "Example 2: Create an upload session to add a large in-line attachment to a draft message"