Message flows

This document explains at a high level some parts of chasquid's message processing, in particular how messages flow through the system.

Message reception

  • Client connects to chasquid on the smtp or submission ports, and issues HELO/EHLO.
  • Client optionally performs STARTTLS.
  • Client optionally performs AUTH.
    • Check that this is done over TLS.
  • Client sends MAIL FROM.
    • Check SPF.
    • Check connection security level.
  • Client sends one or more RCPT TO.
    • If the destination is remote, then the user must have authenticated.
    • If the destination is local, check that the user exists.
  • Client sends DATA.
  • Client sends actual data, and ends it with '.'
    • Run the post-data hook. If the hook fails, return an error.
    • Parse the data contents to perform loop detection.
    • Add the required headers (Received, SPF results, post-data hook output).
    • Put it in the queue and reply success.

Queue processing

Before accepting a message:

  • Create a (pseudo) random internal ID for it.
  • For each recipient, use the alias database to expand it, add the results to the list of final recipients (which may not be email).
  • Save the resulting envelope (with the final recipients) to disk.

Queue processing runs asynchronously, there's a goroutine for each message which does, in a loop:

  • For each recipient which we have not delivered yet:
    • Attempt delivery.
    • Write to disk the results.
  • If there are mails still pending, wait for some time (incrementally).
  • When all the recipients have completed delivery, or enough time has passed:
    • If all were successful, remove from the queue.
    • If some failed, send a delivery status notification back to the sender.