Entering IMAP commands using Telnet

You can use the Telnet program to enter the same commands an email client would issue to an Internet Message Access Protocol (IMAP) server, which can be helpful in troubleshooting problems related to connectivity to an IMAP server.

A telnet program is often available by default with Linux and OS X/macOS systems. On an OS X/macOS system, you can run the program from a Terminal window; the program is found in the Applications folder. On a Microsoft Windows system, you can use the free PuTTY program or you can install a Telnet client from Microsoft Windows. With a telnet client that is uses a command-line interface (CLI), you can issue the command telnet server imap where server is the fully qualified domain name (FQDN) of the IMAP server or the IP address of the server. Or you can use the well-known port for the IMAP protocol, which is TCP port 143, i.e., telnet server 143.

When you connect to the server, you should see an "OK" reply; enter the command A login username password where username is the account name for the relevant account and password is the account's password. That will verify you can log into the account. You can then enter B select INBOX which should return information about the inbox for the account followed by another "OK" response. You can issue the command C logout to logoff the IMAP server. You should see another "OK" response and be returned to the shell prompt. E.g.:

$ telnet 127.0.0.1 imap
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE START
TLS AUTH=PLAIN] Dovecot ready.
A login nell ASecretPassword
A OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT 
SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL
-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 
CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS SPEC
IAL-USE BINARY MOVE] Logged in
B select INBOX
* FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
* OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft \*)] Flags permit
ted.
* 228 EXISTS
* 21 RECENT
* OK [UNSEEN 208] First unseen.
* OK [UIDVALIDITY 1209955743] UIDs valid
* OK [UIDNEXT 99272] Predicted next UID
* OK [NOMODSEQ] No permanent modsequences
B OK [READ-WRITE] Select completed (0.416 secs).
C logout
* BYE Logging out
C OK Logout completed.
Connection closed by foreign host.
$

In the example above, I entered an incrementing alphabetical character, i.e., "A", "B", "C", before each command. You can enter a word of your choosing before each command. The server will include that word at the beginning of its response, e.g. "C OK Logout completed." If you don't include a word, or letter, preceding the IMAP command, you will see an error message stating "Unknown command" such as shown below:

select inbox
select BAD Error in IMAP command INBOX: Unknown command.

The purpose of putting a unique word before each command is to allow the client to asociate each response with the corresponding command issued by the client. A client program might issue several commands without waiting for a response, so when it gets the reponses it can associate each one with the corresponding command it issued. E.g., I could also have used "a1", "a2", "a3", etc. as in the example below:




$ telnet localhost 143
Trying ::1...
Connected to localhost.
Escape character is '^]'.
* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE START
TLS AUTH=PLAIN] Dovecot ready.
a1 login nell ASecretPassword
a1 OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT
SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND UR
L-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1
CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS SPE
CIAL-USE BINARY MOVE] Logged in
a2 select inbox
* FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
* OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft \*)] Flags permit
ted.
* 229 EXISTS
* 1 RECENT
* OK [UNSEEN 208] First unseen.
* OK [UIDVALIDITY 1209955743] UIDs valid
* OK [UIDNEXT 99273] Predicted next UID
* OK [NOMODSEQ] No permanent modsequences
a2 OK [READ-WRITE] Select completed (0.028 secs).
a3 Examine inbox
* OK [CLOSED] Previous mailbox closed.
* FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
* OK [PERMANENTFLAGS ()] Read-only mailbox.
* 229 EXISTS
* 0 RECENT
* OK [UNSEEN 208] First unseen.
* OK [UIDVALIDITY 1209955743] UIDs valid
* OK [UIDNEXT 99273] Predicted next UID
* OK [NOMODSEQ] No permanent modsequences
a3 OK [READ-ONLY] Examine completed (0.028 secs).
a4 logout
* BYE Logging out
a4 OK Logout completed.
Connection closed by foreign host.
$

In the above example, I used another command, examine which can, as with the select command, be used to obtain information on a mailbox on the server for that account.

If you want to retrieve a message from a mailbox, you can use the FETCH command. E.g., when I issue the select inbox command in the example below, I can see there are 232 messages in the user's inbox. I can use fetch 232 body to see information regarding the last message received or I can use fetch 232 body[] to view the contents of the last message received, which will show me the entire message. Or I can use Fetch 232 (BODY.PEEK[HEADER]) to view just the message header.

Udemy Generic Category (English)120x600

$ telnet localhost 143
Trying ::1...
Connected to localhost.
Escape character is '^]'.
* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE START
TLS AUTH=PLAIN] Dovecot ready.
A login nell ASecretPassword
A OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT 
SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL
-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 
CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS SPEC
IAL-USE BINARY MOVE] Logged in
B select inbox
* FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
* OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft \*)] Flags permit
ted.
* 232 EXISTS
* 0 RECENT
* OK [UNSEEN 208] First unseen.
* OK [UIDVALIDITY 1209955743] UIDs valid
* OK [UIDNEXT 99276] Predicted next UID
* OK [NOMODSEQ] No permanent modsequences
B OK [READ-WRITE] Select completed (0.028 secs).
C fetch 232 body
* 232 FETCH (BODY ("TEXT" "PLAIN" ("format" "flowed" "charset" "US-ASCII") NIL N
IL "7bit" 17 1))
C OK Fetch completed.
D fetch 232 body[]
* 232 FETCH (FLAGS (\Seen) BODY[] {723}
Return-Path: <root@example.com>
Received: from example.com (localhost [127.0.0.1])
	by example.com (8.14.7/8.14.7) with ESMTP id v6SISBnq002954
	for <nell@example.com>; Fri, 28 Jul 2017 14:28:11 -0400
Received: from localhost (root@localhost)
	by example.com (8.14.7/8.14.7/Submit) with ESMTP id v6SISBmS002950
	for <nell@example.com>; Fri, 28 Jul 2017 14:28:11 -0400
Date: Fri, 28 Jul 2017 14:28:11 -0400 (EDT)
From: root <root@example.com>
To: Nell Gwyn <nell@example.com>
Subject: Hello
Message-ID: <alpine.LRH.2.11.1707281427400.2341@example.com>
User-Agent: Alpine 2.11 (LRH 23 2013-08-11)
MIME-Version: 1.0
Content-Type: TEXT/PLAIN; format=flowed; charset=US-ASCII

A test message.
)
D OK Fetch completed.
E Fetch 232 (BODY.PEEK[HEADER])
* 232 FETCH (BODY[HEADER] {706}
Return-Path: <root@example.com>
Received: from example.com (localhost [127.0.0.1])
	by example.com (8.14.7/8.14.7) with ESMTP id v6SISBnq002954
	for <nell@example.com>; Fri, 28 Jul 2017 14:28:11 -0400
Received: from localhost (root@localhost)
	by example.com (8.14.7/8.14.7/Submit) with ESMTP id v6SISBmS002950
	for <nell@example.com>; Fri, 28 Jul 2017 14:28:11 -0400
Date: Fri, 28 Jul 2017 14:28:11 -0400 (EDT)
From: root <root@example.com>
To: Nell Gwyn <nell@example.com>
Subject: Hello
Message-ID: <alpine.LRH.2.11.1707281427400.2341@example.com>
User-Agent: Alpine 2.11 (LRH 23 2013-08-11)
MIME-Version: 1.0
Content-Type: TEXT/PLAIN; format=flowed; charset=US-ASCII

)
E OK Fetch completed.
F logout
* BYE Logging out
F OK Logout completed.
Connection closed by foreign host.
$

The following flags can be associated with a message:

\SeenMessage has been read
\AnsweredMessage has been answered
\FlaggedMessage is "flagged"for urgent/special attention
\DeletedMessage is "deleted" for removal by later EXPUNGE
\DraftMessage has not completed composition
\RecentMessage has arrived since the previous time this mailbox was selected

You can see the flags on messages using the fetch command. You can specify a range of messages to check in the form fetch start_number:end_number. E.g., if the mailbox in the examples above has 232 messages in it, I can view the flags for messages 200 through 210 with the command fetch 200:210 flags.

C fetch 200:210 FLAGS
* 200 FETCH (FLAGS (\Seen))
* 201 FETCH (FLAGS (\Seen))
* 202 FETCH (FLAGS (\Seen))
* 203 FETCH (FLAGS (\Seen))
* 204 FETCH (FLAGS (\Seen))
* 205 FETCH (FLAGS (\Seen))
* 206 FETCH (FLAGS (\Seen))
* 207 FETCH (FLAGS (\Seen))
* 208 FETCH (FLAGS ())
* 209 FETCH (FLAGS ())
* 210 FETCH (FLAGS ())
C OK Fetch completed.

From the output shown above, I can see that messages 200 through 207 have already been seen, but messages that arrived after message number 207 have not yet been seen.

References:

  1. Telnet IMAP Commands Note
    Date: November 27, 2012
    My Notes - busylog.net