Sometimes it can be handy to connect into an IMAP(s) server to verify it is working as expected, or to view emails via a command line interface. In this example I’m connecting to a Microsoft Exchange 2016 Server with IMAP enabled, specifically IMAPS, so running on port 993.
Connect and Login
Firstly we need to connect and login:
openssl s_client -crlf -connect mail.example.org:993
Once connected, you can login. Notice the “a” at the front of the line, this is needed or you’ll get the following error: LOGIN BAD Command Error. 12
a LOGIN username password
List Folder Structure
Once you are connected, you can then view a list folders by using the following:
a LIST "" "*"
Okay, so in the list we can see our “Inbox”, it will appear like:
* LIST "INBOX/" "*"
We can see the folder structure (if there is one) within “Inbox” and we can also see that there are 31 messages in the root of the “Inbox”. Let’s have a look into it with:
a EXAMINE "INBOX/"
a OK LIST completed.
a EXAMINE INBOX
* 31 EXISTS
* FLAGS (\Seen \Answered \Flagged \Deleted \Draft $MDNSent)
* OK [PERMANENTFLAGS ()] Permanent flags
* OK [UNSEEN 23] Is the first unseen message
* OK [UIDVALIDITY 14] UIDVALIDITY value
* OK [UIDNEXT 239318] The next unique identifier value
a OK [READ-ONLY] EXAMINE completed.
So we can see that there are 31 emails in the “Inbox”.
Select and Fetch Messages
Let’s SELECT the “Inbox” with the below. EXAMINE is the same as SELECT, however the former is read-only, the latter sets the future commands to use this folder as the target.
a SELECT "INBOX/"
Let’s fetch the first 5 messages in the “Inbox”, getting the subject of these messages:
f fetch 1:5 (BODY[HEADER.FIELDS (Subject)])
Nice, so let’s get more of the header fields, to help us see all the messages, we’ll retrieve the Subject, Date and From fields, as per the below:
f fetch 1:5 (BODY[HEADER.FIELDS (Subject Date From)])
We get an output like:
From: Bob Smith <bob@domain.com>
Subject: A test message 1
Date: Fri, 21 Jun 2024 15:04:08 +0100
)
* 2 FETCH (BODY[HEADER.FIELDS (Subject Date From)] {174}
From: Bob Smith <bob@domain.com>
Date: Thu, 10 Oct 2024 13:17:51 +0000
Subject: A test message 2
[EXT]
)
* 3 FETCH (BODY[HEADER.FIELDS (Subject Date From)] {121}
From: Bob Smith <bob@domain.com>
Subject: A test message 3
Date: Wed, 16 Oct 2024 14:56:35 +0000
)
* 4 FETCH (BODY[HEADER.FIELDS (Subject Date From)] {167}
From: Bob Smith <bob@domain.com>
Subject: A test message 4
Date: Mon, 11 Nov 2024 11:02:27 +0000
)
* 5 FETCH (BODY[HEADER.FIELDS (Subject Date From)] {136}
From: Bob Smith <bob@domain.com>
Subject: A test message 5
Date: Mon, 18 Nov 2024 15:33:08 +0000
)
f OK FETCH completed.
You’ll notice that the messages are showing up in reverse date order.
One problem with using FETCH is that it marks the messages as “Seen” i.e. read. If we don’t want to do this, we can use .PEEK, such as:
f fetch 1:5 (BODY.PEEK[HEADER.FIELDS (Subject Date From)])
Read a Message
So finally, let’s open and read one of the messages, there are few bits we can do here. One thing to note is we’re reading in plain text, there is no formatting (for HTML) so we’ll see lots of seemingly superfluous information, unless of course everyone who sends you email does so in plain text! We’ll use the “.PEEK” on the end, so it doesn’t mark the message as read.
a FETCH 1 BODY.PEEK[TEXT]
a FETCH 1 BODY.PEEK[HEADER]
a FETCH 1 BODY.PEEK[]
Close/Logout Session
When you are done:
a LOGOUT