Sending multiple emails in the same thread

Sometimes you might want to send emails that should end up in the same email thread, for example, follow-up emails. Surprisingly, there is (almost) no server-side threading support. Instead, everything related to threads is handled on the client side. In this case, we would have to compose our emails in a way that would make a regular email client group these emails.

Email threads are basically linked lists, bound together by the References and Message-ID headers. So, to keep the thread, use the following:

  1. For each message in a thread, use the same subject line. You can, but you do not have to use a Re: or an Fwd: prefix. You can just keep the subject unchanged. If you change the subject line (except for the added prefix), you risk breaking the thread.
  2. Set a messageId property (which will end up as the Message-ID header in the email) yourself. Normally, EmailEngine would generate this value automatically, but for custom threads, it would probably be easier to manage those values manually. The format is "<UUID@senderdomain.com>" (including the <> symbols). You would also have to store these generated messageId values somewhere so you would know which value corresponds to which email
  3. Starting from the second email, you have to set a custom header "headers": {"references": "reflist"} where reflist is a space-separated list of all previous messageId values in the same thread.
Pay attention to the messageId format. It must be a globally unique value, and the easiest way to achieve it would be to use a UUID as the local part — for example, "<a484d2d2-9d4f-11ed-a8fc-0242ac120002@sender.com>". Originally the domain part was the local hostname. These days local hostnames mean nothing or look like long hex dumps if you are running your app in a container, so the common practice is to use the same hostname as the sender's email address.

Example

The first email in the thread sets a custom messageId and the initial subject line:

{
  "from": {"address": "sender@example.com"},
  "to": {"address": "recipient@example.com"},
  "subject": "Test message thread",
  "html": "<p>First message in thread!</p>",
  "messageId": "<first-message@example.com>"
}

The second follow-up email in the same thread sets a messageId and headers.references that includes the messageId value we are trying to follow up to:

{
  "from": {"address": "sender@example.com"},
  "to": {"address": "recipient@example.com"},
  "subject": "Test message thread",
  "html": "<p>Second message in thread!</p>",
  "messageId": "<second-message@example.com>",
  "headers": {
    "references": "<first-message@example.com>"
  }
}

For the third email, the references value would look like this:

"references": "<first-message@example.com> <second-message@example.com>"

This would nicely group all our follow-up emails in a single thread for most email clients.