RFC 788

Simple Mail Transfer Protocol

๐Ÿ“… published November 1981, from ietf

1. INTRODUCTION โœจ

okay bestie, let's get into it ๐Ÿ’… SMTP (Simple Mail Transfer Protocol) has one big goal: moving mail reliably and efficiently ๐Ÿ“ฌ๐Ÿฆ‹

SMTP doesn't care what transmission subsystem is underneath it ๐ŸŒธ all it needs is a reliable, ordered data stream channel. Appendices A, B, C, and D cover how SMTP runs over different transport services, and there's a Glossary defining the terms used in this document ๐Ÿ“–

Here's the iconic part ๐Ÿ‘‘ mail can hop across different transport service environments. A transport service gives processes an interprocess communication environment (IPCE) ๐Ÿ’œ An IPCE might cover one network, several networks, or just a subset of a network. Transport systems and IPCEs are not one-to-one with networks, so don't mix them up ๐Ÿ™ˆ Any two processes can talk directly through any IPCE they both know about ๐Ÿซถ

Mail is just one application of interprocess communication. To get mail between processes in different IPCEs, it gets relayed through a process that's connected to two (or more) IPCEs โœจ More specifically, mail can be relayed between hosts on different transport systems by a host that sits on both transport systems ๐Ÿงš Main character relay energy, no cap ๐Ÿ’–

2. THE SMTP MODEL ๐ŸŽ€

Here's the vibe of how SMTP works ๐Ÿฆ‹ When a user sends mail, the sender-SMTP sets up a full-duplex transmission channel to a receiver-SMTP โœจ The receiver-SMTP can be the final destination, or it can be an intermediate stop ๐Ÿš The sender-SMTP generates the SMTP commands and sends them to the receiver-SMTP, and the receiver-SMTP sends SMTP replies back in response to those commands ๐Ÿ’Œ

Once the channel is up, the SMTP-sender sends a MAIL command saying who the mail is from. If the SMTP-receiver can accept mail, it replies with an OK ๐Ÿ™Œ Next, the SMTP-sender sends a RCPT command naming a recipient. If the SMTP-receiver can accept mail for that person, it replies OK. If not, it rejects that one recipient, but the whole mail transaction keeps going ๐ŸŒˆ The two sides can negotiate several recipients ๐Ÿ’… Once the recipients are sorted, the SMTP-sender sends the mail data, ending it with a special sequence ๐Ÿ“จ If the SMTP-receiver processes the data successfully, it replies OK โœ… The whole dialog is purposely lock-step, one thing at a time ๐Ÿซถ


Here's the diagram, bestie ๐Ÿงš

   +----------+                +----------+
   +------+    |          |                |          |
   | User |<-->|          |      SMTP      |          |
   +------+    |  Sender- |Commands/Replies| Receiver-|
   +------+    |   SMTP   |<-------------->|    SMTP  |    +------+
   | File |<-->|          |    and Mail    |          |<-->| File |
   |System|    |          |                |          |    |System|
   +------+    +----------+                +----------+    +------+

Sender-SMTP on one side, Receiver-SMTP on the other, and that's the Model for SMTP Use (Figure 1) ๐Ÿ’–


SMTP handles mail transmission in two ways ๐Ÿš€ It can go straight from the sending user's host to the receiving user's host, when both hosts are on the same transport service ๐Ÿซถ Or it can go through one or more relay SMTP-servers, when the source and destination hosts aren't on the same transport service ๐Ÿฆ‹

To make relaying work, the SMTP-server needs to be given the name of the ultimate destination host, along with the destination mailbox name ๐ŸŽ€

The MAIL command argument is a reverse-path, which says who the mail is from โœจ The RCPT command argument is a forward-path, which says who the mail is going to ๐Ÿ’Œ The forward-path is a source route, while the reverse-path is a return route (it can be used to send a message back to the sender if something goes wrong with a relayed message) ๐Ÿ” Lowkey important stuff ๐Ÿ‘€

When one message goes to multiple recipients, SMTP encourages sending only one copy of the data for all the recipients at the same destination host ๐Ÿ“ฆ Efficiency is the goal, periodt ๐Ÿ’…

Mail commands and replies have a rigid syntax ๐Ÿ“ Replies also carry a numeric code ๐Ÿ”ข There are examples below that use real commands and replies ๐Ÿงš The complete lists of commands and replies are in Section 4 on specifications ๐Ÿ“š

Commands and replies are not case sensitive ๐ŸŒธ A command or reply word can be upper case, lower case, or any mix of the two ๐Ÿ’œ BUT this is not true of mailbox user names ๐Ÿ™ˆ For some hosts, the user name is case sensitive, so SMTP implementations must take care to preserve the case of user names as they appear in mailbox arguments โš ๏ธ Host names are not case sensitive ๐Ÿ’–

Commands and replies are made of characters from the ASCII character set [1] ๐Ÿ”ค Each 7-bit character is sent right-justified in an 8-bit byte (or octet), with the high-order bit cleared to zero ๐Ÿงฎ

When describing the general form of a command or reply, an argument (or special symbol) is written as a meta-linguistic variable (or constant), like "<string>" or "<reverse-path>" ๐ŸŽ€ The angle brackets here mark these as meta-linguistic variables ๐Ÿฆ‹ But some arguments use angle brackets literally ๐Ÿ’… For example, an actual reverse-path is wrapped in angle brackets, so "<Smith@ISIA>" is an instance of <reverse-path> (and yes, the angle brackets really get sent in the command or reply) ๐Ÿซถ

3. THE SMTP PROCEDURES ๐ŸŒˆ

This section walks through the SMTP procedures in several parts ๐Ÿงš First up is the basic mail procedure, which is a mail transaction ๐Ÿ’Œ After that come forwarding mail, verifying mailbox names and expanding mailing lists, sending to terminals instead of (or along with) mailboxes, and the opening and closing exchanges ๐Ÿ“ฎ The section wraps up with notes on relaying and a note on mail domains ๐Ÿฆ‹ You'll see examples of partial command and reply sequences throughout, and several complete scenarios are in Appendix F ๐ŸŽ€

3.1. MAIL ๐Ÿ’Œ

There are three steps to an SMTP mail transaction ๐Ÿš€ It starts with a MAIL command that gives the sender identification ๐Ÿ“จ Then one or more RCPT commands follow, giving the receiver information ๐Ÿซถ Then a DATA command brings the mail data ๐Ÿ’– And finally, the end of mail data indicator confirms the transaction โœ…

The first step is the MAIL command ๐ŸŽ€

The <reverse-path> holds the source mailbox โœจ

MAIL <SP> FROM:<reverse-path> <CRLF>

This command tells the SMTP-receiver that a new mail transaction is starting, and that it should reset all its state tables and buffers, including any recipients or mail data ๐Ÿ”„ It gives the reverse-path, which can be used to report errors ๐Ÿšจ If it's accepted, the receiver-SMTP returns a 250 OK reply ๐Ÿ™Œ

The <reverse-path> can be more than just a mailbox ๐Ÿงš It's a reverse source routing list of hosts plus the source mailbox ๐Ÿฆ‹ The first host in the <reverse-path> should be the host sending this command ๐Ÿ’…

The second step is the RCPT command ๐ŸŒธ

RCPT <SP> TO:<forward-path> <CRLF>

This command gives a forward-path that identifies one recipient ๐Ÿ’Œ If it's accepted, the receiver-SMTP returns a 250 OK reply and stores the forward-path โœ… If the recipient is unknown, the receiver-SMTP returns a 550 Failure reply ๐Ÿ˜ญ This second step can be repeated any number of times ๐Ÿ”

The <forward-path> can be more than just a mailbox ๐Ÿงš It's a source routing list of hosts plus the destination mailbox ๐Ÿฆ‹ The first host in the <forward-path> should be the host receiving this command ๐Ÿซถ

The third step is the DATA command ๐Ÿ’œ

DATA <CRLF>

If it's accepted, the receiver-SMTP returns a 354 Intermediate reply and treats all the lines that follow as the message text ๐Ÿ“ When the end of text is received and stored, the SMTP-receiver sends a 250 OK reply ๐ŸŽ‰

Since the mail data goes over the same transmission channel, the end of the mail data has to be marked so the command and reply dialog can pick back up ๐Ÿ”š SMTP marks the end by sending a line containing only a period ๐ŸŒŸ A transparency procedure stops this from messing with the user's text (see Section 4.5.2) ๐Ÿฆ‹

Part 1 of 8 is done, bestie ๐ŸŽ€ Part 2 is coming next, so stay tuned ๐Ÿ’–

Okay so the DATA step is where the mail actually shows up, bestie ๐Ÿ’Œ The mail data includes the memo header items such as Date, Subject, To, Cc, From [2]. Those headers are part of the message itself, so they travel with the body. ๐ŸŽ€

The end of mail data indicator is the moment everything gets confirmed โœจ It finishes the mail transaction and tells the receiver-SMTP to process the stored recipients and mail data now. If it's accepted, the receiver-SMTP sends back a 250 OK reply ๐Ÿ’– The DATA command should fail only if the mail transaction was incomplete (for example, no recipients), or if resources are not available. Otherwise it's a whole vibe.

The procedure above is an example of an SMTP mail transaction, and these commands must be used only in the order we just went over ๐Ÿ™ˆ Example 1 shows how they all fit together in a real transaction.

-------------------------------------------------------------

               Example of the SMTP Procedure

   This SMTP example shows mail sent by Smith at host Alpha, to
   Jones, Green, and Brown at host Beta.  Here we assume that host
   Alpha contacts host Beta directly.

      S: MAIL FROM:<Smith@Alpha>
      R: 250 OK

      S: RCPT TO:<Jones@Beta>
      R: 250 OK

      S: RCPT TO:<Green@Beta>
      R: 550 No such user here

      S: RCPT TO:<Brown@Beta>
      R: 250 OK

      S: DATA
      R: 354 Start mail input; end with <CRLF>.<CRLF>
      S: Blah blah blah...
      S: ...etc. etc. etc.
      S: <CRLF>.<CRLF>
      R: 250 OK

   The mail has now been accepted for Jones and Brown.  Green did
   not have a mailbox at host Beta.

                         Example 1

-------------------------------------------------------------

Jones and Brown got their mail, and Green did not have a mailbox at host Beta, so Green's RCPT TO got a 550 ๐Ÿ˜ญ


3.2. FORWARDING โœจ

Sometimes the destination in the <forward-path> is wrong, but the receiver-SMTP actually knows where the user really lives ๐Ÿงš In those cases, one of the following replies should be used so the sender can contact the correct destination.

251 User not local; will forward to <forward-path>

This reply means the receiver-SMTP knows the user's mailbox is on another host, and it tells the sender the correct forward-path to use from now on. Either the host, the user, or both might be different. The receiver takes responsibility for delivering the message ๐Ÿซถ

551 User not local; please try <forward-path>

This reply also means the mailbox is somewhere else, and it gives the correct forward-path. Either the host, the user, or both might be different. The receiver refuses to accept mail for this user, so the sender must either redirect the mail according to the information provided or return an error response to the originating user ๐Ÿ’…

Example 2 shows both replies in action ๐Ÿ‘‡

-------------------------------------------------------------

                   Example of Forwarding

   Either

      S: RCPT TO:<Postel@ISI>
      R: 251 User not local; will forward to <Postel@ISIF>

   Or

      S: RCPT TO:<Paul@ISIB>
      R: 551 User not local; please try <Mockapetris@ISIF>

                         Example 2

-------------------------------------------------------------

3.3. VERIFYING AND EXPANDING ๐Ÿ”

SMTP has some extra features too: commands to verify a user name or expand a mailing list. Those are the VRFY and EXPN commands, and each one takes a character string argument. For VRFY, the string is a user name. The response may include the full name of the user, and it must include the user's mailbox. For EXPN, the string identifies a mailing list. The multiline response may include the full names of the users, and it must give the mailboxes on the mailing list ๐Ÿฆ‹

Verifying a user name is pretty straightforward, as Example 3 shows.

-------------------------------------------------------------

                Example of Verifying a User Name

   Either

      S: VRFY Postel
      R: 250 Jon Postel <Postel@ISIF>

   Or

      S: VRFY Jones
      R: 550 String does not match anything.

                         Example 3

-------------------------------------------------------------

Expanding a mailing list needs a multiline reply, as Example 4 shows ๐ŸŒธ

-------------------------------------------------------------

              Example of Expanding a Mailing List

   Either

      S: EXPN Example-People
      R: 250-Jon Postel <Postel@ISIF>
      R: 250-Fred Fonebone <Fonebone@ISIQ>
      R: 250-Sam Q. Smith <SQSmith@ISIQ>
      R: 250-Quincy Smith <@ISIF,Q-Smith@ISI-VAXA>
      R: 250-<joe@foo-unix>
      R: 250 <xyz@bar-unix>

   Or

      S: EXPN Executive-Washroom-List
      R: 550 Access Denied to You.

                         Example 4

-------------------------------------------------------------

The character string arguments of VRFY and EXPN can't be restricted any further, because implementations handle user names and mailbox lists in lots of different ways ๐Ÿ™ƒ On some systems, it may make sense for the argument of EXPN to be a file name for a file holding a mailing list, but the internet has a whole variety of file naming conventions, so there's no single rule.

VRFY and EXPN are not included in the minimum implementation (Section 4.5.1), and they are not required to work across relays when they are implemented ๐ŸŽ€


3.4. SENDING AND MAILING ๐Ÿ“ฌ

The main job of SMTP is delivering messages to users' mailboxes. Some hosts also offer a similar service: delivering messages to a user's terminal, as long as that user is active on the host. Delivery to a mailbox is called "mailing", and delivery to a terminal is called "sending". In many hosts, sending and mailing are nearly identical to implement, so SMTP combines them ๐Ÿงƒ The sending commands are not included in the required minimum implementation (Section 4.5.1). Users should be able to control whether messages get written to their terminals, and most hosts let users accept or refuse those messages.

Three commands support the sending options. They're used in place of the MAIL command, and they tell the receiver-SMTP about the special semantics of the transaction:

SEND <SP> FROM:<reverse-path> <CRLF>
SOML <SP> FROM:<reverse-path> <CRLF>
SAML <SP> FROM:<reverse-path> <CRLF>

SEND requires that the mail data be delivered to the user's terminal. If the user isn't active on the host (or isn't accepting terminal messages), a 450 reply may be returned to an RCPT command. The mail transaction is successful if the message is delivered to the terminal ๐Ÿ‘€

SOML (Send Or MaiL) requires that the mail data be delivered to the user's terminal if the user is active and accepting terminal messages on the host. If the user isn't active, or isn't accepting terminal messages, the mail data goes into the user's mailbox instead. The mail transaction is successful if the message is delivered to either the terminal or the mailbox โœจ

SAML (Send And MaiL) requires that the mail data be delivered to the user's terminal if the user is active and accepting terminal messages on the host. In every case, the mail data is also entered into the user's mailbox. The mail transaction is successful if the message is delivered to the mailbox ๐Ÿ’œ

The same reply codes used for the MAIL commands are used for these commands too ๐Ÿซง


3.5. OPENING AND CLOSING ๐Ÿšช

When the transmission channel opens, there's an exchange to make sure the hosts are talking to the hosts they think they're talking to ๐Ÿค

These two commands are used to open and close the transmission channel:

HELO <SP> <host> <CRLF>
QUIT <CRLF>

With the HELO command, the sending host identifies itself. The command can be read as saying "Hello, i am <host>" ๐Ÿ‘‹

-------------------------------------------------------------

                 Example of Connection Opening

   R: 220 BBN-UNIX Simple Mail Transfer Service Ready
   S: HELO USC-ISIF
   R: 250 BBN-UNIX

                         Example 5

-------------------------------------------------------------
-------------------------------------------------------------

                 Example of Connection Closing

   S: QUIT
   R: 221 BBN-UNIX Service closing transmission channel

                         Example 6

-------------------------------------------------------------

3.6. RELAYING ๐Ÿ”

The forward-path can be a source route that looks like @ONE,@TWO,JOE@THREE, where ONE, TWO, and THREE are hosts. This form makes the difference between an address and a route really clear. The mailbox is an absolute address, and the route is just information about how to get there. The two concepts should not be mixed up ๐Ÿ—บ๏ธ

As the message is relayed from one server-SMTP to another, the elements of the forward-path move over to the reverse-path. The reverse-path is a reverse source route, meaning a source route from the message's current location back to its originator ๐Ÿ”™ When a server-SMTP removes its identifier from the forward-path and puts it into the reverse-path, it must use the name it is known by in the environment it is sending into, not the environment the mail came from. That's because a server-SMTP can be known by different names in different environments.

Using source routing, the receiver-SMTP receives mail to be relayed to another server-SMTP. The receiver-SMTP may accept or reject the relaying task the same way it accepts or rejects mail for a local user. It transforms the command arguments by moving its own identifier from the forward-path to the beginning of the reverse-path. Then it becomes a sender-SMTP, sets up a transmission channel to the next SMTP in the forward-path, and sends it the mail ๐Ÿš€

The first host in the reverse-path should be the host sending the SMTP commands, and the first host in the forward-path should be the host receiving the SMTP commands.

Heads up: the forward-path and reverse-path show up in the SMTP commands and replies, but not necessarily in the message itself. There's no need for these paths, or this syntax, to appear in the To:, From:, CC:, etc. fields of the message header ๐Ÿ’–

If a server-SMTP has accepted the relaying task, and later finds that the forward-path is incorrect or that the mail can't be delivered for whatever reason, it must construct an "undeliverable mail" notification message and send it to the originator of the undeliverable mail (as indicated by the reverse-path) ๐Ÿ’Œ

Okay so this notification message has to come from the server-SMTP at this host, obvs ๐Ÿ’… Server-SMTPs should not send notification messages about problems with notification messages ๐Ÿ™ˆ That's how you get infinite error loops, and nobody wants that. One way to stop the loops is to use a null reverse-path in the MAIL command of a notification message. When that message gets relayed, it's totally fine to leave the reverse-path null โœจ A MAIL command with a null reverse-path looks like this:

MAIL FROM:<>

An undeliverable mail notification message is shown in Example 7 ๐ŸŽ€ This one answers a message that JOE at HOSTW originated and sent via HOSTX to HOSTY, with instructions to relay it on to HOSTZ. What we see in the example is the transaction between HOSTY and HOSTX, which is the first step in getting the notification message back home ๐Ÿฆ‹

Example Undeliverable Mail Notification Message

   S: MAIL FROM:<>
   R: 250 ok
   S: RCPT TO:<@HOSTX,JOE@HOSTW>
   R: 250 ok
   S: DATA
   R: 354 send the mail data, end with .
   S: Date: 23 Oct 81
   S: Sender: SMTP@HOSTY
   S: Subject: Mail System Problem
   S:
   S:   Sorry JOE, your message to SAM@HOSTZ lost.
   S:   HOSTZ said this:
   S:    "550 No Such User"
   S: .
   R: 250 ok

Example 7 ๐Ÿงš


3.7. DOMAINS

Okay, so at some not too distant future time, it might be necessary to expand the mailbox format to include a region or name domain identifier ๐ŸŒ There's quite a bit of discussion about this right now, and it's likely that SMTP will be revised in the future to take naming domains into account. Iconic glow-up incoming ๐Ÿ’œ

The examples in this document do not show mail domains.

4. THE SMTP SPECIFICATIONS โœจ

4.1. SMTP COMMANDS ๐Ÿ’Œ

4.1.1. COMMAND SEMANTICS

The SMTP commands define the mail transfer or the mail system function that the user requests. SMTP commands are character strings terminated by <CRLF> ๐Ÿ’– The command codes themselves are alphabetic characters, terminated by <SP> if parameters follow and by <CRLF> otherwise. The syntax of mailboxes must conform to receiver site conventions. The SMTP commands are discussed below, and the SMTP replies are discussed in Section 4.2.

A mail transaction involves several data objects, and each one gets passed as an argument to a different command. The reverse-path is the argument of the MAIL command, the forward-path is the argument of the RCPT command, and the mail data is the argument of the DATA command. These arguments or data objects must be transmitted and held until the end of mail data indication confirms the transaction. The model here is that there are distinct buffers for each type of data object: a reverse-path buffer, a forward-path buffer, and a mail data buffer. Specific commands append information to a specific buffer, or clear one or more buffers ๐Ÿง 

HELLO (HELO) ๐Ÿ‘‹

This command identifies the sender-SMTP to the receiver-SMTP. The argument field contains the host name of the sender-SMTP.

The receiver-SMTP identifies itself to the sender-SMTP in the connection greeting reply, and in the response to this command.

MAIL (MAIL) ๐Ÿ“ฌ

This command starts a mail transaction in which the mail data is delivered to one or more mailboxes. The argument field contains a reverse-path.

The reverse-path consists of an optional list of hosts and the sender mailbox. When the list of hosts is present, it is a "reverse" source route and shows that the mail was relayed through each host on the list (the first host in the list was the most recent relay). This list is used as a source route to send non-delivery notices back to the sender. As each relay host adds itself to the beginning of the list, it must use its name as known in the IPCE it is relaying the mail to, rather than the IPCE the mail came from (if they're different). In some types of error reporting messages, like undeliverable mail notifications, the reverse-path may be null (see Example 7) ๐Ÿฅบ

This command clears the reverse-path buffer, the forward-path buffer, and the mail data buffer, then inserts the reverse-path information from this command into the reverse-path buffer.

RECIPIENT (RCPT) ๐ŸŽฏ

This command identifies an individual recipient of the mail data. Multiple recipients are specified by using this command multiple times.

The forward-path consists of an optional list of hosts and a required destination mailbox. When the list of hosts is present, it is a source route and shows that the mail must be relayed to the next host on the list. If the receiver-SMTP does not implement the relay function, it may use the same reply it would use for an unknown local user (550) ๐Ÿ™ƒ

When mail is relayed, the relay host must remove itself from the beginning of the forward-path and put itself at the beginning of the reverse-path. When mail reaches its ultimate destination (the forward-path contains only a destination mailbox), the receiver-SMTP inserts it into the destination mailbox according to its host mail conventions ๐Ÿ’…

For example, mail received at relay host A with these arguments:

FROM:<X@Y>
TO:<@A,@B,C@D>

will be relayed on to host B with these arguments:

FROM:<@A,X@Y>
TO:<@B,C@D>

This command appends its forward-path argument to the forward-path buffer.

DATA (DATA) ๐Ÿ“ฆ

The receiver treats the lines following this command as mail data from the sender. This command appends the mail data to the mail data buffer. The mail data may contain any of the 128 ASCII character codes ๐Ÿ”ค

The mail data ends with a line containing only a period, which is the character sequence <CRLF>.<CRLF> (see Section 4.5.2 on Transparency). This is the end of mail data indication ๐Ÿ

The end of mail data indication means the receiver must now process the stored mail transaction information. This processing uses up the information in the reverse-path buffer, the forward-path buffer, and the mail data buffer, and once this command completes, those buffers are cleared. If the processing succeeds, the receiver must send an OK reply. If the processing fails completely, the receiver must send a failure reply ๐Ÿ™Œ

When the receiver-SMTP accepts a message, either for relaying or for final delivery, it inserts a time stamp line at the beginning of the mail data. The time stamp line shows the identity of the host that sent the message, the identity of the host that received it (and is inserting this time stamp), and the date and time the message was received. Relayed messages will have multiple time stamp lines โฐ

When the receiver-SMTP makes the "final delivery" of a message, it inserts a return path line at the beginning of the mail data. The return path line keeps the information in the <reverse-path> from the MAIL command. Here, final delivery means the message leaves the SMTP world. Normally that means it has been delivered to the destination user, but in some cases it may be processed further and transmitted by another mail system ๐Ÿฆ‹

The two paragraphs above mean the final mail data will begin with a return path line, followed by one or more time stamp lines. These lines will be followed by the mail data header and body [2]. For example:

Return-Path: <@GHI,@DEF,@ABC,JOE@ABC>
Mail-From: GHI received by JKL at 27-Oct-81 15:27:39-PST
Mail-From: DEF received by GHI at 27-Oct-81 15:15:13-PST
Mail-From: ABC received by DEF at 27-Oct-81 15:01:59-PST
Date: 27-Oct-81 15:01:01-PST
From: JOE@ABC
Subject: Improved Mailing System Installed
To: SAM@JKL

This is to inform you that ...

Now for something that needs special attention ๐Ÿ‘€ The response and further action required get tricky when the processing after the end of mail data indication is only partially successful. This could happen if, after accepting several recipients and the mail data, the receiver-SMTP finds that the mail can be delivered to some of the recipients but not to others (for example, because of mailbox space allocation problems). In that situation, the response to the DATA command must be an OK reply. But the receiver-SMTP must also compose and send an "undeliverable mail" notification message to the originator of the message. Either one notification listing all of the recipients who didn't get the message, or a separate notification message for each failed recipient, must be sent (see Example 7) ๐Ÿ˜ญ All undeliverable mail notification messages are sent using the MAIL command, even if they result from processing a SEND, SOML, or SAML command ๐Ÿ“ฎ

SEND (SEND) ๐Ÿ“ฑ

This command starts a mail transaction in which the mail data is delivered to one or more terminals. The argument field contains a reverse-path. This command is successful if the message is delivered to the terminal.

The reverse-path consists of an optional list of hosts and the sender mailbox. When the list of hosts is present, it is a "reverse" source route and shows that the mail was relayed through each host on the list (the first host in the list was the most recent relay). This list is used as a source route to send non-delivery notices back to the sender.

As each relay host adds itself to the beginning of the list, it must use its name as known in the IPCE it is relaying the mail to, rather than the IPCE the mail came from (if they're different).

This command clears the reverse-path buffer, the forward-path buffer, and the mail data buffer, then inserts the reverse-path information from this command into the reverse-path buffer.

SEND OR MAIL (SOML) ๐Ÿ’ซ

4.1.2. COMMAND SYNTAX โœจ

Okay so SEND is giving "deliver it to their screen if they're online, otherwise drop it in the mailbox" ๐Ÿ’Œ The mail data goes to the recipient's terminal if they're active on the host (and accepting terminal messages), and to their mailbox otherwise. The argument field holds a reverse-path. This command only counts as successful if the message actually lands in the terminal or the mailbox ๐Ÿฆ‹

The reverse-path is an optional list of hosts plus the sender mailbox. When there's a list of hosts, it's a "reverse" source route, and it shows the mail got relayed through each host on the list (the first host on the list was the most recent relay) ๐Ÿซถ That list gets used as a source route for sending non-delivery notices back to the sender. Each relay host adds itself to the front of the list, and it has to use the name it goes by in the IPCE it's relaying to, not the IPCE the mail came from (if they're different) ๐Ÿ’…

This command wipes the reverse-path buffer, the forward-path buffer, and the mail data buffer, then puts the reverse-path info from this command into the reverse-path buffer ๐Ÿงน

SEND AND MAIL (SAML)

SAML is the glow-up of SEND ๐ŸŒŸ It also starts a mail transaction, and the mail data goes to one or more terminals and mailboxes. For each recipient, the mail goes to their terminal if they're active on the host (and accepting terminal messages), and for all recipients it goes to their mailbox. The argument field holds a reverse-path, and this command is successful if the message is delivered to the mailbox.

The reverse-path works exactly the same way it does for SEND. It's an optional list of hosts plus the sender mailbox. A list of hosts means a "reverse" source route, showing each relay host (with the most recent relay first) ๐Ÿ“ The list is used as a source route for non-delivery notices. Each relay host adds itself to the beginning of the list and uses its name as known in the IPCE it's relaying to, not the IPCE the mail came from (if they're different) ๐Ÿงš

This command also clears the reverse-path buffer, the forward-path buffer, and the mail data buffer, and then stores the reverse-path information from this command in the reverse-path buffer ๐Ÿ’œ

RESET (RSET)

RSET is the "never mind, start over" command ๐Ÿ™ˆ It says the current mail transaction gets aborted. Any stored sender, recipients, and mail data must be discarded, and all buffers and state tables get cleared. The receiver must send an OK reply, no exceptions โœจ

VERIFY (VRFY)

VRFY asks the receiver to confirm that the argument identifies a user ๐Ÿ•ต๏ธโ€โ™€๏ธ If it's a user name, the receiver returns the user's full name (if it knows it) and the fully specified mailbox. This command has no effect on the reverse-path buffer, the forward-path buffer, or the mail data buffer.

EXPAND (EXPN)

EXPN asks the receiver to confirm that the argument identifies a mailing list, and if it does, to hand back the list's membership ๐Ÿ“ฌ The full names of the users (if known) and the fully specified mailboxes come back in a multiline reply. Like VRFY, this command has no effect on the reverse-path buffer, the forward-path buffer, or the mail data buffer.

HELP (HELP)

HELP makes the receiver send helpful info back to whoever sent the HELP command ๐Ÿ†˜ The command can take an argument (like any command name) and then return more specific info as the response. It has no effect on the reverse-path buffer, the forward-path buffer, or the mail data buffer.

NOOP (NOOP)

NOOP is the chill one ๐Ÿ˜Œ It doesn't change any parameters or previously entered commands. Its only job is to make the receiver send an OK reply. It has no effect on the reverse-path buffer, the forward-path buffer, or the mail data buffer.

QUIT (QUIT)

QUIT tells the receiver it must send an OK reply, and then close the transmission channel ๐Ÿ‘‹ The receiver should not close the channel until it has received and replied to a QUIT command (even if there was an error). The sender should not close the channel until it has sent a QUIT command and received the reply (even if an earlier command got an error response) ๐Ÿซถ

If the connection closes early, the receiver should act as if an RSET command had been received, which cancels any pending transaction but doesn't undo any transaction that was already completed. The sender should act as if the command or transaction in progress got a temporary error (4xx) ๐Ÿ˜ญ

There are restrictions on the order these commands may be used in, so let's go through them ๐Ÿ—บ๏ธ

  • The first command in a session must be the HELO command. HELO can show up again later in the session too.
  • NOOP, HELP, EXPN, and VRFY can be used at any time during a session ๐ŸŒˆ
  • MAIL, SEND, SOML, or SAML begin a mail transaction. Once started, a mail transaction is made of one of those transaction-beginning commands, one or more RCPT commands, and a DATA command, in that order. A mail transaction can be aborted with RSET. There can be zero or more transactions in a session.
  • The last command in a session must be the QUIT command. QUIT can't be used at any other time in a session ๐Ÿšช

4.1.2. COMMAND SYNTAX (the syntax details)

The commands are a command code followed by an argument field. Command codes are four alphabetic characters. Upper and lower case letters get treated identically, so any of these could mean the mail command:

MAIL    Mail    mail    MaIl    mAIl

This also goes for parameter values, like "TO" or "to" for the forward-path ๐Ÿ‘€ The command code and the argument fields are separated by one or more spaces. Within the reverse-path and forward-path arguments, though, case does matter. For example, on some hosts the user "smith" is different from the user "Smith" ๐Ÿ™ƒ

The argument field is a variable-length character string that ends with the character sequence <CRLF>. The receiver takes no action until that sequence arrives. Square brackets mark an optional argument field, and if the option isn't taken, the appropriate default is implied โœจ

The SMTP commands are:

HELO <SP> <host> <CRLF>

MAIL <SP> FROM:<reverse-path> <CRLF>

RCPT <SP> TO:<forward-path> <CRLF>

DATA <CRLF>

RSET <CRLF>

SEND <SP> FROM:<reverse-path> <CRLF>

SOML <SP> FROM:<reverse-path> <CRLF>

SAML <SP> FROM:<reverse-path> <CRLF>

VRFY <SP> <string> <CRLF>

EXPN <SP> <string> <CRLF>

HELP [<SP> <string>] <CRLF>

NOOP <CRLF>

QUIT <CRLF>

The syntax of the argument fields above (in BNF notation where it applies) is below. The "..." notation means a field can be repeated one or more times ๐Ÿงฉ

<reverse-path> ::= <path>

<forward-path> ::= <path>

<path> ::= "<" ["@" <host> "," ...] <mailbox> ">"

<host> ::= <a> <string> | "#" <number> | "[" <dotnum> "]"

<mailbox> ::= <user> "@" <host>

<user> ::= <string>

<string> ::= <char> | <char> <string>

<char> ::= <c> | '\' <c> | '\' <s>

<dotnum> ::= <snum> "." <snum> "." <snum> "." <snum>

<number> ::= <d> | <d> <number>

<snum> ::= three digits representing a decimal integer value
          in the range 0 through 255

<a> ::= any one of the 52 alphabetic characters A through Z
          in upper case and a through z in lower case

<c> ::= any one of the 128 ASCII characters except
          <specials>

<d> ::= any one of the ten digits 0 through 9

<s> ::= any one of <specials>

<specials> ::= '<', '>', '(', ')', '\', ',', ';', ':', '@',
'"', and the control characters (ASCII codes 0 through 37
octal inclusive and 177 octal)

The backslash, '\', is a quote character ๐Ÿ”ช It means "the next character is to be taken literally (instead of its usual meaning)." For example, "Joe\,Smith" could be a single nine-character user field, with the comma as the fourth character of the field.

Hosts are usually known by names that get translated into addresses on each host. Sometimes a host isn't known to the translation function, and communication gets blocked ๐Ÿ˜ฉ To get past that, two numeric forms are also allowed for host "names." The first is a decimal integer with a pound sign in front, #, which means the number is the address of the host. The second is four small decimal integers separated by dots and wrapped in brackets, like "[123.255.37.2]", which means a 32-bit ARPA Internet Address written as four 8-bit fields ๐ŸŒธ

The time stamp line and the return path line are formally defined like this:

<return-path-line> ::= "Return-Path:" <SP><reverse-path><CRLF>

<time-stamp-line> ::= "Mail-From:" <SP> <stamp> <CRLF>

<stamp> ::= [<ptcl>] <from-host> <this-host> <daytime>

<ptcl> ::= <protocol> <SP> "host" <SP>

<from-host> ::= <host> <SP>

<this-host> ::= "received by" <SP> <host> <SP>

<protocol> ::= "TCP" | "NCP" | "NITS" | "X25" | "INTERNET" |
          "ARPANET"

   Note: INTERNET = TCP, ARPANET = NCP, and if the <ptcl> is
             not present INTERNET is assumed.

<daytime> ::= "at" <SP> <date> <SP> <time>

<date> ::= <dd> "-" <mon> "-" <yy>

<time> ::= <hh> ":" <mm> ":" <ss> "-" <zone>

<dd> ::= the one or two decimal integer day of the month in
          the range 1 to 31.

<mon> ::= "JAN" | "FEB" | "MAR" | "APR" | "MAY" | "JUN" |
          "JUL" | "AUG" | "SEP" | "OCT" | "NOV" | "DEC"

<yy> ::= the two decimal integer year of the century in the
          range 01 to 99.

<hh> ::= the two decimal integer hour of the day in the
          range 00 to 24.
            <mm> ::= the two decimal integer minute of the hour in the
                      range 00 to 59.

            <ss> ::= the two decimal integer second of the minute in the
                      range 00 to 59.

            <zone> ::= a time zone designator (as in [2]) or "UT" for
                      Universal Time (the default).

Okay so that's the time bits, bestie ๐Ÿ•ฐ๏ธโœจ The minutes go from 00 to 59, the seconds go from 00 to 59 too, and the zone is either a time zone designator (see [2]) or "UT" for Universal Time, which is the default ๐ŸŒ๐Ÿ’–

Here's what the return path looks like ๐Ÿ’Œ

Return-Path: <@CHARLIE,@BAKER,JOE@ABLE>

And here's the Mail From example ๐Ÿ“ฌ

Mail-From: ABC received by XYZ at 22-OCT-81 09:23:59-PDT

4.2. SMTP REPLIES ๐ŸŽ€

Okay, replies are literally how the sender and receiver stay in sync ๐Ÿซถ The whole point is to make sure the mail transfer steps happen in order, and to guarantee that the sender-SMTP always knows what state the receiver-SMTP is in. Every command must generate exactly one reply. No cap, that's the golden rule ๐Ÿ‘‘

The full command-reply flow gets spelled out in Section 5.3 on Sequencing and Section 5.4 State Diagrams, so go check those out ๐Ÿ”

An SMTP reply is a three digit number (sent as three alphanumeric characters) followed by some text ๐Ÿ’… The number is what the machines read to figure out which state to jump into next. The text is for the human user ๐Ÿงš The three digits should carry enough info that the sender-SMTP doesn't even need to read the text. It can toss the text or pass it along to the user, whatever fits ๐ŸŒธ The text might also change depending on the receiver, so you can expect different wording for each reply code, which is so relatable ๐Ÿ˜ญ The theory behind reply codes is in Appendix E, so if you're curious, go read that. Formally, a reply is defined as: a three-digit code, <SP>, one line of text, and <CRLF>, or a multiline reply (as defined in Appendix E) ๐Ÿ’œ In normal circumstances, only the EXPN and HELP command are expected to give multiline replies. Multiline replies are allowed for any command, though ๐Ÿฆ‹

4.2.1. REPLY CODES BY FUNCTION GROUPS ๐ŸŒˆ

500 Syntax error, command unrecognized
   [This may include errors such as command line too long]
501 Syntax error in parameters or arguments
502 Command not implemented
503 Bad sequence of commands
504 Command parameter not implemented

211 System status, or system help reply
214 Help message
   [Information on how to use the receiver or the meaning of a
   particular non-standard command; this reply is useful only
   to the human user]

220 <host> Service ready
221 <host> Service closing transmission channel
421 <host> Service not available, closing transmission channel
   [This may be a reply to any command if the service knows it
   must shut down]

250 Requested mail action okay, completed
251 User not local; will forward to <forward-path>
450 Requested mail action not taken: mailbox unavailable
   [E.g., mailbox busy]
550 Requested action not taken: mailbox unavailable
   [E.g., mailbox not found, no access]
451 Requested action aborted: error in processing
551 User not local; please try <forward-path>
452 Requested action not taken: insufficient system storage
552 Requested mail action aborted: exceeded storage allocation
553 Requested action not taken: mailbox name not allowed
   [E.g., mailbox syntax incorrect]
354 Start mail input; end with <CRLF>.<CRLF>
554 Transaction failed

4.2.2. NUMERIC ORDER LIST OF REPLY CODES ๐Ÿ”ข

Same codes, now lined up in numeric order, bestie ๐Ÿ’–

211 System status, or system help reply
214 Help message
   [Information on how to use the receiver or the meaning of a
   particular non-standard command; this reply is useful only
   to the human user]
220 <host> Service ready
221 <host> Service closing transmission channel
250 Requested mail action okay, completed
251 User not local; will forward to <forward-path>

354 Start mail input; end with <CRLF>.<CRLF>

421 <host> Service not available, closing transmission channel
   [This may be a reply to any command if the service knows it
   must shut down]
450 Requested mail action not taken: mailbox unavailable
   [E.g., mailbox busy]
451 Requested action aborted: local error in processing
452 Requested action not taken: insufficient system storage

500 Syntax error, command unrecognized
   [This may include errors such as command line too long]
501 Syntax error in parameters or arguments
502 Command not implemented
503 Bad sequence of commands
504 Command parameter not implemented
550 Requested action not taken: mailbox unavailable
   [E.g., mailbox not found, no access]
551 User not local; please try <forward-path>
552 Requested mail action aborted: exceeded storage allocation
553 Requested action not taken: mailbox name not allowed
   [E.g., mailbox syntax incorrect]
554 Transaction failed

4.3. SEQUENCING OF COMMANDS AND REPLIES ๐ŸŽฌ

The sender and receiver are basically having an alternating dialogue, and the sender is the one running the show ๐Ÿ‘‘ The sender issues a command, the receiver responds with a reply, and the sender must wait for that response before sending any more commands. Patience is a virtue, babe ๐Ÿ™ˆ

One super important reply is the connection greeting. Normally, the receiver sends a 220 "Awaiting input" reply once the connection is completed. The sender should wait for this greeting before sending any commands ๐Ÿซง

Note: all the greeting type replies have the official name of the server host as the first word following the reply code.

For example, a greeting looks like this:

220 <SP> USC-ISIF <SP> Service ready <CRLF>

The table below lists the alternative success and failure replies for each command. These must be strictly adhered to. A receiver can swap out the text in the replies, but the meaning and action implied by the code numbers, and by the specific command reply sequence, can't be changed ๐Ÿšซ

COMMAND-REPLY SEQUENCES ๐Ÿ“‹

Each command is listed with its possible replies. The prefixes are "P" for preliminary (not used in SMTP), "I" for intermediate, "S" for success, "F" for failure, and "E" for error. The 421 reply (service not available, closing transmission channel) may be given to any command if the SMTP-receiver knows it must shut down. This listing is the basis for the State Diagrams in Section 4.4 ๐Ÿฆ‹

CONNECTION ESTABLISHMENT
   S: 220
   F: 421
HELO
   S: 250
   E: 500, 501, 504, 421
MAIL
   S: 250
   F: 552, 451, 452
   E: 500, 501, 421

RCPT
   S: 250, 251
   F: 550, 551, 552, 553, 450, 451, 452
   E: 500, 501, 421
DATA
   I: 354 -> data -> S: 250
                     F: 552, 554, 451, 452
   F: 451, 554
   E: 500, 501, 421
RSET
   S: 250
   E: 500, 501, 504, 421
SEND
   S: 250
   F: 552, 451, 452
   E: 500, 501, 502, 421
SOML
   S: 250
   F: 552, 451, 452
   E: 500, 501, 502, 421
SAML
   S: 250
   F: 552, 451, 452
   E: 500, 501, 502, 421
VRFY
   S: 250
   F: 550
   E: 500, 501, 502, 504, 421
EXPN
   S: 250
   F: 550
   E: 500, 501, 502, 504, 421
HELP
   S: 211, 214
   E: 500, 501, 502, 504, 421
NOOP
   S: 250
   E: 500, 421
QUIT
   S: 221
   E: 500

4.4. STATE DIAGRAMS ๐Ÿ—บ๏ธ

Here come the state diagrams for a simple-minded SMTP implementation ๐Ÿง  Only the first digit of the reply codes gets used. There's one state diagram for each group of SMTP commands. The groupings came from building a model for each command, then grouping together the commands with structurally identical models ๐Ÿ’œ

For each command there are three possible outcomes: "success" (S), "failure" (F), and "error" (E). In the diagrams below, the symbol B means "begin", and the symbol W means "wait for reply" โณ

First up, the diagram that covers most of the SMTP commands ๐Ÿ’…

                            1,3    +---+
                       ----------->| E |
                      |            +---+
                      |
   +---+    cmd    +---+    2      +---+
   | B |---------->| W |---------->| S |
   +---+           +---+           +---+
                      |
                      |     4,5    +---+
                       ----------->| F |
                                   +---+

This diagram models the commands:

HELO, MAIL, RCPT, RSET, SEND, SOML, SAML, VRFY, EXPN, HELP,
NOOP, QUIT.

Next, a more complex diagram that models the DATA command ๐ŸŒ€

   +---+   DATA    +---+ 1,2                 +---+
   | B |---------->| W |-------------------->| E |
   +---+           +---+        ------------>+---+
                   3| |4,5     |
                    | |        |
      --------------   -----   |
     |                      |  |             +---+
     |               ----------     -------->| S |
     |              |       |      |         +---+
     |              |  ------------
     |              | |     |
     V           1,3| |2    |
   +---+   data    +---+     --------------->+---+
   |   |---------->| W |                     | F |
   +---+           +---+-------------------->+---+
                        4,5

Note that the "data" here is a series of lines sent from the sender to the receiver, with no response expected until the last line is sent ๐Ÿ“จ

4.5. DETAILS ๐Ÿง

4.5.1. MINIMUM IMPLEMENTATION ๐Ÿ› ๏ธ

To make SMTP workable, every receiver is required to have at least the following minimum implementation:

COMMANDS -- HELO
            MAIL
            RCPT
            DATA
            RSET
            NOOP
            QUIT

4.5.2. TRANSPARENCY ๐Ÿ™ˆ๐Ÿ”

Without some provision for data transparency, the character sequence <CRLF>.<CRLF> ends the mail text, and the user can't send it. Users usually don't know about these "forbidden" sequences. So that all user-composed text can get sent transparently, the following procedures are used ๐Ÿซถ

  1. Before sending a line of mail text, the sender-SMTP checks the first character of the line. If it is a period, one additional period is inserted at the beginning of the line.
  2. When a line of mail text is received, the receiver-SMTP checks the line. If the line is made up of a single period, it marks the end of mail. If the first character is a period and there are other characters on the line, the first character is deleted ๐Ÿ’–

The mail data can contain any of the 128 ASCII characters, and every one of them has to land in the recipient's mailbox ๐Ÿ“ฌ, format effectors and other control characters included ๐Ÿซถ. The 7-bit ASCII codes get sent right justified in 8-bit bytes (octets), with the high order bits cleared to zero ๐Ÿฆ‹.

Some systems might need to transform the data while it's being received and stored ๐Ÿ‘€. That can happen when a host's local character set isn't ASCII, or when a host stores data in records instead of strings ๐Ÿ’…. If a transform is needed, it must be reversible -- especially when the mail is being relayed ๐Ÿ”.

4.5.3. SIZES โœจ

Okay, so there are several objects with required sizes. Every implementation must be able to receive objects of at least these sizes, but it must not send objects larger than these sizes ๐Ÿ’–.

****************************************************
*                                                  *
*  TO THE MAXIMUM EXTENT POSSIBLE, IMPLEMENTATION  *
*  TECHNIQUES WHICH IMPOSE NO LIMITS ON THE LENGTH *
*  OF THESE OBJECTS SHOULD BE USED.                *
*                                                  *
****************************************************
  • user: The maximum total length of a user name is 64 characters.
  • host: The maximum total length of a host name or number is 40 characters.
  • path: The maximum total length of a reverse-path or forward-path is 256 characters (including the punctuation and element separators).
  • command line: The maximum total length of a command line including the command word and the <CRLF> is 512 characters.
  • reply line: The maximum total length of a reply line including the reply code and the <CRLF> is 512 characters.
  • text line: The maximum total length of a text line including the <CRLF> is 1000 characters (but not counting the leading dot duplicated for transparency).
  • recipients buffer: The maximum total number of recipients that must be buffered is 100 recipients.
****************************************************
*                                                  *
*  TO THE MAXIMUM EXTENT POSSIBLE, IMPLEMENTATION  *
*  TECHNIQUES WHICH IMPOSE NO LIMITS ON THE LENGTH *
*  OF THESE OBJECTS SHOULD BE USED.                *
*                                                  *
****************************************************

Errors caused by going over these limits can be reported with reply codes, like these ๐Ÿ™ˆ:

500 Line too long.

501 Path too long

552 Too many recipients.

552 Too much mail data.

APPENDIX A ๐Ÿงš

TCP Transport service

The Transmission Control Protocol [3] is used on the ARPA Internet, and on any network that follows the US DoD standards for internetwork protocols ๐ŸŒ.

Connection Establishment

The SMTP transmission channel is a TCP connection between the sender process port U and the receiver process port L. This one full duplex connection is the transmission channel ๐Ÿ”—. The protocol gets the service port 25 (31 octal), so L=25 โœจ.

Data Transfer

The TCP connection supports the transmission of 8-bit bytes. The SMTP data is 7-bit ASCII characters, and each character goes out as a 8-bit byte with the high-order bit cleared to zero ๐Ÿฉต.

APPENDIX B ๐ŸŒธ

NCP Transport service

The ARPANET Host-to-Host Protocol [4] (implemented by the Network Control Program) may be used on the ARPANET ๐Ÿ›ฐ๏ธ.

Connection Establishment

The SMTP transmission channel is set up via NCP between the the sender process socket U and receiver process socket L. The Initial Connection Protocol [5] gets followed, which gives a pair of simplex connections, and that pair is the transmission channel ๐ŸŽ€. The protocol gets the contact socket 25 (31 octal), so L=25 ๐Ÿ’œ.

Data Transfer

The NCP data connections are set up in 8-bit byte mode. The SMTP data is 7-bit ASCII characters, and each character goes out as a 8-bit byte with the high-order bit cleared to zero ๐Ÿ“.

APPENDIX C ๐Ÿฆ‹

NITS

The Network Independent Transport Service [6] may be used ๐ŸŒˆ.

Connection Establishment

The SMTP transmission channel is set up via NITS between the sender process and the receiver process. The sender process runs the CONNECT primitive, and the waiting receiver process runs the ACCEPT primitive ๐Ÿค.

Data Transfer

The NITS connection supports the transmission of 8-bit bytes. The SMTP data is 7-bit ASCII characters, and each character goes out as a 8-bit byte with the high-order bit cleared to zero โญ.

APPENDIX D ๐Ÿ’…

X.25 Transport service

It may be possible to use the X.25 service [7] straight from the Public Data Networks, but there are signs it's too error prone to count as a reliable channel ๐Ÿ˜ญ. It's suggested that a reliable end-to-end protocol such as TCP gets used on top of X.25 connections ๐Ÿซถ.

APPENDIX E โœจ

Theory of Reply Codes ๐Ÿ’–

okay so the three digits in a reply each carry their own meaning ๐ŸŽ€ The first digit tells you if the response is good, bad, or still in progress. Even a super basic sender-SMTP can figure out what to do next (move on, try again, back off, etc.) just by looking at that first digit ๐Ÿ’… If the sender wants more detail, like whether it was a mail system error or a command syntax error, it can check the second digit. The third digit is reserved for the finest-grained info ๐Ÿ”

There are five possible values for the first digit:

1yz   Positive Preliminary reply
2yz   Positive Completion reply
3yz   Positive Intermediate reply
4yz   Transient Negative Completion reply
5yz   Permanent Negative Completion reply

1yz: Positive Preliminary reply ๐ŸŒธ The command was accepted, but the action is on hold until the info in this reply gets confirmed. The sender-SMTP then sends another command saying whether to keep going or abort.

Note: SMTP doesn't have any commands that allow this type of reply, so it also doesn't have the continue or abort commands. So this one is basically a no-show in real life ๐Ÿ™ˆ

2yz: Positive Completion reply ๐ŸŽ‰ The requested action worked out perfectly. A new request can now be started.

3yz: Positive Intermediate reply ๐Ÿฆ‹ The command was accepted, but the action is paused until more info arrives. The sender-SMTP sends another command with that info. This reply is used inside command sequence groups.

4yz: Transient Negative Completion reply ๐ŸŒง๏ธ The command was not accepted and the action didn't happen. BUT the error is temporary, so the action can be requested again. The sender goes back to the start of the command sequence (if there is one). It's kinda tricky to pin down what "transient" really means when the receiver and sender sites both have to agree on it ๐Ÿค” Each reply in this group could have a different time value, but the sender-SMTP is encouraged to just try again. A handy rule of thumb for telling 4yz apart from 5yz: a reply is 4yz if you can repeat the exact same thing with no change in the command form or in the properties of the sender or receiver. (For example, the command gets repeated identically and the receiver doesn't set up a new implementation.) ๐Ÿ’œ

5yz: Permanent Negative Completion reply ๐Ÿšซ The command was not accepted and the action didn't happen. The sender-SMTP is discouraged from repeating the exact same request in the same sequence. Even some "permanent" errors can be fixed though! So a human user might tell the sender-SMTP to start the command sequence again later on, after something changes, like the spelling gets fixed or the user's account status gets updated ๐Ÿ› ๏ธ

The second digit sorts replies into specific categories:

x0z   Syntax
x1z   Information
x2z   Connections
x3z   Unspecified as yet.
x4z   Unspecified as yet.
x5z   Mail system
  • x0z: Syntax ๐Ÿ“ These cover syntax errors, commands that are syntactically correct but don't fit any functional category, and commands that are unimplemented or superfluous.
  • x1z: Information โ„น๏ธ These are replies to requests for info, like status or help.
  • x2z: Connections ๐Ÿ”Œ These replies are about the transmission channel.
  • x3z and x4z: Unspecified as yet. ๐Ÿ•ณ๏ธ Nothing's been assigned here yet.
  • x5z: Mail system ๐Ÿ“ฌ These replies show the status of the receiver's mail system in relation to the requested transfer or other mail system action.

The third digit gives a finer breakdown inside each category the second digit points to. The list of replies shows this in action ๐ŸŽ€ Each reply text is recommended, not mandatory, and it can even change depending on the command it goes with โœจ The reply codes themselves, though, have to follow the specs in this section exactly, no wiggle room ๐Ÿ’… Receiver implementations should not invent brand-new codes for situations that are a little different from the ones described here. Instead, they should adapt a code that's already defined ๐Ÿงš

For example, a command like NOOP, whose successful run doesn't give the sender-SMTP any new info, returns a 250 reply ๐Ÿ’– A 502 reply shows up when the command asks for an unimplemented, non-site-specific action. And a refinement of that is the 504 reply, for a command that is implemented but asks for an unimplemented parameter ๐ŸŒˆ

The reply text can run longer than one line. When that happens, the whole text has to be marked so the sender-SMTP knows when to stop reading ๐Ÿ“– That's where the special multi-line format comes in ๐Ÿซถ

The format for multi-line replies says that every line except the last one begins with the reply code, immediately followed by a hyphen, "-" (also known as minus), and then the text. The last line begins with the reply code, immediately followed by <SP>, then optionally some text, and then <CRLF>.

For example:

123-First line
123-Second line
123-234 text beginning with numbers
123 The last line

So the sender-SMTP just has to look for the reply code followed by <SP> at the beginning of a line, and it can ignore all the lines before that ๐Ÿฆ‹


APPENDIX F ๐Ÿงš

Scenarios ๐ŸŒธ

This section walks through complete examples of several kinds of SMTP sessions. Let's go ๐Ÿ’…

A Typical SMTP Transaction Scenario ๐Ÿ’Œ

This example shows Smith at host USC-ISIF sending mail to Jones, Green, and Brown at host BBN-UNIX. We're assuming host USC-ISIF contacts host BBN-UNIX directly ๐Ÿ“ฎ The mail gets accepted for Jones and Brown. Green doesn't have a mailbox at host BBN-UNIX, so that one bounces ๐Ÿ™ˆ

   R: 220 BBN-UNIX Simple Mail Transfer Service Ready
   S: HELO USC-ISIF
   R: 250 BBN-UNIX

   S: MAIL FROM:<Smith@USC-ISIF>
   R: 250 OK

   S: RCPT TO:<Jones@BBN-UNIX>
   R: 250 OK

   S: RCPT TO:<Green@BBN-UNIX>
   R: 550 No such user here

   S: RCPT TO:<Brown@BBN-UNIX>
   R: 250 OK

   S: DATA
   R: 354 Start mail input; end with <CRLF>.<CRLF>
   S: Blah blah blah...
   S: ...etc. etc. etc.
   S: .
   R: 250 OK

   S: QUIT
   R: 221 BBN-UNIX Service closing transmission channel

                         Scenario 1

Aborted SMTP Transaction Scenario ๐Ÿ™…โ€โ™€๏ธ

This one shows a session that gets aborted partway through ๐Ÿฅบ Smith's mail gets accepted for Jones, but Green is a no-go. So the sender uses RSET to reset the transaction and then QUITs.

   R: 220 MIT-Multics Simple Mail Transfer Service Ready
   S: HELO ISI-VAXA
   R: 250 MIT-Multics

   S: MAIL FROM:<Smith@ISI-VAXA>
   R: 250 OK

   S: RCPT TO:<Jones@MIT-Multics>
   R: 250 OK

   S: RCPT TO:<Green@MIT-Multics>
   R: 550 No such user here

   S: RSET
   R: 250 OK

   S: QUIT
   R: 221 MIT-Multics Service closing transmission channel

                         Scenario 2

Relayed Mail Scenario ๐Ÿ”

This scenario is about mail that gets passed along through a relay host on its way to the final destination ๐Ÿฆ‹ It happens in two steps.

Step 1 -- Source Host to Relay Host ๐ŸŒท

      R: 220 USC-ISIE Simple Mail Transfer Service Ready
      S: HELO MIT-AI
      R: 250 USC-ISIE

      S: MAIL FROM:<JQP@MIT-AI>
      R: 250 OK

      S: RCPT TO:<@ISIE,Jones@BBN-VAX>
      R: 250 OK

      S: DATA
      R: 354 Start mail input; end with <CRLF>.<CRLF>
      S: Date: 2-Nov-81 22:33:44
      S: From: John Q. Public <JQP at MIT-AI>
      S: Subject:  The Next Meeting of the Board
      S: To: Jones at BBN-Vax
      S:
      S: Bill:
      S: The next meeting of the board of directors will be
      S: on Tuesday.
      S:                                              John.
      S: .
      R: 250 OK

      S: QUIT
      R: 221 USC-ISIE Service closing transmission channel

Step 2 -- Relay Host to Destination Host ๐ŸŒŸ

      R: 220 BBN-VAX Simple Mail Transfer Service Ready
      S: HELO USC-ISIE
      R: 250 BBN-VAX

      S: MAIL FROM:<@ISIE,JQP@MIT-AI>
      R: 250 OK

      S: RCPT TO:<Jones@BBN-VAX>
      R: 250 OK

      S: DATA
      R: 354 Start mail input; end with <CRLF>.<CRLF>
      S: Mail-From: NCP host MIT-AI received by USC-ISIE at
         2-Nov-81 22:40:10
      S: Date: 2-Nov-81 22:33:44
      S: From: John Q. Public <JQP at MIT-AI>
      S: Subject:  The Next Meeting of the Board
      S: To: Jones at BBN-Vax
      S:
      S: Bill:
      S: The next meeting of the board of directors will be
      S: on Tuesday.
      S:                                              John.
      S: .
      R: 250 OK

      S: QUIT
      R: 221 USC-ISIE Service closing transmission channel

                         Scenario 3

Verifying and Sending Scenario ๐Ÿ”

Here the sender checks that a user exists with VRFY first, then sends the mail using SEND ๐Ÿ’ซ

   R: 220 SU-SCORE Simple Mail Transfer Service Ready
   S: HELO MIT-MC
   R: 250 SU-SCORE

   S: VRFY Crispin
   R: 250 Mark Crispin <Admin.MRC@SU-SCORE>

   S: SEND FROM:<EAK@MIT-MC>
   R: 250 OK

   S: RCPT TO:<Admin.MRC@SU-SCORE>
   R: 250 OK

   S: DATA
   R: 354 Start mail input; end with <CRLF>.<CRLF>
   S: Blah blah blah...
   S: ...etc. etc. etc.
   S: .
   R: 250 OK

   S: QUIT
   R: 221 SU-SCORE Service closing transmission channel

                         Scenario 4

Sending and Mailing Scenarios ๐Ÿ“จ

First, the user's name gets verified, and then an attempt is made to send to the user's terminal ๐Ÿ–ฅ๏ธ If that fails, the message gets mailed to the user's mailbox instead ๐Ÿ’Œ

   R: 220 SU-SCORE Simple Mail Transfer Service Ready
   S: HELO MIT-MC
   R: 250 SU-SCORE

   S: VRFY Crispin
   R: 250 Mark Crispin <Admin.MRC@SU-SCORE>

   S: SEND FROM:<EAK@MIT-MC>
   R: 250 OK

   S: RCPT TO:<Admin.MRC@SU-SCORE>
   R: 450 User not active now

   S: RSET
   R: 250 OK

   S: MAIL FROM:<EAK@MIT-MC>
   R: 250 OK

   S: RCPT TO:<Admin.MRC@SU-SCORE>
   R: 250 OK

   S: DATA
   R: 354 Start mail input; end with <CRLF>.<CRLF>
   S: Blah blah blah...
   S: ...etc. etc. etc.
   S: .
   R: 250 OK

   S: QUIT
   R: 221 SU-SCORE Service closing transmission channel

                         Scenario 5

Doing the preceding scenario more efficiently โœจ

Same vibe as before, but make it lean ๐Ÿ’…

         R: 220 SU-SCORE Simple Mail Transfer Service Ready
         S: HELO MIT-MC
         R: 250 SU-SCORE

         S: VRFY Crispin
         R: 250 Mark Crispin <Admin.MRC@SU-SCORE>

         S: SOML FROM:<EAK@MIT-MC>
         R: 250 OK

         S: RCPT TO:<Admin.MRC@SU-SCORE>
         R: 250 User not active now, so will do mail.

         S: DATA
         R: 354 Start mail input; end with <CRLF>.<CRLF>
         S: Blah blah blah...
         S: ...etc. etc. etc.
         S: .
         R: 250 OK

         S: QUIT
         R: 221 SU-SCORE Service closing transmission channel

Scenario 6


Mailing List Scenario ๐Ÿ“ฌ

So first, two mailing lists get expanded in separate sessions with different hosts. Then the message goes to everyone who showed up on either list, but no duplicates ๐Ÿ™…โ€โ™€๏ธ, via a relay host. Iconic multitasking, honestly ๐Ÿ”ฅ

Step 1 -- Expanding the First List

            R: 220 MIT-AI Simple Mail Transfer Service Ready
            S: HELO SU-SCORE
            R: 250 MIT-AI

            S: EXPN Example-People
            R: 250-<ABC@MIT-MC>
            R: 250-Fred Fonebone <Fonebone@ISIQ>
            R: 250-Xenon Y. Zither <XYZ@MIT-AI>
            R: 250-Quincy Smith <@ISIF,Q-Smith@ISI-VAXA>
            R: 250-<joe@foo-unix>
            R: 250 <xyz@bar-unix>

            S: QUIT
            R: 221 MIT-AI Service closing transmission channel

Step 2 -- Expanding the Second List

            R: 220 MIT-MC Simple Mail Transfer Service Ready
            S: HELO SU-SCORE
            R: 250 MIT-MC

            S: EXPN Interested-Parties
            R: 250-Al Calico <ABC@MIT-MC>
            R: 250-<XYZ@MIT-AI>
            R: 250-Quincy Smith <@ISIF,Q-Smith@ISI-VAXA>
            R: 250-<fred@BBN-UNIX>
            R: 250 <xyz@bar-unix>

            S: QUIT
            R: 221 MIT-MC Service closing transmission channel

Step 3 -- Mailing to All via a Relay Host

            R: 220 USC-ISIE Simple Mail Transfer Service Ready
            S: HELO SU-SCORE
            R: 250 USC-ISIE

            S: MAIL FROM:<Account.Person@SU-SCORE>
            R: 250 OK
            S: RCPT TO:<@ISIE,ABC@MIT-MC>
            R: 250 OK
            S: RCPT TO:<@ISIE,Fonebone@ISIQ>
            R: 250 OK
            S: RCPT TO:<@ISIE,XYZ@MIT-AI>
            R: 250 OK
            S: RCPT TO:<@ISIE,@ISIF,Q-Smith@ISI-VAXA>
            R: 250 OK
            S: RCPT TO:<@ISIE,joe@FOO-UNIX>
            R: 250 OK
            S: RCPT TO:<@ISIE,xyz@BAR-UNIX>
            R: 250 OK
            S: RCPT TO:<@ISIE,fred@BBN-UNIX>
            R: 250 OK

            S: DATA
            R: 354 Start mail input; end with <CRLF>.<CRLF>
            S: Blah blah blah...
            S: ...etc. etc. etc.
            S: .
            R: 250 OK

            S: QUIT
            R: 221 USC-ISIE Service closing transmission channel

Scenario 7


Forwarding Scenarios ๐Ÿฆ‹

Here the mail gets forwarded, and the server tells the sender that the user isn't local and where it's going instead ๐Ÿงš

         R: 220 USC-ISIF Simple Mail Transfer Service Ready
         S: HELO LBL-UNIX
         R: 250 USC-ISIF

         S: MAIL FROM:<mo@LBL-UNIX>
         R: 250 OK

         S: RCPT TO:<fred@USC-ISIF>
         R: 251 User not local; will forward to <Jones@USC-ISIA>

         S: DATA
         R: 354 Start mail input; end with <CRLF>.<CRLF>
         S: Blah blah blah...
         S: ...etc. etc. etc.
         S: .
         R: 250 OK

         S: QUIT
         R: 221 USC-ISIF Service closing transmission channel

Scenario 8


Step 1 -- Trying the Mailbox at the First Host

            R: 220 USC-ISIF Simple Mail Transfer Service Ready
            S: HELO LBL-UNIX
            R: 250 USC-ISIF

            S: MAIL FROM:<mo@LBL-UNIX>
            R: 250 OK

            S: RCPT TO:<fred@USC-ISIF>
            R: 251 User not local; will forward to <Jones@USC-ISIA>

            S: RSET
            R: 250 OK

            S: QUIT
            R: 221 USC-ISIF Service closing transmission channel

Step 2 -- Delivering the Mail at the Second Host

            R: 220 USC-ISIA Simple Mail Transfer Service Ready
            S: HELO LBL-UNIX
            R: 250 USC-ISIA

            S: MAIL FROM:<mo@LBL-UNIX>
            R: 250 OK

            S: RCPT TO:<Jones@USC-ISIA>
            R: OK

            S: DATA
            R: 354 Start mail input; end with <CRLF>.<CRLF>
            S: Blah blah blah...
            S: ...etc. etc. etc.
            S: .
            R: 250 OK

            S: QUIT
            R: 221 USC-ISIA Service closing transmission channel

Scenario 9


Too Many Recipients Scenario ๐Ÿ’€

Things get messy when there are too many recipients for one go, so the sender tries again in a fresh transaction ๐Ÿ™ˆ

         R: 220 BERKELEY Simple Mail Transfer Service Ready
         S: HELO USC-ISIF
         R: 250 BERKELEY

         S: MAIL FROM:<Postel@USC-ISIF>
         R: 250 OK

         S: RCPT TO:<fabry@BERKELEY>
         R: 250 OK

         S: RCPT TO:<eric@BERKELEY>
         R: 552 Recipient storage full, try again in another transaction

         S: DATA
         R: 354 Start mail input; end with <CRLF>.<CRLF>
         S: Blah blah blah...
         S: ...etc. etc. etc.
         S: .
         R: 250 OK

         S: MAIL FROM:<Postel@USC-ISIF>
         R: 250 OK

         S: RCPT TO:<eric@BERKELEY>
         R: 250 OK

         S: DATA
         R: 354 Start mail input; end with <CRLF>.<CRLF>
         S: Blah blah blah...
         S: ...etc. etc. etc.
         S: .
         R: 250 OK

         S: QUIT
         R: 221 BERKELEY Service closing transmission channel

Scenario 10


GLOSSARY ๐Ÿ“–

ASCII ๐Ÿ”ค

American Standard Code for Information Interchange [1]. The OG character set, iconic ๐Ÿ‘‘

command

A request for a mail service action sent by the sender-SMTP to the receiver-SMTP. Basically the sender asking for something โœจ

end of mail data indication

A special sequence of characters that indicates the end of the mail data. In particular, the five characters carriage return, line feed, period, carriage return, line feed, in that order. That's the signal that the message is done ๐Ÿ›‘

host

A computer in the internetwork environment on which mailboxes or SMTP processes reside. ๐Ÿ–ฅ๏ธ

line

A line of text ending with a <CRLF>.

mail data

A sequence of ASCII characters of arbitrary length, which conforms to the standard set in the Standard for the Format of ARPA Network Text Messages (RFC 733 [2]). ๐Ÿ’Œ

mailbox

A character string (address) which identifies a user to whom mail is to be sent. Mailbox normally consists of the host and user specifications. The standard mailbox naming convention is defined to be "user@host". Additionally, the "container" in which mail is stored. ๐Ÿ“ซ

receiver-SMTP process

A process which transfers mail in cooperation with a sender-SMTP process. It waits for a connection to be established via the transport service. It receives SMTP commands from the sender-SMTP, sends replies, and performs the specified operations. The listener of the whole operation ๐Ÿงโ€โ™€๏ธ

reply

A reply is an acknowledgment (positive or negative) sent from receiver to sender via the transmission channel in response to a SMTP command. The general form of a reply is a completion code (including error codes) followed by a text string. The codes are for use by programs and the text is usually intended for human users. ๐Ÿ’ฌ

sender-SMTP process

A process which transfers mail in cooperation with a receiver-SMTP process. A local language may be used in the user interface command/reply dialogue. The sender-SMTP initiates the transport service connection. It initiates SMTP commands, receives replies, and governs the transfer of mail. The one who starts the convo ๐Ÿ’…

session

The set of exchanges that occur while the transmission channel is open. ๐ŸŽ€

transaction

The set of exchanges required for one message to be transmitted for one or more recipients. ๐Ÿ“จ

transmission channel

A full-duplex communication path between a sender-SMTP and a receiver-SMTP for the exchange of commands, replies, and mail text. Two-way chat, no cap ๐Ÿซถ

transport service

Any reliable stream-oriented data communication services. For example, NCP, TCP, NITS. ๐Ÿšš

user

A human being (or a process on behalf of a human being) wishing to obtain mail transfer service. In addition, a recipient of computer mail. That's you, bestie ๐ŸŒธ

word

A sequence of printing characters.

<CRLF>

The characters carriage return and line feed (in that order).

<SP>

The space character.


REFERENCES ๐Ÿ“š

[1] ASCII

ASCII, "USA Code for Information Interchange", United States of America Standards Institute, X3.4, 1968. Also in: Feinler, E. and J. Postel, eds., "ARPANET Protocol Handbook", NIC 7104, for the Defense Communications Agency by SRI International, Menlo Park, California, Revised January 1978.

[2] RFC 733

Crocker, D., J. Vittal, K. Pogran, and D. Henderson, "Standard for the Format of ARPA Network Text Messages," RFC 733, NIC 41952, November 1977. Also in: Feinler, E. and J. Postel, eds., "ARPANET Protocol Handbook", NIC 7104, for the Defense Communications Agency by SRI International, Menlo Park, California, Revised January 1978.

[3] TCP

Postel, J., ed., "Transmission Control Protocol - DARPA Internet Program Protocol Specification", RFC 793, USC/Information Sciences Institute, September 1981.

[4] NCP

McKenzie,A., "Host/Host Protocol for the ARPA Network", NIC 8246, January 1972. Also in: Feinler, E. and J. Postel, eds., "ARPANET Protocol Handbook", NIC 7104, for the Defense Communications Agency by SRI International, Menlo Park, California, Revised January 1978.

[5] Initial Connection Protocol

Postel, J., "Official Initial Connection Protocol", NIC 7101, 11 June 1971. Also in: Feinler, E. and J. Postel, eds., "ARPANET Protocol Handbook", NIC 7104, for the Defense Communications Agency by SRI International, Menlo Park, California, Revised January 1978.

[6] NITS

PSS/SG3, "A Network Independent Transport Service", Study Group 3, The Post Office PSS Users Group, February 1980. Available from the DCPU, National Physical Laboratory, Teddington, UK.

[7] X.25

CCITT, "Recommendation X.25 - Interface Between Data Terminal Equipment (DTE) and Data Circuit-terminating Equipment (DCE) for Terminals Operating in the Packet Mode on Public Data Networks," CCITT Orange Book, Vol. VIII.2, International Telephone and Telegraph Consultative Committee, Geneva, 1976. That's the whole thing, bestie ๐ŸŒˆ๐Ÿ’–

๐Ÿ“ฆ where this page comes from