Tech Tip: Send Emails with File Attachments from a .Net Core App using AWS SES

Updated on: 21 Oct 2020

For one of our projects, we built a .Net Core app which sends emails with attachments. SendGrid was originally used as the transactional email service provider to deliver the emails. To integrate with SendGrid, we decided to go with the SMTP relay approach and facilitated using the Nuget Package, MailKit.

When the client decided to migrate from SendGrid to AWS Simple Email Service (SES), we assumed it would be a simple lift and drop by updating the SMTP relay settings.

We initially updated the SMTP settings to the provided AWS SES settings and did a few basic tests. Simple HTML/Plain-text emails delivered just fine but the moment, we send emails with attachments, we received an error.

This prompted us to read the AWS SES documentation (which we admittedly should have done earlier). From that point, we learned that in order to send emails with attachments using AWS SES, we need to use AWS SES's SendRawEmail API.

To start the integration with SendRAwEmailAPI, we Nuget installed the AWS SES SDK (AWSSDK.SimpleEmail). Then we set up the access and secret keys needed to call the APIs using AWS IAM.

After which we then realised that the AWS SDK does not expose any methods for us to add attachments to an email before calling the SendRawEmailAsync(request) method.

To resolve the issue, we decided to use the MimeKit library. We used the library to create a MimeKit MimeMessage object which is then converted into a raw email message with attachments .The raw email message is then passed into the AWS SDK for delivery.

When all is said and then, we end up with a code similar to the one below:

using Amazon.SimpleEmail;
using Amazon.SimpleEmail.Model;
using MimeKit;
using System;
using System.IO;
using System.Threading.Tasks;

namespace MinatCoding.AwsSesEmail
{
    class Program
    {
        static async Task Main(string[] args)
        {
            using (var client = new AmazonSimpleEmailServiceClient("AWS Access Key", "AWS Secret Key"))
            {

                var bodyBuilder = new BodyBuilder();

                bodyBuilder.HtmlBody = "Hello World. Please view the attachment.";
                bodyBuilder.TextBody = "Hello World. Please view the attachment.";

                using (FileStream fileStream = new FileStream("File path e.g. C:/pics/my-pic.jpg", FileMode.Open, FileAccess.Read))
                {
                    bodyBuilder.Attachments.Add("Filename.ext e.g pic.jpg", fileStream);
                }

                var mimeMessage = new MimeMessage();
                mimeMessage.From.Add(new MailboxAddress("From Name", "From email address e.g. no-reply@minatcoding.com"));
                mimeMessage.To.Add(new MailboxAddress("Recipient Name", "recipient email address e.g. recipient@minatcoding.com"));

                mimeMessage.Subject = "Hello World";
                mimeMessage.Body = bodyBuilder.ToMessageBody();
                using (var messageStream = new MemoryStream())
                {
                    await mimeMessage.WriteToAsync(messageStream);
                    var sendRequest = new SendRawEmailRequest { RawMessage = new RawMessage(messageStream) };
                    var response = await client.SendRawEmailAsync(sendRequest);
                }
                Console.WriteLine("Email Successfully Sent");
            }

        }
    }
}

Here are some more posts