Tek's Domain

#<NTA:NnT:SSrgS:H6.6-198:W200-90.72:CBWg>

QMQP: That Other Mail Transfer Protocol

2021-06-29 4 min read Email Networking Sysadmin stuff Tech explained Teknikal_Domain Unable to load comment count

Everyone (okay, everyone this is relevant to) knows what SMTP is, the standard for mail transfer. It’s even in the name, Simple Mail Transfer Protocol, which is how mail servers have been sending mail to other mail servers since… a while. Well, fun fact, there’s another protocol that accomplishes the same goal: QMQP, the Quick Mail Queuing Protocol.

QMQP was originally built for qmail, an MTA like Postfix or Exim, but at least Postfix has also added a QMQP implementation. QMQP compliments QMTP, which, we’ll get to in a second. But, for now, know that QMQP is meant for quick client -> server email injection (that is, creating a new message), and QMTP is server -> server mail transfer.

According to my machine’s /etc/services, QMQP runs on TCP port 628, whereas QMTP runs on port 209. The protocol has very little overhead, and has the client send over the message body, the sender address, and the recipients, in that order, and the server sends back a one-byte reply (minimum) indicating status.

Format

QMQP is based on the netstring, which is a self-delimiting format for transmitting variable length byte sequences (‘strings’). For example, the string Hello world! would be encoded as:

12:Hello world!,

Thus, a netstring starts with a length (in ASCII digits), then a :, then the data, and it terminates with a , character.

A client will send over a single netstring to the server, who’s contents are three separate netstrings. For example, if I was to send the message “A simple message” from [email protected] to [email protected], then the actual protocol data sent would look like this:

64:16:A simple message,19:[email protected],17:[email protected],,

Any additional recipients (if any) are just extra netstrings, since the server knows that the first is the message, and the second is the sender, it can process the rest to be recipients.

Once this is sent, the server can respond back with a status. This starts with either K, Z, or D. K means success, and the server now accepts full responsibility for delivering the message to all recipients. Z means a temporary failure (SMTP 4xx code), and D means a permanent failure (SMTP 5xx code). The remaining bytes of the reply, if any, are a description of what happened. This isn’t parsed, and can be shown to the client.

As an example, sending a K and closing the connection means the message was successfully accepted. A response of DRelay access denied means that the message cannot be delivered, to not retry delivery, and the descriptive error message is Relay access denied.

Given how quickly netstrings can be parsed, and the overall lack of overhead in the protocol, I believe that giving it the name Quick is pretty well warranted. Note that the protocol only allows for one message per connection, and one response per message. If a server can only deliver to some but not all recipients, it needs to signal a failure. QMQP is also not equipped for authentication, and QMQP is not meant to be exposed to the outside world for any arbitrary client to inject mail.

QMTP

The counterpart to QMQP is the Quick Mail Transfer Protocol. QMTP is a bit more structured than QMQP, and has some additional features, like sending multiple messages per connection, and allowing one response per recipient not one response per message. The client sends over one or more ‘packages,’ which are the message / sender / recipients combo discussed before, and then the server sends back responses for each recipient listed. This process will continue until the client has sent all of its packages, and read all server responses, then it will close the connection.

Note there’s two major differences:

The first is that recipient list is itself a netstring, meaning that what we had before:

  • Package
    • Message
    • Sender
    • Recipient
    • Recipient…

Now looks like this:

  • Package
    • Message
    • Sender
    • Recipients
      • Recipient
      • Recipient…

And the second is that the first byte of the message is either a LF (0x0a), or a CR (0x0d). A single LF at the beginning means that the message lines are delimited with just LF characters, (UNIX format), whereas a CR at the beginning means that the message lines are separated with a CRLF pair (Windows / DOS format).

What this means is that our previous example message would look like this under QMTP:

69:17:<LF>A simple message,19:[email protected],21:17:[email protected],,,

QMTP is meant to be used to transmit mail already in the system like server-to-server SMTP does. While it also requires no authentication, normal server SMTP doesn’t either, so that’s not that big of an issue. QMTP could, in theory, be exposed to the public internet, but at this point, you’d need two agreeing servers to use it. Maybe if you had a cluster of Postfix machines you could use QMTP between them all on an intranet, and use QMQP compatible clients, but, I feel relatively comfortable marking the protocol as “basically unused in the wild.”

comments powered by Disqus