CodeWithYou

AWS SES sends mails with a custom Reference header

Published on
Authors
AWS SES sends mails with a custom Reference header

Photo by Mathyas Kurmann

Use case: Group emails by a thread

Sometimes you want mail clients to group emails into threads. For example, if you have a group of emails that are related to the same topic, you want to mail client to group them together when user view the list of emails in threaded view.

Like this one:

my alt text
Figure 1: Thread view in Mail App

Solution

There are a few ways around this / to work with this.

  1. Use In-Reply-To header. If the email is a reply to another email, you can use the In-Reply-To header to group the emails together.
  2. Use References header to group emails together.

In my case, I use the second method.

Add custom headers to the email in AWS SES

To add custom headers to the email, I used sendRawEmail instead of sendEmail method. Below is full example of how to add custom headers to the email.

import AWS from 'aws-sdk'
const { SES } = AWS

// update the following variables with the values from your configuration
AWS.config.update({ region: 'region' })
const fromEmail = 'Info <from@example.com>'
const to = 'to@yourdomain.com'

// fixed a reference id for testing. Replace with your own topic reference id
const TOPIC_REFERENCE = '<111111@example.com>'

// Subject of the email, append the date to the subject. This make subject unique every time the email is sent
const subject = `Test email from AWS SES!!! ${new Date()}`
const plainText = `Hello from AWS SES! ${new Date()}`
const html = `<h1>Hello from AWS SES!</h1> <span>${new Date()}</span>`

const ses = new SES({ apiVersion: '2010-12-01' })

const sendRawMessage = async () => {
  // Set up from_name, from_email, to, subject, message_id, plain_text, html and configuration_set variables from database or manually
  const boundary = `----=_Part${Math.random().toString().substr(2)}`

  const rawMessage = [
    `From: ${fromEmail}`, // Can be just the email as well without <>
    `To: ${to}`,
    `Subject: ${subject}`,
    `MIME-Version: 1.0`,
    // `Message-ID: <${ message_id }@eu-west-1.amazonses.com>`, // Will be replaced by SES
    // `Date: ${ formatDate( date ) }`, // Will be replaced by SES
    // `Return-Path: <${ message_id }@eu-west-1.amazonses.com>`, // Will be replaced by SES
    `Content-Type: multipart/alternative; boundary="${boundary}"`, // For sending both plaintext & html content
    // ... you can add more headers here as described in https://docs.aws.amazon.com/ses/latest/DeveloperGuide/header-fields.html
    `References: ${TOPIC_REFERENCE}`,
    `\n`,
    `--${boundary}`,
    `Content-Type: text/plain; charset=UTF-8`,
    `Content-Transfer-Encoding: 7bit`,
    `\n`,
    plainText,
    `--${boundary}`,
    `Content-Type: text/html; charset=UTF-8`,
    `Content-Transfer-Encoding: 7bit`,
    `\n`,
    html,
    `\n`,
    `--${boundary}--`,
  ]

  // Send the actual email
  return ses
    .sendRawEmail({
      Destinations: [to],
      RawMessage: {
        Data: rawMessage.join('\n'),
      },
      Source: fromEmail, // Must be verified within AWS SES
      // ConfigurationSetName: 'ConfigurationSetName', // optional AWS SES configuration set for open & click tracking
      Tags: [
        // ... optional email tags
      ],
    })
    .promise()
}

You can download sample code here

References

https://www.ietf.org/rfc/rfc0822.txt

https://www.hostknox.com/tutorials/email/headers

https://docs.aws.amazon.com/ses/latest/dg/header-fields.html

Advertisement