
This blog is about self-hosting things. I have written several articles about running on your own server what other people rent you by the month.
This one is about the single piece I recommend you do not self-host.
That is not a contradiction, it is what the numbers say. Standing up a mail server is the easy part: apt install postfix and ten minutes later you have one running. The problem is that running and delivering are two different things, and your server has very little say in the second one.
And it is not just me saying so. The company that sells you the server you would run it on says it in writing:
«We strongly recommend against running your own mail server, as self-hosted mail servers are difficult to secure and maintain, are frequently flagged as spam, and require constant monitoring.»
DigitalOcean documentation, checked in July 2026
By the end of this article you will have SMTP2GO connected, running for free and with tracking switched off. But first it is worth understanding what we are up against, because it decides everything else.
Why your own mail server does not deliver

Port 25 is closed, and it is not your provider being awkward
Server-to-server mail travels over port 25. Almost no cloud provider will let you use it outbound:
| Provider | Outbound port 25 | How you get it opened |
|---|---|---|
| AWS EC2 | Blocked | A form, roughly 48 hours, and per region |
| Google Cloud | Blocked | Only lifted once they consider the project low risk |
| Azure | Blocked except on EA or MCA-E contracts | Exemption by contract type |
| DigitalOcean | Blocked, and 465 and 587 too | No documented process |
| Hetzner Cloud | 25 and 465 blocked | After a month and your first paid invoice |
| Vultr | Blocked on new instances | A ticket, and they warn they cannot promise it |
| Oracle Cloud | Blocked since June 2021 | A limit increase request |
At home it is worse, because your ISP almost certainly blocks it as well. One thing worth getting right: RFC 5068 does not recommend blocking port 25, it explicitly declares itself neutral. The recommendation comes from M3AAWG, the industry association. What the RFC does require: providers may not block port 587 on you.
Your IP has no history, and that costs you
Google and Microsoft have never seen your IP address. Before anyone trusts it you have to warm it up, sending little and ramping slowly. Amazon puts that at two to six weeks depending on the receiving provider.
For a sense of how seriously the people who do this for a living take it, look at SendGrid’s warm-up schedule: they start at twenty emails an hour and do not reach 211 until a week later. A freshly installed Postfix does exactly the opposite: it sends everything you throw at it from the first second.
And there are lists that include you without you doing anything wrong
Spamhaus’ Policy Blocklist covers more than 1.4 billion IPv4 addresses, close to 40% of the routable space. They clear up the misunderstanding themselves: «IPs in this set are not necessarily bad; they simply should not be sending email». If your provider declared that range as non-sending, you are in it before you have sent a thing.
UCEPROTECT is worse: its level 3 lists entire autonomous systems. They admit it without flinching: «may, and probably will, cause collateral damage to innocent users». And the same people sell delisting by subscription through another site. Your neighbour in the IP range decides your deliverability.
If you follow a tutorial telling you to put reject_rbl_client dnsbl.sorbs.net in your Postfix, that tutorial has been out of date for two years: SORBS shut down on 5 June 2024 and its zones are empty.
The alternative: a relay, and why the free tier is plenty
A transactional mail relay is a service that takes your messages over SMTP and delivers them from its own IPs, which have years of reputation behind them and teams paid to keep it that way. You skip all four problems at once.
The interesting part is that transactional mail from an internal service is a tiny volume. Signups, password resets, notifications that somebody shared something. For a team of fifteen that is dozens of emails a month, not thousands. It fits inside any free tier with room to spare.
These are the August 2026 numbers, taken from each provider’s own pricing page:
| Provider | Free tier | Card required | Log retention | Catch |
|---|---|---|---|---|
| SMTP2GO | 1,000/month, 200/day | No | 5 days | Five sender domains |
| Mailgun | 3,000/month | No | 1 day | One sender domain |
| Elastic Email | 3,000/month, 100/day | No | Limited | Their branding on the footer |
| Resend | 3,000/month, 100/day | No | 3 days | Has SMTP, but no SMTP logs to debug with |
| Brevo | 300/day | No | Limited | Their branding on the footer |
| SendGrid | Gone | Yes | N/A | 60-day trial only |
| Amazon SES | Gone for new accounts | Yes | N/A | Sandbox until approved |
The last two rows need a warning, because most comparisons you will find still recommend them:
- SendGrid announced the end of its free plan on 27 May 2025 and gave sixty days’ notice: «email sending will be paused for accounts on all free plans». The cutoff landed on 26 July. Today there is only a 60-day trial.
- Amazon SES retired its free tier on 21 July 2026, three weeks ago, for new customers. If you come across the figure of 62,000 emails a month, that is from an era that ended in 2023. You now go in through generic AWS credits. And watch out for the sandbox, which is still very much there: until they approve you, you can only send to verified addresses, 200 messages per 24 hours.
The rest of this article being about SMTP2GO does not mean it is the best one. Several in that table are fine, and the choice depends on your situation: Mailgun gives you triple the volume, so does Elastic Email, and none of the three asks for a card. I use SMTP2GO because the signup is one of the simplest to write up, and because the procedure is nearly identical everywhere: verify the domain with a couple of DNS records, get the credentials, put them in your application. If you follow this article with a different provider, you will recognise every step.
That said, two things about it I do like, and that are worth checking on whichever one you pick. It allows five sender domains instead of one, and it keeps five days of logs instead of one. That second one matters more than it sounds: when somebody tells you on Monday that they never got Friday’s invitation, one day of history leaves you nothing to look at.
And one detail about its limits, which behave differently from each other: go over the daily cap and mail is queued and goes out later. Go over the monthly one and it is rejected and lost.
Would you rather I set one of the others up? Leave me a comment and I will write that one.
Signing up, step by step
Let us do the practical part first, which is ten minutes. Afterwards I explain why what you are about to build works, which is what actually helps you the day something does not arrive.

Once you have confirmed your email, the first thing is to register the domain you will send from. There is a decision here worth understanding:

For an internal service you want a sender domain, so you can use passbolt@, uptime@ or whatever else without coming back here. The free plan allows five.


A minute later the records are in place:

The third record: the one I delete

The link CNAME exists so SMTP2GO can rewrite every link in your emails and route them through its tracking system to count clicks. It is the same mechanism marketing tools use, and for that it is fine. For an internal service’s notifications, I have three reasons not to create it.
One: it can burn your single-use links
This is the serious one, and it is not about deliverability but about things simply working.
Corporate filters open the links in your emails before delivering them. Microsoft Safe Links documents it plainly: «URLs are scanned prior to message delivery». Barracuda, Proofpoint and Mimecast do the same.
Now think about what a signup or password reset link is: it only works once. If a scanner visits it before the person does, it is already used. This is not theory, it is documented by the identity vendors themselves: NextAuth has a whole page about the problem and describes it without ambiguity, «effectively consuming it». Supabase warns about the same thing and names Safe Links. Auth0 recommends using codes instead of links outright.
Adding a tracking domain that rewrites every link means putting one more hop on a path that is fragile already. I do not do it.

Two: the number that justifies tracking is not reliable any more
Open tracking works with a transparent one-pixel image. Since iOS 15, Apple’s Mail Privacy Protection downloads that remote content «upon receipt of the message rather than when viewing it». Which means the pixel fires whether or not anybody opened anything. Gmail, for its part, has served images through its own proxy since 2013, so the IP and browser you record are not your user’s.
The definitive line comes from Google itself, in its sender guidelines: «Google does not track open rates», adding that low opens «are not necessarily a reliable indicator of delivery problems».
Three: shared tracking domains end up blocked
When tracking runs through a shared domain, you share its reputation too. Netcraft documented a phishing campaign built on a large provider’s click tracking, with at least nine customer accounts compromised. Spamhaus has a specific code for this in its domain list: 127.0.1.103, «abused redirector domain».
And there is a fourth reason that is no longer technical: in 2026 both the Italian and the French data protection authorities published guidance requiring prior consent for tracking pixels. The French one does explicitly exempt transactional mail tied to a service the user asked for. Which is exactly our case, but better not to have the argument at all.
How to remove it
You delete it from your own DNS, not from SMTP2GO:


And now the part that had to be checked, because theory is one thing and the provider not getting upset is another. Back to SMTP2GO, hit verify again, and this is what comes out:

The domain stays verified, mail keeps going out authenticated, and the panel simply marks tracking as disabled. No drama.
Checking it came out right
Before connecting anything, check the DNS looks the way you want it: the two authentication records resolving, and the tracking one resolving nothing at all. Swap the identifier for yours, which is the one SMTP2GO gave you:
# The bounce one: has to return return.smtp2go.net
dig +short em799236.itrafa.com CNAME
# The DKIM one: has to return a key, not an empty line
dig +short s799236._domainkey.itrafa.com TXT
# And the tracking one must return NOTHING
dig +short link.itrafa.com CNAME
dig commands are real, run against itrafa.com’s DNS. Two in place and one gone.If the first one does not return return.smtp2go.net., or the second does not return a key, the record is mistyped or DNS has not propagated yet. If the third returns anything, the tracking one is still alive. And with all three like that, it is time to understand why this works without touching anything else on your domain.
Why you never touch your domain’s SPF or DMARC
You have the three records in place and checked. Here is what they do, and why nothing else needs changing.
Every email carries two senders. The From: header, which is the one your user sees, and the envelope sender, the MAIL FROM, which travels in the Return-Path and only servers ever see. SPF validates the envelope one, not the one your user sees: RFC 7208 is explicit about it and advises against checking other identities.
The first CNAME puts that envelope in your name. By creating em799236.yourdomain.com pointing at return.smtp2go.net, the receiver checks SPF against your subdomain and, following the CNAME, ends up reading SMTP2GO’s record. Your root SPF never comes into it, which is why it can stay on -all with only Microsoft 365 inside.
DMARC adds one more condition: the domain SPF validated has to align with the one in the From:. In relaxed mode, which is the default (aspf=r), sharing an organisational domain is enough, and em799236.yourdomain.com and yourdomain.com do. The second CNAME does the same job on the DKIM side: the signature goes out with d=yourdomain.com. As long as one of the two aligns, DMARC passes the message, so your policy can stay at p=reject untouched.

Put another way: the relay’s messages authenticate using records that hang off your domain but whose contents SMTP2GO maintains. You publish two pointers and they handle the rest, key rotation included.
Do not add SMTP2GO to your SPF record. Besides being unnecessary, it is risky: SPF has a hard limit of ten DNS lookups and Microsoft 365 already spends several. Going over does not fail «a bit», it returns
permerror, and that does not take down the relay’s mail: it takes down SPF for your entire domain, corporate mail included.
One note for anyone going to look things up: DMARC changed specification in 2026. RFC 7489 is obsolete, and where there was one document there are now three: RFC 9989, which also obsoletes 9091, plus RFC 9990 for aggregate reports and RFC 9991 for failure reports. The change most likely to affect you: the pct= tag is gone, which was the standard way to roll DMARC out gradually. In its place comes t=, the test mode, and the underlying change is that there is no percentage rollout any more: either you apply the policy or you do not. You still scope with sp= and np=.
The four details you are going to need
The DNS records authenticate your domain, but they are not what you send with. For that you need credentials, and they live somewhere not entirely obvious: in the SMTP2GO panel, under Sending → SMTP Users.
You create a user there and the service hands you a password. That gives you the four details:

| Detail | Value |
|---|---|
| Server | mail.smtp2go.com |
| Port | 587. If your network blocks it, 2525. With implicit TLS: 465 |
| Username | The one you created under SMTP Users |
| Password | The one it generated for you right there |

And mind the password, because this is the moment. SMTP2GO shows it in the clear here and only here. Copy it into your password manager before you leave this screen. If you lose it there is no recovery, it generates a new one, and that means touching the configuration of everything that was already sending with the old one.
All eight ports, and which one to actually use
The panel gives you a list of eight ports. I checked them one by one before writing this: all eight accept connections, all eight negotiate TLS 1.3, and on all eight I got as far as authenticating, cutting the conversation before sending anything. You can verify the encryption yourself with this:

The port number does not decide the encryption, the protocol does. On 25, 587, 2525, 80 and 8025 the session starts in the clear and upgrades to TLS with STARTTLS. On 465, 443 and 8465 it is encrypted from the first byte, with no preceding phase. Which is why all eight come back with TLS 1.3 up there: 2525 is not «the unencrypted port», it is a 587 with a different number.
That said, they are not fully interchangeable, and the criteria are these:
- 587, by default. It is the port registered with IANA for mail submission (RFC 6409) and absolutely everything understands it. If your network lets it out, look no further.
- 465, if your client supports it. Encrypted from the first byte, so there is no cleartext phase for someone in the middle to strip and leave the session unencrypted. RFC 8314 recommends it for that reason.
- 2525, only if the others are blocked. It is not registered with IANA for anything: it is an industry convention, and it works precisely because it does not show up on the usual blocklists.
- 443, as a last resort. On a network that filters everything, this is the hardest one to spot: from the outside it is indistinguishable from an HTTPS connection.
And remember the first section: the one blocking port 25 is your provider, not SMTP2GO. Them having eight ports open does not mean you can get out through all eight.
Check this before you configure anything
This takes thirty seconds and saves you an entire afternoon. Before touching the application, find out which ports the server you are installing it on can actually get out through. If the one you picked is filtered, you will not find out from a clear error message: you will find out because nothing arrives, and you will start checking the password, which was fine.
No need to install nc or telnet. /dev/tcp is a redirection built into bash itself and it is always there:
for p in 25 587 2525 465; do
if timeout 5 bash -c "</dev/tcp/mail.smtp2go.com/$p" 2>/dev/null; then
echo " $p open"
else
echo " $p BLOCKED"
fi
done
BLOCKED.It reads itself: if it answers instantly, that port gets out. If it takes the whole five seconds and says BLOCKED, that port is filtered and there is nothing to configure there, you either ask for it to be opened or use another one. And if everything comes back blocked, check whether your outbound firewall is allowlist-based, which is more common than you would think on corporate networks.
Three settings on the form, and one costs you half your quota
The signup goes through without touching any of these three. They are worth a look anyway.
Set a sending limit, even if you do not need one
The form has a Rate Limit field, and it comes with Use default ticked, which on a new account means unlimited. Untick it and put a number in.
Which number: look at what that service actually sends and multiply by five. If your site sends twenty notifications a day, set it to a hundred. It will never get in your way in normal use, and the day a runaway loop fires at three in the morning, it stops there instead of eating the month’s thousand emails. A cap is not a restriction, it is a fault detector that also stops the fault.
Turn tracking off here as well
Further up I explained why I delete the third CNAME, the tracking one. As it turns out, the switches also live on each user, under the Tracking & Status tab. Turning Open Tracking and Click Tracking off here is belt as well as braces, and it is what makes your links go out exactly as you wrote them.

The audit copy doubles what you use
Under Advanced there is an option that looks like a gift: Email Auditing, which blind-copies everything you send to whatever address you give it. Sounds like a safety net. But read the small print, which is right there: those copies count towards your monthly quota. Meaning you switch it on and go from 1,000 emails to 500 real ones.
Next to it is Bounce Notifications, which is worth switching on: it emails you every time a message bounces. That is the difference between finding out the next day and finding out in August.

One per service, not one for everything
Last decision, and the one you thank yourself for most over time. You can create several SMTP users at no cost, so create one for each thing that sends and give it a description that means something: website, backups, Uptime Kuma.
The reason is containment, and it fits with the cap above. An SMTP credential lives in the clear in the config file of every service that uses it: in wp-config, in docker-compose, in the backup script. Anyone who can read that file walks away with it. And with that credential they cannot just send: they can send as your domain, signed and aligned, which is exactly what we have spent half an afternoon setting up.
With one shared credential, that day means rotating it and reconfiguring everything that sends mail on your network at once, while the rest stays broken. With one per service, you revoke that one and you are done. And if each carries its own cap, whoever walks off with one cannot go past that number: the damage has a ceiling before you even find out. As a side effect, the activity log tells you which user sent what, so «who sent this?» has an answer.

Send a test email before touching your application
This step saves you the pointless afternoons. Do it and you know for certain whether the problem is in the relay or in your application’s configuration, instead of guessing.
curl speaks SMTP, so there is nothing else to install. Swap in your credentials and your address:
curl --url 'smtp://mail.smtp2go.com:587' --ssl-reqd \
--user 'YOUR_USERNAME:YOUR_PASSWORD' \
--mail-from '[email protected]' \
--mail-rcpt '[email protected]' \
--upload-file - <<'EOF'
From: Alerts <[email protected]>
To: [email protected]
Subject: SMTP2GO test
If you are reading this, the relay works.
EOF
curl prints nothing at all when it works: the confirmation is the 0.The --ssl-reqd is not decoration: it forces the connection to be encrypted and fails if the server does not offer it. Without it, curl would send your credentials in the clear if something went wrong.
If the message arrives, the relay is fine and whatever is left to sort out is in your application. If it does not, check the log under Reports → Activity in the panel: it shows you whether the message went out, whether it bounced and why. Remember that on the free plan that history lasts five days.
And while you have it in front of you, open it and hit Show original. Those are the three lines that close the loop: if SPF, DKIM and DMARC all say PASS, the records you set up are doing their job. If DKIM passes but with a domain that is not yours, the second CNAME is wrong. And if DMARC fails while the other two say PASS, that is an alignment problem, which is what the previous section explains.
If your domain already uses Microsoft 365 or Google Workspace
This is the situation of almost any small company, and the scariest one: you already have corporate mail working and you do not want to break it by adding a relay for four notifications.
You are not going to break it, and you do not have to touch anything you already have. I checked it on a live domain sending through Microsoft 365, with SPF ending in -all and DMARC at p=reject, which is the strictest configuration available. SMTP2GO’s mail goes through regardless, for the reason you saw in the alignment section.
The one thing worth being careful about is the sender. Always send from an address on your own domain, something like [email protected]. If you put a From: from another domain, the DMARC in charge is that other domain’s and your configuration does not protect you.
The date worth putting in your calendar
You have it built now, so this is about why you will need it beyond the service you just connected. You may also have arrived at this article the other way round: because something stopped sending without anybody touching anything. If that is you, this will sound familiar.
Plenty of organisations have applications and devices sending with the username and password of a corporate account, pointed at Microsoft’s or Google’s SMTP server. The most common case is an account created for exactly that, something like [email protected], set up by somebody the day the multifunction printer arrived. That is ending, and the two providers are moving at different speeds.

Google: this already happened
Google has already switched off what it called «less secure apps», in stages between mid-2024 and the first half of 2025. Its documentation puts it plainly: «CalDAV, CardDAV, IMAP, SMTP, and POP will no longer work with legacy passwords».
And a taste of how hard these timelines are to follow: Google publishes four different shutdown dates across four of its own official pages (30 September 2024, January 2025, 14 March 2025 and 1 May 2025). I am not going to pick one and pretend it is the right one. What matters is that it is off today.
And one nuance that changes the diagnosis: Google did not close SMTP. What it stopped accepting is the account password. App passwords still work, so a device can be reconfigured. The problem is that somebody has to know that and do it.
Microsoft: yours happens in December
This one still works, which is exactly why it is worth reading now and not in January. The official timeline, which replaces an earlier and more aggressive one, is this:
| When | What happens |
|---|---|
| Now to December 2026 | Nothing changes |
| End of December 2026 | Disabled by default for existing organisations. An administrator can still turn it back on |
| Organisations created afterwards | Not available by default. OAuth as the supported method |
| Second half of 2027 | The final removal date gets announced |
In other words: if you have something sending with the username and password of a Microsoft 365 account, you have until the end of December. After that it stays re-enablable by hand, but you are swimming against the tide, and in 2027 they announce the end of it. One note for anyone inclined to trust the deadline: this date has already slipped twice, from September 2025 to April 2026 and from there to December. That it has moved twice is not a reason to skip preparing, it is a reason not to leave it to the last month.
Microsoft offers a replacement of its own called High Volume Email, and it is worth knowing what it is before somebody suggests it: it is for internal recipients within your organisation, and only that. For sending a notification to a customer it is no use. It is also billed from 1 June 2026, at $42 per million recipients, and without a billing policy assigned the account simply will not send.
Why this always gets discovered through a ticket
I have seen the same pattern several times, and it is what makes this change hurt more than it should. Nobody monitors the thing that has worked for years.
The classic case is the printer that had been scanning to email for six years without anybody touching it. It was set up by somebody who has since left, with the password of an account nobody remembers, and it worked. One day it stops, and the systems team does not find out from an alert or a dashboard: they find out because tickets start coming in from people saying the scanner no longer sends anything.
And that this is not a hobby horse of mine is what the industry itself says: Ricoh published a formal notice in May 2025, updated in February 2026, listing which functions stop working (scan to email, internet fax, notifications) and on which models. Xerox has another, with OAuth-capable firmware already available and no hardware change needed. If your estate is either of those brands, you have homework with names on it.
The same goes for backup notifications, the contact form on your site, the alarm system’s alerts and any automation somebody set up years ago. They all share one property: nobody looks at them until they break, and when they break they do not tell you, they just stop sending.
This is where a relay stops being a convenience and becomes the sensible option. Those credentials do not depend on any person’s account, they do not expire with corporate mail policy, and if they need rotating tomorrow you rotate them in one place and that is that. It is the difference between an inventory and a surprise.
And now, connect it
You have the relay working and verified. What is left is putting those four details into each service, and that does change depending on which one.
The next article I publish is the Passbolt one, where I connect it end to end. It is the perfect case for this: without working email, Passbolt will not let you create a single user.
Self-hosting makes sense for almost everything. For outbound email the sums do not add up: weeks of fighting blocklists and IP warm-up, only to deliver worse than a service that charges you nothing. Handing this one off is not giving up. It is choosing where you spend your afternoons.
More from IT Rafa
- How to install Passbolt with Docker, the password manager that will not start without email (on its way)
- How to connect your domain to Cloudflare for free, which is where these records are going
- How to install Docker and Docker Compose on Linux
- Installing Uptime Kuma with Docker, another service that appreciates a mail relay