2

I'm using updating out Exchange Mail Client written in .NET 4 Framework using Exchange Web Services (EWS) to .NET Core 6 using Microsoft.Graph. I've managed to port most of the functions but I'm having trouble working out how to Forward a Message as an Attachment.

In EWS

// This method results in a GetItem call to EWS.
var msgToAttach = EWS.EmailMessage.Bind(
    ServiceInstance,
    message.Source.Id,
    new EWS.PropertySet(EWS.ItemSchema.MimeContent, EWS.ItemSchema.Subject));

// Create an email message and set properties on the message.
var forward = new EWS.EmailMessage(ServiceInstance);
if (!bodyType.HasValue)
    bodyType = message.BodyType;

forward.Subject = subject == null ? $"FW: {message.Subject}" : subject;
forward.Body = new EWS.MessageBody(
    bodyType.Value == BodyTypes.Html ? EWS.BodyType.HTML : EWS.BodyType.Text,
    body ?? "Please refer to the attachment message");

// Add additional recipients to the reply email message. 
if (to?.Any() ?? false)
    forward.ToRecipients.AddRange(to);
if (cc?.Any() ?? false)
    forward.CcRecipients.AddRange(cc);
if (bcc?.Any() ?? false)
    forward.BccRecipients.AddRange(bcc);

// before we can add the attachments, we need to save the draft
// according to the docoumentation this isn't required but without
// it throws an exception on Save/SendAndSaveCopy if the attachments
// are added to a message which doesn't exist
forward.Save();

// Add an email message item attachment and set properties on the item.
EWS.ItemAttachment<EWS.EmailMessage> itemAttachment = forward.Attachments.AddItemAttachment<EWS.EmailMessage>();
itemAttachment.Item.MimeContent = msgToAttach.MimeContent;
itemAttachment.Name = msgToAttach.Subject;
// Send the mail and save a copy in the Sent Items folder.
// This method results in a CreateItem and SendItem call to EWS.
forward.Update(EWS.ConflictResolutionMode.AlwaysOverwrite);
forward.Send();

UPDATE: Solution You can read the mime content using

_serviceInstance.Users[UserId].Messages[message.Id].Content.GetAsync()

which returns a stream that can be saved as .eml file. The attachment name must end with .eml or it doesn't work.

    public void ForwardMessageAsAttachment(
        Message message,
        IEnumerable<string> to,
        string subject = null,
        string body = null,
        BodyType? bodyType = null)
    {
        // Download the mime content for the specific message
        var mimeContentStream = _serviceInstance
            .Users[UserId]
            .Messages[message.Id]
            .Content
            .Request()
            .GetAsync()
            .GetAwaiter()
            .GetResult();

        // the mine content is returned as a Stream, so write it to buffer
        var buffer = new Span<Byte>(new byte[mimeContentStream.Length]);
        var mimeContent = mimeContentStream.Read(buffer);

        // The attachment Name must ends with .eml else Outlook wont recognize its an email
        // even with the contentType = message/rfc822
        var messageAsAttachment = new FileAttachment
        {
            ContentBytes = buffer.ToArray(),
            ContentType = "message/rfc822",
            Name = $"{message.Subject}.eml"
        };

        // create a new message
        var forward = new Message()
        {
            Attachments = new MessageAttachmentsCollectionPage(),
            Subject = String.IsNullOrWhiteSpace(subject) ? subject : $"FW: {message.Subject}".Trim(),
            Body = new ItemBody
            {
                ContentType = bodyType,
                Content = body
            },
            ToRecipients = to.Select(x => new Recipient { EmailAddress = new EmailAddress { Address = x } })
        };

        // add the EML attachment
        forward.Attachments.Add(messageAsAttachment);

        _serviceInstance
            .Users[UserId]
            .SendMail(forward)
            .Request()
            .PostAsync()
            .GetAwaiter()
            .GetResult();
    }
Rhett Leech
  • 145
  • 1
  • 2
  • 14
  • What part are you stuck on? Turning the email into a file? If so, I found this https://stackoverflow.com/questions/54820844/download-attachments-from-mail-using-microsoft-graph-rest-api – CthenB Nov 15 '22 at 10:00
  • @Chrotenise thanks for the response but the provided link discusses download attachment rather than forwarding a message as an attachment. – Rhett Leech Nov 16 '22 at 01:09

2 Answers2

2

Mime content from a message can be read using MS Graph and converted to .EML, then sent FileAttachment on a new message. You need to make sure the attachment's name ends with .eml or outlook will not recognize attachment as a message. Adding content type of message/rfc822 does not appear to affect how the attachment is read by gmail, hotmail or Outlook desktop.

    public void ForwardMessageAsAttachment(
        Message message,
        IEnumerable<string> to,
        string subject = null,
        string body = null,
        BodyType? bodyType = null)
    {
        // Download the mime content for the specific message
        // _serviceInstance is an instance of GraphServiceClient
        var mimeContentStream = _serviceInstance 
            .Users[UserId]
            .Messages[message.Id]
            .Content
            .Request()
            .GetAsync()
            .GetAwaiter()
            .GetResult();

        // the mine content is returned as a Stream, so write it to buffer
        var buffer = new Span<Byte>(new byte[mimeContentStream.Length]);
        var mimeContent = mimeContentStream.Read(buffer);

        // The attachment Name must ends with .eml else Outlook wont recognize its an email
        // even with the contentType = message/rfc822
        var messageAsAttachment = new FileAttachment
        {
            ContentBytes = buffer.ToArray(),
            ContentType = "message/rfc822",
            Name = $"{message.Subject}.eml"
        };

        // create a new message
        var forward = new Message()
        {
            Attachments = new MessageAttachmentsCollectionPage(),
            Subject = String.IsNullOrWhiteSpace(subject) ? subject : $"FW: {message.Subject}".Trim(),
            Body = new ItemBody
            {
                ContentType = bodyType,
                Content = body
            },
            ToRecipients = to.Select(x => new Recipient { EmailAddress = new EmailAddress { Address = x } })
        };

        // add the EML attachment
        forward.Attachments.Add(messageAsAttachment);

        _serviceInstance 
            .Users[UserId]
            .SendMail(forward)
            .Request()
            .PostAsync()
            .GetAwaiter()
            .GetResult();
    }
Rhett Leech
  • 145
  • 1
  • 2
  • 14
1

In the Graph there is no equivalent to

EWS.ItemAttachment<EWS.EmailMessage> itemAttachment = 
forward.Attachments.AddItemAttachment<EWS.EmailMessage>();
itemAttachment.Item.MimeContent = msgToAttach.MimeContent;

So your options are to attach the message as an EML file as a File Attachment

or you can build the MIME message outside with a MIME parser like mailkit and then send the message as MIME https://github.com/microsoftgraph/microsoft-graph-docs/blob/main/concepts/outlook-send-mime-message.md you will be limited on size with this method you can have anything larger then 4MB and with mimebloat that usually means around 2-3 MB

Glen Scales
  • 20,495
  • 1
  • 20
  • 23