Running a mail server that actually reaches the inbox
Sending mail from your own server is easy. Having it arrive is the hard part. What we set up, in what order, and the two things we do not send ourselves.
- Published
- Updated
- Reading time
- 8 min
- By
- MuslimSpot
Standing up a mail server takes an afternoon. Getting the mail it sends into somebody's inbox takes longer, and most of that work has nothing to do with the mail server. It is DNS, reputation, and resisting the urge to send things you have no business sending.
We run our own mail for muslimspot.com: mailcow on the same box as everything else, with
the host's nginx in front of the web interface and the SMTP and IMAP ports going straight
to the mail stack. We also pay a third party to send one specific category of mail. This is
the reasoning behind both halves of that, and the order we did things in, because the order
matters more than any individual setting.
Start with the three DNS records, and get them right before you send anything#
A receiving server decides whether to trust you mostly on the strength of three records and one reverse lookup. None of them are optional in 2026, and a mistake in any one of them is worse than not having it, because a broken record looks like a forgery.
SPF says which hosts may send mail claiming to be from your domain. Publish one TXT
record, with one v=spf1, listing the hosts that actually send. We end ours with -all
rather than ~all. The soft fail is popular advice because it is forgiving, and that is
exactly the problem: a receiver that sees ~all has been told the sender is not sure, and
it will treat a forgery as merely suspicious. If you know which hosts send your mail — and
on one server you do — say so and close the list.
Ours, with the one third-party sender we use, is a single record:
v=spf1 mx include:sendgrid.net -allmx covers the server itself without naming its address, so the record survives the machine
moving. The include covers the one external sender. Nothing else may send as us.
The trap in SPF is the ten-lookup limit. Every include: costs a DNS lookup, and a nested
include costs its children too. Three or four large SaaS includes will quietly push you over
the limit, at which point the record returns permerror and some receivers treat that as a
failure. Count your lookups. If you cannot get under ten, you are sending from too many
places.
DKIM signs each message with a private key and publishes the public half in DNS under a selector. Use a 2048-bit key. mailcow generates these for you, which is convenient and also the reason the private keys end up in a place you need to think about: ours are in the nightly off-box backup, which is a large part of why that bucket is private and stays private. A DKIM key is a credential that can send mail as you.
The thing people get wrong with DKIM is the selector. Publish one, use it, and when you rotate, publish the new selector first, wait for the old one's TTL to pass, then switch the signer. Rotating by overwriting a selector in place guarantees a window where signed mail cannot be verified.
DMARC ties the first two together and tells receivers what to do when both fail. Start
at p=none with a rua= address and read the reports for a couple of weeks before you
tighten anything:
v=DMARC1; p=none; rua=mailto:dmarc@muslimspot.com; adkim=s; aspf=s; pct=100adkim=s and aspf=s ask for strict alignment: the domain in the From: header must match
the signing and envelope domains exactly rather than merely being a parent of them. Strict is
the right default for a company that sends from one domain, and you relax it only when you
find a sender you actually want that cannot meet it.
The reports are XML and unpleasant, and they are also the only way you will discover the forgotten system that has been sending invoices as you for a year.
The record that is not a record: reverse DNS. Your sending IP must resolve back to a
hostname, that hostname must resolve forward to the same IP, and your SMTP HELO must
match it. Ours is mail.muslimspot.com, set as the PTR with the hosting provider rather
than in our own zone, because the PTR lives in the reverse zone of whoever owns the
address space. Mail from an IP with a generic provider PTR is treated as suspicious before
the content is even looked at, and no amount of correct DKIM compensates.
Two more worth adding once the first four are right: MTA-STS, which tells senders your domain requires TLS and makes a downgrade attack visible, and TLS-RPT, which gets you told when a sender could not negotiate TLS with you. Both are a static file and a DNS record.
Then worry about the IP, because that is the part you cannot configure#
Everything above is deterministic. Reputation is not. A new IP address has no sending history, and on a VPS it may have somebody else's history, which is worse. Before we sent any mail we checked the address against the public blocklists, and we would have asked for a different one had it been listed. That check takes five minutes and it is the only point at which the problem is cheap to fix.
After that, the only thing that builds reputation is sending a small amount of mail that people want. Not a volume ramp, not a schedule: real mail, to real people, who do not mark it as spam. We did not warm the address with anything artificial, because artificial warming is itself a pattern that gets noticed.
Two things are worth doing once mail is flowing. Register the domain with the large
providers' postmaster tools, which is the only direct feedback you get from them on spam
rate and authentication. And read your own bounces: a 550 from a receiver usually contains
a URL explaining exactly why, and it is the cheapest diagnostic in the whole system.
What we deliberately do not send ourselves#
There are two categories of mail we hand to somebody else, and both decisions were made on risk, not convenience.
The first is application mail — TimeTracer's digest e-mails. Those go through SendGrid. The reason is that application mail is bursty, mechanical, and the kind of thing that gets reported as spam by someone who forgot they signed up. Putting that traffic on the same IP as the address a customer uses to reach a human means one bad week for the digest worker also means our replies to customers stop arriving. Separating the two is the single highest-value thing you can do for the mail that actually matters, and it costs nothing while volume is small.
The second is anything resembling a newsletter, which we do not send at all. A list you do not maintain is a liability: addresses decay, people forget they subscribed, and spam traps accumulate. We will send one when there is something to say and a way to maintain the list properly.
The maintenance nobody mentions#
A mail server is not a thing you finish. Ours needs, on an ongoing basis:
- Certificate renewal that does not forget the mail ports. Our certificates come from certbot on the host, and the renewal hook reloads nginx. The mail stack needs its own reload, or SMTP and IMAP keep serving an expired certificate long after the web interface stopped. This is the single most common way a working mail setup breaks three months later.
- Watching the queue. A quietly growing outbound queue is the first sign that a receiver has started deferring you, and it is visible long before anyone complains that mail is missing.
- Reading the DMARC reports. Not every day. Often enough that a new sender claiming your domain gets noticed.
- Backing up the DKIM keys and the mailcow configuration, and testing the restore. A mail server you cannot rebuild is a mail server whose reputation you will lose on the day the disk fails.
Is it worth it?#
For transactional volume at any real scale: probably not, and we have said so above by paying for exactly that case. For a company's own mail — the address on the contact page, the replies to customers, the mail between the people who work there — yes, and for a reason that has nothing to do with cost. The alternative is that the most sensitive correspondence the business has sits in a third party's logs under terms that can change.
The work is front-loaded and the list is finite. Four DNS facts, a clean IP, a separation between human mail and machine mail, and a certificate renewal that reloads everything it should. After that it is quiet, which is the whole point.