January 18, 2021

Easy SMTP Server With Python

Easy SMTP Server With Python

Have you ever found yourself in need of a quick SMTP server that just accepts email and doesn't ask any questions? Using the Python smtpd module, you can easily set one up on your computer without installing anything but Python! Simply launch the server like this:

python3 -m smtpd -n -c DebuggingServer localhost:8025

Congrats! You now have an SMTP server that outputs to your terminal. Let's break down what this command is doing:

  • The -m smtpd flag tells python to use the smtpd module
  • The -n flag tells python to not set the uid to nobody (required if you aren't running as root)
  • The -c DebuggingServer flag is optional and lets us set the name of the SMTP Proxy class that is instantiated (remember this is all Python!)
  • Finally, localhost:8025 tells python that this SMTP server should be bound to localhost on TCP port 8025 (We need to use a port above 1024 since we are not running as root.

Okay, now that we know what the server is doing, how do we know it is actually working? To test this server, let's whip out my favorite troubleshooting tool of all time—telnet!

Fire up a new terminal window or tab, and then open a connection to your nice and shiny new python SMTP server by entering the following on your terminal:

telnet localhost 8025

Once you type this in, you will see that the python server responds with an SMTP 220 status code. This is good and means everything is working! We now have a connection open to our SMTP server, and we can start sending SMTP commands! Now that you are connected, tell the python server who you are by sending an EHLO command and pressing enter:

EHLO localhost

The server will respond with some 250 codes that tell you what it is capable of. Now you need to set your MAIL FROM field like so:

MAIL FROM: <test@slash64.tech>

Once you press enter, you should receive a 250 OK message, and can now enter the email address that you want to send to. Note that this (just like the MAIL FROM) can be completely bogus as our SMTP server will take whatever you throw at it:

RCPT TO: <helloworld@slash64.tech>

As soon as the enter key is pressed, the python server will once again shoot back with a 250 OK, and now you are ready to set your headers by entering the DATA command and pressing enter. This results in a 354 Start Mail Input status code. Now you simply enter your email headers, which should look something like this:

From: "Telent" <test@slash64.tech>
To: "Hello World" <helloworld@slash64.tech>
Subject: Hello, World!
Date: Mon, 18 Jan 2021 20:51:00 -0600

Press enter twice to begin entering the body of the email. We'll just do a simple hello world message"

Hello, World!

Once you are done typing your message, you can end the email by typing a single period . and then hitting the enter key. You should see a 250 OK and just like that, your email has been sent! Here is a screenshot of everything that I typed in so you can get a feel for what your telnet session should look like:

Terminal window showing telnet input.

Now that the email has been sent, head on over to your terminal window that has your python mail server running. You should now be able to see the full email that you sent to your SMTP server printed to your terminal! Here is what my python SMTP server received:

Terminal window showing SMTP server output.

Here is a PCAP I took of this whole thing in case you are curious!

Thanks for sticking with this post to the end, and I hope you enjoyed it and find it useful. Let me know what you think by commenting below.

Credit to this post by Miguel Grinberg which taught me about this neat python module. Check out his blog, it is full of great Python knowledge—I have been working through his posts on Flask and have learned tons!