Talking text-based protocols
From CLUG Wiki
Contents |
Notes
Syntax for this page
Here is a conversation:
$ telnet server port S: Server says hi C: Client says hi
Secure connections
For connecting to POP3S / SMTPS / IMAPS ports, you need to use the openssl client, not telnet.
Example:
$ openssl s_client -connect server:port -crlf -quiet
SMTP
Example SMTP conversation:
SMTP is a very nice protocol to talk. It has 4-character commands and you only need to remember a handful of them.
Almost all servers even have a HELP command ;-)
The numbers at the front of each server response tell you it's status. The english bit is actually optional, only the numbers matter. Numbers beginning with 2 are success, 4 means a temporary error (i.e. full mailbox) try again later, 5 means permenant error (causes a bounce).
Here, I'm talking to a server called ixia on my local network. It will relay mail for me to anywhere.
$ telnet ixia 25 Trying 10.20.1.2... Connected to ixia.owlsbarn.rivera.za.net. Escape character is '^]'. S: 220 Owlsbarn server ready and waiting... ESMTP C: EHLO imago S: 250-Owlsbarn server ready and waiting... S: 250-PIPELINING S: 250 8BITMIME
I could have also used the HELO command. EHLO tells me what the server supports. Up to you.
You are supposed to identify yourself. Most servers don't care what you say (they use your IP address in logs anyway), but some expect a FQDN.
C: MAIL FROM: <test@example.com> S: 250 ok C: RCPT TO: <stefano@foo.bar> S: 250 ok C: RCPT TO: <stefano-cell@foo.bar> S: 250 ok
That was the envelope. I don't have to put those addresses in the header of the message, but the message will still get to them. The mail server only looks at those addresses, not the header. Note the angle brackets <> - some servers need them to be there.
C: DATA S: 354 go ahead C: From: <test@example.com> C: To: <stefano@foo.bar>, <stefano-cell@foo.bar> C: Subject: This is a test C: C: Hello there C: C: SR C: .
Data is terminated with a . on a line by itself.
S: 250 ok 1118262778 qp 18322 C: QUIT S: 221 Good bye. Connection closed by foreign host.
Done. Message winging its way.
POP3
Example SMTP conversation:
POP3 is very similar to SMTP: It has 4-character commands and you only need to remember a handful of them.
The server either replies with +OK or -ERR. Multiline responses are closed with a single .
Here, I'm talking to a GMail pop3 server over pop3s (using openssl)
$ openssl s_client -connect pop.gmail.com:pop3s -crlf -quiet S: +OK Gpop h19pf1023865rnb ready. C: USER example S: +OK send PASS C: PASS example-password S: +OK Welcome.
Some servers also let you do an APOP login. But over SSL, we don't care about secure logins...
Now, let's see what's waiting to be read:
C: STAT S: +OK 10 16286
10 messages 16286 bytes.
Can we have some more detail please?
C: LIST S: +OK 10 messages (16286 bytes) S: 1 4435 S: 2 1891 S: 3 1816 S: 4 1648 S: 5 968 S: 6 469 S: 7 1732 S: 8 1746 S: 9 852 S: 10 729 S: .
That was the message number and size of each message.
On servers which support it, each message is assigned a unique identifier which will be consistant across sessions. This command displays them:
C: UIDL S: +OK S: 1 GmailIdff726c90ed4c1a1 S: 2 GmailId101ee88d221707b5 S: 3 GmailId101fda875b72f187 S: 4 GmailId1020a6ac1997881a S: 5 GmailId1020a6e90afeb093 S: 6 GmailId102ee53f3c4e2d87 S: 7 GmailId103330fef147ed4b S: 8 GmailId10336350ede8033e S: 9 GmailId10355a2306f5a36a S: 10 GmailId1038993cffda13f6 S: .
Now lets look at just the headers of message 1: (If we wanted to see the first x lines of the message, replace 0 with x)
C: TOP 1 0 S: +OK message follows S: X-Gmail-Received: 082542631f11cb66e9a683677feeae23b2d425f4 S: Message-ID: <dd0a2bd40410070106689e1d19@mail.gmail.com> S: Date: Thu, 7 Oct 2004 01:06:18 -0700 S: From: Gmail Team <gmail-noreply@google.com> S: To: Stefano Rivera <example@gmail.com> S: Subject: Gmail is different. Here's what you need to know. S: Mime-Version: 1.0 S: Content-Type: multipart/alternative; S: boundary="----=_Part_141_22594222.1097136378333" S: Received:: by 10.54.8.63; Thu, 7 Oct 2004 01:06:18 -0700 (PDT) S: S: .
Now we download the whole message:
S: RETR 1 S: +OK message follows S: X-Gmail-Received: 082542631f11cb66e9a683677feeae23b2d425f4 S: Message-ID: <dd0a2bd40410070106689e1d19@mail.gmail.com> S: Date: Thu, 7 Oct 2004 01:06:18 -0700 S: From: Gmail Team <gmail-noreply@google.com> S: To: Stefano Rivera <example@gmail.com> etc. S: .
Junk, delete it.
S: DELE 1 S: +OK marked for deletion
We decide we made a mistake and didn't want to delete anything we deleted:
S: RSET S: +OK
We are done:
S: QUIT S: +OK Farewell.
IMAP4r1
IMAP is an immense and complex protocol with many extensions (some of which must be available on the server for clients like Outlook / Outhouse to be happy).
It allows out of order responses and pipelining. This means that before each command, you have to put in a unique identifier which ties requests to results.
Here is a short example:
C: telnet servername.domain.net imap S: * OK [CAPABILITY IMAP4REV1 LOGIN-REFERRALS STARTTLS LOGINDISABLED] servername.domain.net IMAP4rev1 2003.339 at Wed, 17 Aug 2005 12:00:20 +0200 (SAST) C: 1 CAPABILITY S: * CAPABILITY IMAP4REV1 IDLE NAMESPACE MAILBOX-REFERRALS BINARY UNSELECT SCAN SORT THREAD=REFERENCES THREAD=ORDEREDSUBJECT MULTIAPPEND LOGIN-REFERRALS STARTTLS LOGINDISABLED S: 1 OK CAPABILITY completed C: 2 LOGOUT S: * BYE servername.domain.net IMAP4rev1 server terminating connection S: 2 OK LOGOUT completed
Connection closed by foreign host.
HTTP
There are many versions of HTTP, but the simplest to talk is HTTP 1.0
HTTP is based on requests and responses. So example:
$ telnet www.example.com 80 Trying 127.0.0.1... Connected to localhost Escape character is '^]'. C: GET http://www.example.com/ HTTP/1.0 C: S: HTTP/1.1 200 OK S: Date: Wed, 21 Dec 2005 21:49:37 GMT S: Server: Apache/2.0.54 (Debian GNU/Linux) DAV/2 SVN/1.1.4 PHP/4.3.10-16 mod_ssl/2.0.54 OpenSSL/0.9.7e mod_perl/1.999.21 Perl/v5.8.4 S: X-Powered-By: PHP/4.3.10-16 S: Content-Length: 722 S: Connection: close S: Content-Type: text/html S: S: <?xml version="1.0" encoding="utf-8"?> S: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> S: <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> S: <head> S: <title>Example Web Page</title> S: <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> S: </head> S: <body> S: <p>Hi There</p> S: </body> S: </html> Connection closed by foreign host.
Here you can see I give my request containing the URL I want to receive, and terminate it with a double-enter. The server replies with two things: first the header which tells me about the document, then the document itself.
The header contains a HTTP version number and status code (note that Apache doesn't really care for HTTP/1.0). Code 200 means success. Then the server tells me a bit about itself and the file it is serving -- i.e. the file size and MIME-type. Then, after a blank line, comes the file itself, in this case some basic XHTML.
HTTP/1.1
HTTP/1.1 requires you to request with a Host header, so my example above becomes
C: GET / HTTP/1.1 C: Host: www.example.com C:
Most modern web servers will also hold the connection open for you to make more requests. If you only want to make one request, you need to tell them about that. So:
C: GET / HTTP/1.1 C: Host: www.example.com C: Connection: close C:
Of course HTTP gets far more advanced than that... Read RFC 2616 (or this nice web version of it)
