Email has always mystified me technically. SMTP/IMAP/POP3 are among the most widely implemented and used communication protocols ever, yet I’ve found it difficult to follow detailed explanations of a typical email system architecture. Even operating my own server didn’t really help (given I didn’t dig into the guts). In this post I’m going to put this to bed for myself once and for all(ish).

Cast of Characters

  • Mail User Agent (MUA) - The email client (Thunderbird, Gmail, Outlook, etc).
  • Mail Submission Agent (MSA) - Pre-processes an email before transmitting it through the MTAs.
  • Mail Transfer Agent (MTA) - The MX server. Receives mail from MSAs and MTAs to forward to MTAs and MDAs respectively.
  • Mail Delivery Agent (MDA) - The IMAP or POP3 server. Stores emails in maildir or mbox format.

Whoof. Following, presumbly, the Unix philosophy, we have a separate actor for each step of the process. The email client (MUA) is easy enough to understand.

The MSA and MTA are confusing because they both receive and handle emails. The exact way they connect seems to be… flexible. An MTA can apparently perform the function of an MSA, but there are supposedly benefits to separating them. An MTA can apparently run on the same computer as the MUA rather than being a remote server (I’m wondering if this is a mistake in the wikipedia page actually and should say MSA instead). Bleargh.

So, back in the day, I’d be sitting in my cubicle at the office with my MUA, Outlook, open on my ethernet-connected Dell desktop, writing a passive-aggresive email to my department about people drinking the communal coffee without dropping a nickel in the collection cup. My employer’s IT department operates an MSA on the corporate network, which my email client connects to and hands my email. The MSA does a few things1:

  1. Make sure the user is allowed to send emails through that server.
  2. Make sure the email itself doesn’t violate any policies (forgery, sent by the authenticated user, domain greylist, etc).
  3. Virus/Spam detection.
  4. If these things don’t result in the message getting rejected, the email is queued in the corporate MTA. In practice Postfix might play both roles.

The corporate MTA will connect to the destination MTA/MX servers and deliver the message. The receiving MTA will then peform many of the same santity/security checks before finally delivering the message to the MDA, where the recipient will connect using their own MUA via IMAP or POP3.

Ack. Lots of moving pieces here. Looking at the configuration for my own email server, I appear to have configured postfix to use Mailgun as an SMTP relay rather than to send emails on its own. This is for “improved deliverability” - basically it’s super easy to get your domain name and IP addresses added to worldwide shit lists, so you can go through a specialized mail delivery provider whose servers are especially likely not to get blacklisted. So I think that in my setup Mailgun plays the role of MTA, which relays messages to the destination MTAs.

Clearing Up Ambiguity

Part of what makes this hard to understand is that we’re looking at everyone’s perspective at once. From an MUA’s perspective, all we care about are two things - talking to an MSA to send email, and talking to an MDA to fetch it. The MSA and MTA being separate is also confusing becuse both receive emails - the difference is that one receives them from a local user in order to send, and the other receives it from an external source to deliver it to a local user. Therefore messages the MSA receives are more trusted than ones the MTA receives, and can be processed differently if needed (for example with different spam detection policies).

There are multiple ports at play here as well. MSAs receive messages on port 587, while MTAs receive messages on the more well-known SMTP port, 25. SMTP is the protocol used to communicate over both ports. The client-server connection on port 587 is always secure (not actually sure this is true), whereas the server-server connection over port 25 may or may not be secure depending on what the MTAs are configured to support (I think)2. IMAP and POP3 each use different ports as well.

I seem to be forcing my own postfix relay traffic through port 587, which is traditionally the MSA port. Mailgun recommends this but I’m not sure why. Best I can tell, it would make no difference if I used 25 instead. After connecting through a VPN (because my ISP blocks outgoing traffic to port 25, lol), I can confirm that the server on port 25 does support STARTTLS. Since both client-server and server-server use SMTP as the communication protocol, I’m assuming that the exchange looks identical, and that the only difference is how much and what kind of processing is applied to the message before relaying it. If this is the case, and given it, like my own MSA, authenticates via SASL, I wonder whether it’s more like my MSA is acting like an MUA for Mailgun’s MSA. The formal boundary is in the eye of the beholder.

From what I can tell the distinction between MTA and MSA is primarily conceptual and that in practice it’s usually a single piece of software (usually postfix) that satisfies both roles. A (very) simple diagram outlining how each cast member talks to each other can be found here.

Mail Storage and Retrieval

The MDA is the easiest server-side component to understand. After the email has been bounced around however many relays (in practice probably very few) it makes it to its final destination MTA, which does spam checking and other good stuff before finally dumping the message into the recipient’s inbox. The MDA is the server responsible for the inbox. The most common email storage formats are maildir and mbox. Mbox is older, more widely supported but less flexible, while maildir is more flexible while incurring slightly more overhead. Dovecot seems to be the most popular MDA and supports both formats, so you can take your pick. Mbox seems to have some very specific advantages so if that’s what matters to you you might pick that, but it seems like maildir is generally superior. How they behave in a distributed storage setting is what really stands out to me. Mbox is just not capable of functioning in that setting. Both are stored in the filesystem, which is the crux of my architectural woes - I need distributed storage to be able to use the scaling techniques I’m familiar with. Not to mention I have take volume snapshots for backups, which are cumbersome.

To that end, dovecot supports an s3-style backend as well. I don’t know if this was an option when I first set up my server, if it was I didn’t notice it or wasn’t given the option. I’d much rather just have all the email be in s3 by default.

Other than that it seems like a pretty basic client-server setup. POP3 downloads messages from the server permanently, IMAP copies them and allows users to explicitly delete (or not). IMAP also seems to allow uploading emails directly to the inbox3. I think POP3 is probably legacy at this point.

AV and Spam Detection

My mail server uses iRedMail, which has three (four?) third-party components participating in the MSA/MTA ecosystem:

  • ClamAV (virus detection)
  • Amavis (content filtering)
  • Spamassassin (spam detection - this is actually rolled into amavis)
  • Fail2ban (spam/ip blocking)

Without these I would probably have a Very Bad Time. If I were setting everything up instead of using a kit (iRedMail) I’d have to configure all these myself. That doesn’t seem totally ridiculous given some initial cursory research.

User Auth

Postfix is clever in that it can integrate with dovecot’s user store so that sending and retrieving email are authenticated from the same user pool. Dovecot, in turn, can be configured to work with any mysql or postgres server and configured using custom queries. In the case of iRedMail, it uses an iRedMail-defined schema and then tells dovecot how to query it. This uses a framework called SASL to integrate with a variety of credential backends. Dovecot is merely one possible SASL provider.

Other components

iRedMail includes three additional pieces of software:

  • A standard webmail client.
  • MS ActiveSync/CalDAV/CardDAV software. Enables more sophisticated email clients.
  • A mailing list manager.

The first two are easy enough to understand, but the mailing list manager is different to me. It looks like the way it works is it’s part of a pipeline that postfix runs when routing mail that rewrites addresses. So it would rewrite a mailing list address to represent the recipients? At some point I’ll dig into some of the data that’s flowing through this thing to see what happens to it. But not today.

Neat Email Features

Forwarding/Aliasing

Servers can send rejections that include a forwarding address4.

I know it’s possible for me to set up gmail to send email as a user with a non-gmail MTA, and to receive email with gmail for that address. Not sure exactly how that works but it’s cool.

Relaying

MTAs can forward to each other in a chained fashion. This used to be common in order to improve reliability in the early days but not so much anymore due to spam abuse. However, in theory you could choose who relays any given sent email, which gives the user some control in balancing between mass deliverability and privacy. This is how Mailgun and other email service providers work.

Notes

Protocols are very chatty. Long-lived connections, lots of back and forth. Lots of unix-style integrations. Pipes, sockets, cronjobs. Filesystem is default storage. Very old school.

MTAs have a way of determining the credibility of the server trying to send them mail. I’ve read there are reverse DNS lookups and some other things involved. Sender Policy Framework are some words I’ve read on websites. If IP is used, then it probably needs to be static. This may have some architectural implications for scaling. I want to understand this better5 6.

In Sum

This has helped me. I think I know what all the relevant components and their responsibilities are now. Precisely how those responsibilities are accomplished is still fuzzy, but it’s more approachable. I will revisit this at some point to dig into some of the loose threads. Maybe make a diagram or two.

Until next time.