Skip to content
Serverküche
Search

Loading search … (only available on the published site).

Applications Difficulty: Advanced

Email deliverability: SPF, DKIM, DMARC and PTR done right

So your self-hosted mails land in the inbox instead of spam: reverse DNS, SPF, DKIM and DMARC explained, set up and tested step by step.

· 14 min read ·Duration: approx. 60 minutes
Table of contents

Your mail server is running, mailboxes are created – and still your mails land in the recipient’s spam or get rejected outright. Welcome to the actually hard part of self-hosting: deliverability. It doesn’t depend on your server software, but on four DNS building blocks that prove to other servers that your mails are genuine. This tutorial sets them up and tests them.

What are we building?

By the end, large mail providers (Gmail, Outlook, GMX & co.) recognize your mails as authentic and deliver them to the inbox instead of spam. Four mechanisms working together ensure this:

  • Reverse DNS (PTR): proves that your server IP belongs to your mail hostname – the basic prerequisite, without which many servers don’t accept at all.
  • SPF: defines which servers may send on behalf of your domain.
  • DKIM: signs every outgoing mail cryptographically, so manipulation and forgery are exposed.
  • DMARC: tells recipients what to do if SPF or DKIM fail – and sends you reports.

The benefit is twofold: your own mails arrive reliably – and no one can forge in your name. Without these records, any attacker can send mails with your sender domain (“spoofing”) and thus conduct phishing in your name. SPF, DKIM and DMARC make exactly that impossible: they turn your domain from an openly abusable sender into a demonstrably genuine one. Especially when customers or colleagues expect mails from you, this protection is at least as important as deliverability itself.

These four records are independent of your server software. Whether you run Mailcow or Stalwart doesn’t matter – you configure deliverability in DNS and at the provider.

No 'set it once and done'

Deliverability is a process, not a state. Even with perfect records, a fresh server IP needs time to build a good reputation. Reckon with a few days until everything runs smoothly, and keep watching the DMARC reports.

Prerequisites

  • A running mail server under your domain (e.g. from the Mailcow or Stalwart tutorial).

  • Full access to the DNS zone of your domain (see connecting a domain to your server).

  • Access to the provider panel to set the reverse-DNS entry of the server IP (at netcup in the SCP).

  • The tool dig to check the records:

    Terminal
    sudo apt install -y bind9-dnsutils

Step by step

Step 1: Set reverse DNS (PTR) – the foundation

The most important and most frequently forgotten entry. While a normal DNS entry resolves a name into an IP, the PTR entry does the opposite: it resolves your server IP back into a name. Recipients check whether this name matches your mail hostname. If the PTR is missing or points to a generic provider name, your server is considered suspicious.

You set the PTR entry not in your DNS zone, but at the provider that owns the IP. At netcup you go to the Server Control Panel (SCP)Network / Reverse DNS and enter the value mail.YOUR_DOMAIN for your IP. After propagation you check:

Terminal
dig +short -x YOUR_SERVER_IP
Ausgabe
mail.example.com.

If mail.YOUR_DOMAIN comes back here, the PTR is correct. If it still points to something like vXXXXXXXXX.example-provider.net, it isn’t set yet or hasn’t propagated.

Warning

The PTR hostname (mail.YOUR_DOMAIN) must resolve forward back to the same IP (A record). This match – “forward-confirmed reverse DNS” (FCrDNS) – is mandatory for many recipients. Check both: dig +short mail.YOUR_DOMAIN must yield YOUR_SERVER_IP.

Step 2: SPF – who may send in your name?

The SPF record is a TXT entry in your DNS zone. It lists the IPs or hostnames that may send mail for your domain. For a single mail server this suffices:

Ausgabe
YOUR_DOMAIN.   TXT   "v=spf1 a:mail.YOUR_DOMAIN -all"

Broken down:

  • v=spf1 – the SPF version.
  • a:mail.YOUR_DOMAIN – the server behind this A record may send. Alternatively the IP directly with ip4:YOUR_SERVER_IP (and ip6:… for IPv6).
  • -allall other servers are not authorized (“hard fail”). That’s the strict, recommended variant. A ~all (“soft fail”) is more lenient, but less effective.

Check – and do it with a filter:

Terminal
dig +short TXT YOUR_DOMAIN | grep spf1
Ausgabe
"v=spf1 a:mail.example.com -all"

The grep isn’t a luxury: dig +short TXT prints all TXT entries of your zone, and over time verification tokens from Google, Microsoft & co. pile up there. Measured for real – google.com answers with 16 TXT entries, microsoft.com with 61. Without the filter you’re picking your SPF record out by hand. If nothing comes back at all, no SPF record exists. If two lines come back, you have two SPF records – and that’s an error, see “When things go wrong”.

If you also send via third parties – e.g. a newsletter service or an app’s transactional-mail gateway – their servers must be authorized too. You do that via include:, and in a single record:

Ausgabe
YOUR_DOMAIN.   TXT   "v=spf1 a:mail.YOUR_DOMAIN include:_spf.provider.com -all"

Tip

There may be only one SPF record per domain, and SPF allows a maximum of 10 DNS lookups in total. Collect all senders in the same record and save yourself superfluous include:, otherwise SPF becomes invalid or runs into a permerror.

Step 3: DKIM – sign every mail cryptographically

DKIM signs every outgoing mail with a private key; you publish the matching public key as a DNS record. Recipients use it to verify that the mail really comes from you and wasn’t changed along the way.

Here’s how it works: when sending, your server computes a signature from important headers and the message body and attaches it as a DKIM-Signature header. The recipient fetches your public key from DNS and checks the signature. If it matches, it’s proven: the mail comes from a server with your private key and wasn’t changed. Use 2048-bit keys – 1024 bit is considered too weak, and most DNS providers now handle the key length without problems.

Your mail server generates the key – you only have to publish the DNS record:

  • In Mailcow: Configuration → ARC/DKIM keys, select the domain, generate a key (2048 bit). Mailcow shows you the finished DNS record.
  • In Stalwart: the keys are created in the setup wizard; you find the record in the console under the respective domain.

The record has a selector (a freely chosen name, e.g. dkim or default) and looks like this:

Ausgabe
dkim._domainkey.YOUR_DOMAIN.   TXT   "v=DKIM1; k=rsa; p=MIIBIjANBgkq...LONG_PUBLIC_KEY...AQAB"

Adopt the value exactly as your mail server outputs it. Check:

Terminal
dig +short TXT dkim._domainkey.YOUR_DOMAIN
Ausgabe
"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA…FIRST_PART" "SECOND_PART…AQAB"

Don’t be puzzled by the two quoted blocks: a single character string inside a TXT entry may carry at most 255 bytes, and a 2048-bit key is longer. It therefore inevitably sits in DNS as two concatenated strings, and dig shows exactly that. This is not a truncated key – recipients reassemble the parts when verifying. Most DNS panels handle the splitting for you; if yours wants the value in one piece, enter it without quotes and without line breaks.

If the v=DKIM1; … value comes back, the public key is published.

Step 4: DMARC – rules and reports

DMARC connects SPF and DKIM: it tells recipients how to handle mails that do not pass the check, and has reports sent to you about the use of your domain. A good starter record:

Ausgabe
_dmarc.YOUR_DOMAIN.   TXT   "v=DMARC1; p=quarantine; rua=mailto:dmarc@YOUR_DOMAIN; adkim=s; aspf=s"

Broken down:

  • p=quarantine – failing mails should go to spam. To start, p=none is recommended (only observe, sort out nothing), so you first evaluate the reports before you arm it. Later you move to quarantine and finally p=reject.
  • rua=mailto:dmarc@YOUR_DOMAIN – the aggregate reports come to this address (create the mailbox beforehand).
  • adkim=s / aspf=s – strict alignment (the signing or sending sender must match the domain exactly). The specification’s default is r (relaxed) – then the same organizational domain suffices, so mail.YOUR_DOMAIN and YOUR_DOMAIN count as aligned. For a single mail server that sends everything under the same domain, s is the sharper and fitting choice; as soon as services on subdomains send along, fall back to r.

Check:

Terminal
dig +short TXT _dmarc.YOUR_DOMAIN
Ausgabe
"v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com; adkim=s; aspf=s"

State of the specification: RFC 9989 (May 2026)

DMARC has been an official IETF standard since May 2026: RFC 9989 (the protocol) together with RFC 9990 (aggregate reports) and RFC 9991 (failure reports) replaces the old, merely informational RFC 7489 (and RFC 9091). Almost nothing changes for you – v=DMARC1 stays the same, existing records remain valid. Three points are worth a look:

  • pct= has been removed with no replacement. The tag that used to apply the policy to only a percentage of mail no longer exists. If it’s still in your record, take it out.
  • np= is new and handy for self-hosters: it sets the policy for non-existent subdomains. np=reject lets recipients immediately reject any mail from a subdomain that doesn’t exist in your DNS at all – a popular spoofing route you close without side effects. (sp= remains responsible for existing subdomains.)
  • The Public Suffix List is out. The organizational domain is now determined by a “DNS tree walk” directly in DNS instead of an externally maintained list.

Step 5: Test everything together

Now the reality check. Three tools – from the big picture to the individual record:

  1. mail-tester.com: the holistic test. Open the page, it shows you a random address. Send a perfectly normal mail there from your new mailbox and click “Then check your score”. You get a rating of 10/10 broken down by SPF, DKIM, DMARC, reverse DNS, content and block lists. Anything below 10 shows you concretely where it’s stuck.

  2. Individual validators per record. For targeted debugging, check each building block separately online: you enter your domain (for DKIM additionally the selector, e.g. dkim) and get the syntax, resolved values and warnings shown:

  3. Counter-check via dig: Check all four building blocks once more in one go:

    Terminal
    dig +short -x YOUR_SERVER_IP                  # PTR
    dig +short TXT YOUR_DOMAIN | grep spf1        # SPF
    dig +short TXT dkim._domainkey.YOUR_DOMAIN    # DKIM
    dig +short TXT _dmarc.YOUR_DOMAIN             # DMARC

A particularly good practical test: send a mail to a Gmail account, open the mail there, and via “Show original” you see SPF: PASS, DKIM: PASS and DMARC: PASS directly. Only when all three are PASS are you on the safe side.

Step 6: Evaluate DMARC reports and arm it

After one or two days, the first DMARC reports arrive at your rua address – XML files from the recipient servers that show which sources sent under your domain and whether SPF/DKIM passed. They’re hard to read raw; a free report analyzer makes them understandable. As soon as you see in the reports that your own mails consistently pass and no foreign sources appear, you raise the DMARC policy step by step from p=none through p=quarantine to p=reject.

Step 7: What Gmail, Yahoo and Outlook.com actually require

You don’t have to guess what “good enough” means – the large providers have put their requirements in writing.

Google and Yahoo, binding since 1 February 2024. For every sender: SPF or DKIM set up, valid forward and reverse DNS records, TLS for transport, and a spam complaint rate below 0.3%. Anyone sending 5,000 mails or more per day to Gmail or Yahoo accounts must additionally set up SPF and DKIM, publish a DMARC record (p=none suffices), align the From: domain with either the SPF or the DKIM domain, and offer one-click unsubscribe via the List-Unsubscribe header for marketing and subscribed mail.

Microsoft, binding since 5 May 2025. For Outlook.com, Hotmail, Live and MSN the same threshold of 5,000 mails per day applies: SPF and DKIM must pass, a DMARC record with at least p=none must exist, and alignment must work via SPF and/or DKIM. Non-compliant mail was first routed to the junk folder; by now Microsoft rejects it right in the SMTP dialogue:

Ausgabe
550 5.7.515 Access denied, sending domain YOUR_DOMAIN does not meet the required authentication level

One detail that’s easily missed: the threshold is sticky. Once a domain has crossed it, the requirements apply permanently – even if you later send considerably less.

As a self-hoster you’ll rarely hit the 5,000 mark. Still, that’s exactly the bar to aim for – and the good news: the requirements are precisely what you built in steps 1 to 4. Whoever has PTR, SPF, DKIM and DMARC set cleanly meets the rules of the three largest providers without having to add anything.

Step 8: Warm up the IP reputation

Perfect DNS records are the entry ticket – but large providers still don’t trust a fresh server IP immediately. They observe your sending behavior and build up a reputation picture over days to weeks. Two things help decisively:

  • Start small, send regularly. A new server that fires off hundreds of mails from a standstill looks like a spam cannon. Send few, genuine mails at first and increase slowly. Consistency beats volume.
  • Send only to existing addresses. Every mail to a non-existent mailbox (a “bounce”) worsens your reputation. Keep your recipient lists clean.

A special case is Microsoft (Outlook, Hotmail, Live): their filters are especially suspicious of new IPs, even with flawless records. The authentication from step 7 is the entry ticket there, but it doesn’t replace reputation. Here only patience helps – and, if necessary, enrolling in Microsoft’s sender programs (SNDS/JMRP), through which you get insight and a line to the reputation assessment.

Advanced: BIMI

When SPF, DKIM and DMARC (with p=quarantine or p=reject) run cleanly, you can use BIMI to display your company or sender logo next to your mails in the inbox. That’s optional polish, not a must – but a nice signal of legitimacy once the foundation is in place.

When things go wrong

mail-tester shows “reverse DNS does not match”. The PTR entry is missing, not propagated yet, or doesn’t match the A record. Set the PTR in the provider panel to mail.YOUR_DOMAIN and check with dig -x; make sure mail.YOUR_DOMAIN points forward to the same IP.

DKIM fails (DKIM: FAIL or “no signature”). The DNS record was adopted incorrectly (genuinely truncated key, wrong selector) or not propagated yet. Copy the value exactly from the mail server UI, match the selector in the record (SELECTOR._domainkey) with the one configured in the server, then counter-check with dig. That dig shows the key as two quoted blocks is normal and not an error – see step 3.

SPF “permerror” or “too many DNS lookups”. Several SPF records, or too many nested include: (limit: 10 DNS lookups). Check with dig +short TXT YOUR_DOMAIN | grep spf1 that really only one line comes back, consolidate to one SPF record and remove unnecessary include:.

Mails to Outlook/Hotmail land in spam or get rejected. If you get a hard rejection with 550 5.7.515 Access denied, sending domain … does not meet the required authentication level, it’s not a reputation problem but Microsoft’s authentication rule from 5,000 mails per day – SPF and DKIM must pass and an aligned DMARC record (at least p=none) must exist; the threshold sticks to the domain even if you later send less. If the mails only land in the junk folder, Microsoft is simply strict with new IPs: patience, send little but regularly, and if needed use Microsoft’s SNDS/JMRP program.

Your IP is on a block list. The IP was with a spammer before you, or a mailbox of yours sends spam. Check on the common block-list checkers, and on a legitimate hit have it removed via the respective delisting form – and fix the cause (compromised account).

Maintenance & backups

Deliverability is ongoing maintenance, not a one-off action:

  • Watch DMARC reports. A regular look immediately shows when someone abuses your domain or an own service suddenly fails.
  • Rotate DKIM keys. Generate a new key every one to two years (new selector, leave the old one standing for a while) to keep security high.
  • Keep an eye on reputation. Occasionally check block lists and the send volume. A sudden rise in outgoing mail is almost always the sign of a hijacked account.
  • Back up records. SPF, DKIM and DMARC records belong in your docs or backup – if the DKIM keys on the server are lost, you have to generate new ones anyway and replace the DNS record (see the backup sections of the mail server tutorials).

Once all four building blocks are set and tested, you’ve got half the battle of reputable mail self-hosting won – the rest is done by a cleanly operated server that isn’t abused as a spam cannon.

Last updated: Aug 25, 2026

You might also like