Sending Emails, with netcat

Plaintext protocol for the win!

Sending email might sound complicated—in fact it is. After years of spam fighting efforts, layers upon layers of complexity was added and Email has turned into the behemoth we are dealing with today, where most people and organization leave it to dedicated mail providers.

But that's a rant of another day. Most of the complicated black magic happens under the hood, after we have submitted our mail to the server. And the submission part, fortunately, stays pretty simple. The way you read your Email changed quite a bit (POP1 -> POP3 -> IMAP), but sending still uses SMTP, just like the 1980s. There has been extensions1, yes, but it remains to be plaintext and most of the commands remains. And since it's plaintext, let's open up netcat and send an email with just that!

Establish a connection

Information Circle
info

We will denote lines that are sent from the server with a > in the front.

First we need to establish a connection to a mail server. I'm using one of the mail server that I maintain, University of Waterloo Computer Science Club's mail server as an example. If you are happy with sending your mail in plaintext, then any netcat implementation would do. If you want some semblance of modern Internet and want encrypted communication though, we will use TLS/SSL to connect instead of STARTTLS, as the latter requires TLS handshake after inputting a SMTP command and is difficult to do with just netcat.

Warning
warning

Note that since password is transferred in Base64 on most SMTP servers, your username and password is NOT encrypted if you are using plaintext connection! SSL is strongly recommended, unless you are sitting right next to the mail server.

# For plaintext connection
# This is GNU Netcat here, but OpenBSD Netcat should work the same
$ nc mail.csclub.uwaterloo.ca 25
> 220 mail.csclub.uwaterloo.ca ESMTP Postfix

# For SSL
# ncat is bundled with Nmap, so make sure that Nmap is installed
$ ncat --ssl mail.csclub.uwaterloo.ca 465
> 220 mail.csclub.uwaterloo.ca ESMTP Postfix

And the server greets us with a happy 220, means server ready!

Say Hello!

And now it's time to say hello. We do so by sending EHLO with a hostname. The hostname is mostly used as a check when mails are sent between servers, so it's not relevant here. We will just send a loopback address.

But why is it called EHLO rather than HELO? Well actually both exists, but we will be using EHLO since that indicates we will use ESMTP 1 which supports username and password login we will be using.

Information Circle
info

More specifically, it's SASL PLAIN authentication mechanism we will be using. There actually exists LOGIN authentication mechanism, which sounds more appropriate but has actually been deprecated in favor of PLAIN. Confusing, right?

# Say hello!
EHLO 127.0.0.1
> 250-mail.csclub.uwaterloo.ca
> 250-PIPELINING
> 250-SIZE 52428800
> 250-ETRN
> 250-AUTH PLAIN
> 250-AUTH=PLAIN
> 250-ENHANCEDSTATUSCODES
> 250-8BITMIME
> 250-DSN
> 250-SMTPUTF8
> 250 CHUNKING

And the server tells us about its capabilities.

Login

Now we will provide the server with our credentials. Note that in SMTP, although the name says it's "plain auth", which may make you believe plaintext username and password are sent, they are actually combined into one string and get encoded with BASE64. To obtain the correct credential, use:

echo "$USERNAME:$PASSWORD" | base64

And now we feed the generated Base64 string into netcat.

# Tell the server we will be using PLAIN as authentication method
AUTH PLAIN
> 334
# Server says go ahead and we will go ahead and give our credential
[YOUR_COMBINED_BASE64_HERE]
> 235 2.7.0 Authentication successful

The server says we are good!

Finally, actually sending the mail

Now it's finally time to actually send the Email. First we tell the server where the mail is from and its destination:

# Tell the server which FROM address to use
MAIL FROM:<y266shen@csclub.uwaterloo.ca>
> 250 2.1.0 Ok
# And who are the recipients.
# Note that there can be multiple RCPT TO commands to indicate multiple recipients
# The To, Cc and Bcc information is actually added in the DATA field,
# which we will be typing in shortly
RCPT TO:<i@szclsya.me>
> 250 2.1.5 Ok

And finally, the mail body. SMTP will just send whatever is before the termination symbol (<CR><LF>.<CR><LF> here2) as the contents, and it doesn't care about it's plaintext or not. So to do attachments, you just concat the content of the file directly into the mail body, with some boundaries and metadata around it. But that's too complicated for a party trick with netcat, we will just send a plaintext mail here:

# Tell the server we are now sending the data portion
DATA
> 354 End data with <CR><LF>.<CR><LF>
# Type in the mail headers and body
From: [Leo Shen] <y266shen@csclub.uwaterloo.ca>
To: <i@szclsya.me>
Date: Wed, 19 Jul 2023 23:16:48 -0400
Subject: Hello from netcat

This is an email composed with `ncat --ssl mail.csclub.uwaterloo.ca 465`.

.
> 250 2.0.0 Ok: queued as 108142E003A

And the server tells us it has queued our mail in the send queue, just like a real world post office.

Now all's remaining is to Say Goodbye:

QUIT
> 221 2.0.0 Bye

Check the destination mailbox, and if everything goes okay, you've sent your Email with just netcat and your bare hands!


1

ESMTP (Extended Simple Mail Transfer Protocol), defined in RFC1869.

2

In case you didn't know, in UNIX world (popular example being Linux, macOS and *BSD) <CR><LF> represents a new line. So to input <CR><LF>.<CR><LF>, just press Enter, type ., and press Enter again.

Published on Oct 30, 2023
JS
Arrow Up