Receiving email (online)
This is a follow up (part 3) to Receiving email.
Now that the groundwork for receiving email (with SMTP) and storage email (with the Maildir format) is established, I want to see if we can actually store mail in the wild.
To run the server online, I am renting a VPS from Linode. The VPS is running Debian 13 and has the following (minimal) configuration:
| Plan | Monthly | Hourly | RAM | CPUs | Storage | Transfer | Network In/Out |
|---|---|---|---|---|---|---|---|
| Nanode 1 GB | $5 | $0.0075 | 1 GB | 1 | 25 GB | 1 TB | 40 Gbps / 1 Gbps |
This is a very lightweight, single-user experimental service so I believe this should be sufficient.
When I started up the server, I was greeted this with warning message:
SMTP ports may be restricted on this Linode. Need to send email? Review our mail server guide, then open a support ticket.
Before choosing Linode, I read through their aforementioned mail server guide which states that "outbound connections on ports 25, 465, and 587 are blocked by default… for some new accounts". Given that, at least at this time, I am only interested in in-bound traffic, I'm hoping this won't be an issue.
Now, I could simply ssh into the remote server and run the code, but I first need to make the service discoverable with DNS records, so that mail assigned to "mail.pokey.onl" can be properly routed to this VPS.
Configuring DNS records and PTR record
This comes in two parts, configured at the domain/DNS level:
- A record: maps "mail.pokey.onl" to VPS IP
- MX record: maps mail to "mail.pokey.onl"
In my case, my email-specific DNS configuration looks like this:
| Type | Host | Answer | Priority |
|---|---|---|---|
| A | mail.pokey.onl | 96.126.120.46 | |
| MX | pokey.onl | mail.pokey.onl | 10 |
I also want to configure a PTR Record at the VPS provider level. This is designed to work in the reverse direction of the A record by mapping the VPS IP to the mail server's domain name. With Akamai, I navigated to my Linode, then Network > IP Addresses > Edit RDNS > insert "mail.pokey.onl".
Testing records
After defining the routing information, I took a break to wait for the necessary propagation. Now, we can see that the records are set properly.
Using dig mail.pokey.onl (checking A record):
mail.pokey.onl. 600 IN A 96.126.120.46
Using dig MX pokey.onl (checking MX record):
pokey.onl. 600 IN MX 10 mail.pokey.onl.
Using dig -x 96.126.120.46 (checking PTR record):
46.120.126.96.in-addr.arpa. 295 IN PTR mail.pokey.onl.
Surprisingly, it was the PTR record which took the longest to propagate in my case.
Getting online
Finally, we can begin running the actual SMTP server. I transferred my files to the VPS, installed gcc through the build-essentials package, and then compiled the project.
I ran the server for the first time using the following command:
./server & echo $! > mves.pid
Then, from my laptop terminal, trying to telnet into the SMTP server (telnet mail.pokey.onl 25) gives me Trying 96.126.120.46..., but this never connects even though (on the VPS) I see the expected entry using socket statistics (ss -tulnp | grep :25).
As a result, I am fairly certain that these ports were being blocked prior to reaching my VPS. Following the warning message I received from Linode at the VPS creation, I filed a ticket to remove the SMTP port restriction early in the morning on March 27, 2026.
After less than 6 hours, my ticket was approved, but I still couldn't telnet into the server. As it turns out, the issue here was with my local machine: my home network was apparently blocked from sending on port 25, but as soon as I switched to a mobile hotspot, my requests to the server could go through.
With this setup and issues resolved, I was now able to send my first email over the internet to the email server:
% telnet mail.pokey.onl 25 Trying 96.126.120.46... Connected to mail.pokey.onl. Escape character is '^]'. 220 mail.pokey.onl Simple Mail Transfer Service Ready EHLO mail.pokey.onl 250-mail.pokey.onl greets mail.pokey.onl 250-SIZE 100000 250 VRFY MAIL FROM:<alice@pokey.onl> 250 OK RCPT TO:<bob@pokey.onl> 250 OK DATA 354 Start mail input; end with <CRLF>.<CRLF> Hello Bob, this is a test message over the internet! . 250 OK QUIT 221 mail.pokey.onl Service closing transmission channel Connection closed by foreign host.
As a result of this communication, the email server wrote "1774645958.10644.mail.pokey.onl" to "./mail/bob/Maildir/new". This is a important milestone for this project!
Here is a summary of the progress so far:
| Capability | Standard/support | Status |
|---|---|---|
| Receive mail | SMTP (RCC 5321) | Implemented |
| IMF (RFC 5322) | Supported* | |
| MIME (RFC 2045-2049) | Unimplemented | |
| Store mail | Local user accounts | Implemented (manual) |
| Maildir | Implemented | |
| Read mail | IMAP (RFC 3501) | Unimplemented |
| Send mail | SMTP Submission (RFC 6409) | Unimplemented |
| STARTTLS (RFC 3207) | Unimplemented | |
| SPF, DKIM, DMARC, TLS | Unimplemented |
*The Internet Message Format is a standard for headers and content sent within DATA of SMTP. This is supported but only as arbitrary data at this point.
Last updated March 28, 2026