MX Record Setup for Your Own Mail Server (Postfix)

Updated: 5 min read Editorial team vserverhost
Short answer

For an MX record setup, add a record of type MX on @ with a priority such as 10 and a hostname as the target, for example mail.example.com. That hostname needs its own A record, and AAAA if IPv6 works, pointing at the mail server. For mail that actually gets delivered you also need SPF, DKIM, DMARC and a matching PTR record.

Adding the MX record takes a minute. Getting mail into Gmail and Outlook inboxes afterwards depends on five more records, and one of them doesn’t even live in your zone. If you run Postfix on a VPS, set up all six together.

What the MX record does

The MX (mail exchanger) record tells other mail servers where to deliver mail for @example.com. It points at a hostname, never an IP, and carries a priority:

$ORIGIN example.com.
@      3600  IN  MX    10 mail.example.com.
mail   3600  IN  A     192.0.2.25
mail   3600  IN  AAAA  2001:db8:10::25

A sending server looks up MX example.com, gets mail.example.com, resolves that name and connects on port 25. Two rules from RFC 2181 and RFC 5321 are firm: the target is a name with its own A or AAAA record, and it isn’t a CNAME. The reasoning is in CNAME vs A record.

Priority with several MX records

RecordMeaning
MX 10 mail.example.com.Primary server
MX 20 backup.example.net.Used only when 10 is unreachable
MX 10 mx1.example.com. + MX 10 mx2.example.com.Equal preference, load is shared
MX 0 .Null MX: domain accepts no mail (RFC 7505)

A single VPS rarely needs a backup MX. Senders don’t bounce immediately when your server is down. They queue and retry for days. A poorly maintained backup MX without spam filtering, on the other hand, is a well-known way in for spam.

Publish a null MX on every domain that receives no mail. Without any MX, senders fall back to the A record and try to deliver to your web server.

MX record setup: every record Postfix needs

For your own mail server the complete set looks like this:

$ORIGIN example.com.
@                 3600  IN  MX   10 mail.example.com.
mail              3600  IN  A    192.0.2.25
mail              3600  IN  AAAA 2001:db8:10::25
@                 3600  IN  TXT  "v=spf1 mx -all"
mail._domainkey   3600  IN  TXT  "v=DKIM1; k=rsa; p=MIIBIjANBgkqh...IDAQAB"
_dmarc            3600  IN  TXT  "v=DMARC1; p=none; rua=mailto:[email protected]"

SPF lists who may send for the domain. mx allows the hosts from the MX record and -all rejects everyone else. If a newsletter service also sends as you, add its include:. A domain may have only one SPF record.

DKIM signs outgoing mail. Generate the key on the server, with OpenDKIM for instance via opendkim-genkey -s mail -d example.com. The part before ._domainkey is the selector and must match your signing configuration. Some panels split long keys into several quoted strings, which is fine.

DMARC tells receivers what to do when SPF or DKIM fail and where to send reports. Start with p=none, read the reports for a few weeks, then move to quarantine or reject. Since 2024, Gmail and Yahoo require at least SPF or DKIM from all senders, and DMARC as well from bulk senders.

At betadomain you add all of these in the customer area under the domain’s DNS records.

The record outside your zone: PTR

Many receivers check that your mail server’s IP has a reverse DNS entry that matches its hostname. The PTR record lives in your hosting provider’s zone, not yours, and you set it in their panel. Without it, mail lands in spam or is rejected outright. The how-to is in reverse DNS and PTR records.

Postfix’s myhostname should match:

postconf myhostname
myhostname = mail.example.com

The HELO name, the PTR for the IP and the A record of mail.example.com should all agree.

Check MX and mail DNS

dig example.com MX +short
dig mail.example.com A +short
dig example.com TXT +short | grep spf
dig mail._domainkey.example.com TXT +short
dig _dmarc.example.com TXT +short
dig -x 192.0.2.25 +short

Then test port 25 and STARTTLS from outside:

openssl s_client -starttls smtp -connect mail.example.com:25 -servername mail.example.com

If that fails from another machine while Postfix is running, check the firewall. In the other direction, some VPS providers block outbound port 25 for new accounts until you ask support to lift it. You’ll see it as messages stuck in postqueue -p with connection timeouts.

A certificate for the mail hostname

Senders encrypt with STARTTLS when you offer it, and a valid certificate for mail.example.com avoids client warnings on IMAP and submission. If nginx already runs on the server, get one with certbot and point Postfix at it:

certbot certonly --nginx -d mail.example.com
postconf -e 'smtpd_tls_cert_file = /etc/letsencrypt/live/mail.example.com/fullchain.pem'
postconf -e 'smtpd_tls_key_file = /etc/letsencrypt/live/mail.example.com/privkey.pem'
systemctl reload postfix

Postfix and Dovecot have to reload after each renewal, easiest with a --deploy-hook.

Four mistakes behind lost mail

  1. MX pointing at the bare domain (MX 10 example.com.). It works until you move the website, and the mail moves with it. A separate mail name decouples the two.
  2. Old MX records left behind. After switching from your host’s mailboxes to your own server, their MX records often remain with a lower priority. dig MX shows them.
  3. Two SPF records. One from the old host, one from you. RFC 7208 treats that as a permanent error, as if the domain had no SPF at all. Merge them.
  4. AAAA without an IPv6 PTR. Give mail an AAAA record and Postfix delivers over IPv6, where Gmail rejects senders without PTR. See the AAAA record guide.

Switching MX without losing mail

When you change mail servers, lower the MX TTL first, as described in the DNS TTL guide. Keep the old server accepting mail until the old TTL has passed, then copy what arrived there with imapsync. Senders that hit a temporary failure in between retry later.

Set the PTR at your provider, send a test message to a Gmail account and look for the SPF, DKIM and DMARC lines under “Show original”. If you want a separate domain just for mail, you can find one at betadomain. An .email domain is €29.99 a year and a .com for the mail host €14.99.

Step by step

  1. Create an A record for the mail hostPoint mail.example.com at the mail server with an A record, plus AAAA if IPv6 is configured.
  2. Add the MX recordOn @, create an MX record with priority 10 and target mail.example.com, and remove old MX records.
  3. Publish SPFAdd a TXT record on @ with v=spf1 mx -all so only the MX host may send for the domain.
  4. Set up DKIMGenerate a key with OpenDKIM or rspamd and publish the public part as TXT at selector._domainkey.
  5. Publish DMARCAdd a TXT record at _dmarc with v=DMARC1; p=none; rua=mailto:... and tighten the policy after a few weeks of reports.
  6. Set PTR and testSet the reverse DNS of the server IP to mail.example.com at your hosting provider and check with dig MX, dig -x and a test message.

Found your domain? You can check and register it directly at compare domain prices – yearly price from €2.99.

FAQ

Can an MX record point directly to an IP address?

No. The MX target must be a hostname that has its own A or AAAA record. Panels that accept an IP usually create a helper name behind the scenes or store an invalid record.

What does the number before the MX target mean?

It's the preference. Senders try the lowest number first. Records with equal numbers share the load, and higher numbers act as backups.

What happens if a domain has no MX record?

Under RFC 5321, senders fall back to the domain's A or AAAA record. If a domain should never receive mail, publish a null MX as defined in RFC 7505: priority 0 and a single dot as the target.

How long does a new MX record take to work?

As long as the old MX record's TTL. Sending servers that reach the old server in the meantime and get a temporary error keep retrying for days, so short transitions rarely lose mail.