Back to tutorials
Tutorial

VPS Email Setup Tutorial (2026): SPF, DKIM, DMARC, rDNS, and SMTP Ports Without Deliverability Surprises

VPS email setup tutorial for 2026: configure SPF, DKIM, DMARC, rDNS, and SMTP ports to improve inbox placement and reduce bounces.

By Anurag Singh
Updated on Sep 11, 2026
Category: Tutorial
Share article
VPS Email Setup Tutorial (2026): SPF, DKIM, DMARC, rDNS, and SMTP Ports Without Deliverability Surprises

Email from a VPS fails for a few predictable reasons: a sloppy HELO, missing rDNS, broken SPF/DKIM alignment, or a firewall rule blocking outbound SMTP. This VPS email setup tutorial walks you through a practical setup you can verify end-to-end before you send invoices, password resets, or WooCommerce order emails.

This guide assumes you send mail directly from your VPS (Postfix/Exim) and you control DNS for the domain.

If you use cPanel/WHM, the same rules apply. You’ll click more and type less.

What you’ll build (and what you’ll verify)

  • Clean DNS authentication: SPF + DKIM + DMARC with correct alignment
  • Reverse DNS (rDNS/PTR) that matches your sending host
  • Working SMTP ports and firewall rules that don’t break inbound mail
  • Concrete tests: SMTP banner/HELO, TLS, auth headers, and DMARC results

Recommended platform for this tutorial: a Linux VPS where you control the network and DNS.

If you want the least-friction path, start with a HostMyCode VPS. You can set rDNS, manage ports, and tune mail without shared-host constraints.

Prerequisites and a quick decision: direct send vs relay

Before you change configs, decide how this VPS will send mail.

Will it deliver directly from the VPS IP, or hand delivery off to an SMTP relay provider?

  • Direct send (this tutorial): full control, but you own reputation. You also need correct authentication on every message.
  • SMTP relay: often better deliverability for transactional mail; your VPS authenticates to a relay on 587/465.

If your main goal is transactional email (password resets, WooCommerce notifications), a relay is usually the fastest route to consistent inboxing.

HostMyCode has a detailed guide here: SMTP relay setup guide tutorial (2026). If you’re set on direct-send, continue below.

Step 1 — Set a stable hostname and correct HELO/EHLO

Many bounces start with mismatched identity.

The usual culprits are the server hostname, SMTP banner, and rDNS.

Pick a mail hostname that exists in DNS (A record) and keep it stable. A common choice is mail.example.com.

On Ubuntu/Debian

sudo hostnamectl set-hostname mail.example.com
hostname -f

hostname -f should return the FQDN.

Next, confirm it resolves cleanly on the server:

getent hosts mail.example.com

If it doesn’t resolve, fix the DNS A record (best).

Or add a temporary entry in /etc/hosts (fine for a quick test, not a long-term plan).

Postfix banner/HELO (common defaults)

Open /etc/postfix/main.cf and set:

myhostname = mail.example.com
mydomain = example.com
myorigin = $mydomain

Reload Postfix:

sudo systemctl reload postfix

Quick test:

echo | openssl s_client -starttls smtp -connect 127.0.0.1:25 -crlf -quiet

You should see an SMTP banner showing your chosen hostname.

Certificate details come into play later. For now, confirm identity and a working TLS handshake.

Step 2 — Open only the SMTP ports you actually need

Good mail setups don’t “open everything and hope.”

Decide what this VPS is responsible for:

  • Outbound sending only: 25 outbound (server-to-server) must work; inbound 25 is optional.
  • Inbound mailbox hosting: inbound 25 is required, plus 587 for submission, plus IMAPS/POP3S if you offer client mailboxes.

If you’re on a hardened VPS, confirm network rules early.

People often lose hours “fixing DNS” when the firewall is the real problem.

UFW example (Ubuntu)

sudo ufw status verbose
sudo ufw allow 25/tcp
sudo ufw allow 587/tcp
sudo ufw allow 465/tcp

If you also host IMAP/POP:

sudo ufw allow 993/tcp
sudo ufw allow 995/tcp

Pitfall: even with your firewall open, some providers block outbound 25 by policy.

If port 25 is filtered, request unblocking (if available) or switch to the relay approach.

For a structured “don’t-break-mail” approach to firewalling on cPanel servers, see: cPanel Firewall Setup Guide (2026).

Step 3 — Create the DNS records that mail servers expect

You’re going to set four core DNS elements.

Two handle identity. Two handle enforcement:

  • MX for inbound (optional if you only send outbound)
  • SPF to declare allowed senders
  • DKIM to sign mail cryptographically
  • DMARC to enforce policy and receive reports

3.1 MX record (only if receiving mail)

If your domain will receive mail on this VPS:

  • Type: MX
  • Name: @
  • Value: mail.example.com
  • Priority: 10

Also ensure mail.example.com has an A record pointing to your VPS public IP.

3.2 SPF record (baseline)

SPF is a TXT record at the domain root.

Start small and explicit.

If you only send from this VPS IP:

Name: @
Type: TXT
Value: v=spf1 ip4:YOUR.VPS.IP.ADDRESS -all

If you also send from a provider (Google Workspace, Microsoft 365, a relay): include them explicitly (example shown for a generic include):

Value: v=spf1 ip4:YOUR.VPS.IP.ADDRESS include:mailprovider.example -all

Rules that prevent future pain:

  • Keep SPF under 10 DNS lookups total.
  • Avoid “~all” (softfail) for production. Move to “-all” once you’ve confirmed all legitimate senders are covered.

3.3 DKIM: generate keys and publish the public key

On a VPS, you’ll usually implement DKIM with OpenDKIM (Postfix). Or you’ll use the MTA’s built-in signing (Exim/cPanel).

Either way, the outcome is the same. Your server signs outgoing mail, and receivers validate it using a DNS TXT record.

If you want a dedicated OpenDKIM walkthrough, use HostMyCode’s step-by-step guide: DKIM Setup Tutorial (2026).

Below is the short, workable path for Ubuntu/Debian with Postfix.

Install packages

sudo apt update
sudo apt install -y opendkim opendkim-tools

Create a selector and keys

Use a selector like s1. It makes key rotation easier later without breaking mail.

sudo mkdir -p /etc/opendkim/keys/example.com
sudo opendkim-genkey -D /etc/opendkim/keys/example.com/ -d example.com -s s1
sudo chown -R opendkim:opendkim /etc/opendkim/keys/example.com
sudo chmod 0700 /etc/opendkim/keys/example.com
sudo chmod 0600 /etc/opendkim/keys/example.com/s1.private

Publish DKIM DNS record

Print the TXT record content:

sudo cat /etc/opendkim/keys/example.com/s1.txt

It will look like s1._domainkey with a long p= value.

Add that TXT record to DNS exactly as shown.

Wire OpenDKIM into Postfix (minimal)

Edit /etc/opendkim.conf (key lines):

Syslog                  yes
UMask                   002
Canonicalization        relaxed/simple
Mode                    sv
SubDomains              no
Socket                  local:/run/opendkim/opendkim.sock
UserID                  opendkim:opendkim
KeyTable                /etc/opendkim/key.table
SigningTable            /etc/opendkim/signing.table
TrustedHosts            /etc/opendkim/trusted.hosts

Create the tables:

sudo tee /etc/opendkim/key.table >/dev/null <<'EOF'
s1._domainkey.example.com example.com:s1:/etc/opendkim/keys/example.com/s1.private
EOF

sudo tee /etc/opendkim/signing.table >/dev/null <<'EOF'
*@example.com s1._domainkey.example.com
EOF

sudo tee /etc/opendkim/trusted.hosts >/dev/null <<'EOF'
127.0.0.1
localhost
*.example.com
EOF

Ensure the socket directory exists and permissions are right:

sudo mkdir -p /run/opendkim
sudo chown opendkim:opendkim /run/opendkim

Add these to /etc/postfix/main.cf:

milter_default_action = accept
milter_protocol = 6
smtpd_milters = local:/run/opendkim/opendkim.sock
non_smtpd_milters = local:/run/opendkim/opendkim.sock

Restart services:

sudo systemctl restart opendkim
sudo systemctl restart postfix

3.4 DMARC record (start with reports, then enforce)

DMARC is where “we set SPF/DKIM” turns into “we can see what receivers accept.”

Start in monitoring mode first. You’ll get reports before you tighten policy.

Name: _dmarc
Type: TXT
Value: v=DMARC1; p=none; adkim=s; aspf=s; rua=mailto:dmarc-reports@example.com; fo=1

After you confirm alignment and clean reports, move to enforcement:

  • p=quarantine (good first step)
  • p=reject (strictest)

For a reporting-focused walkthrough and practical alignment checks, see: Set Up DMARC Reporting for a VPS Email Domain (2026).

Step 4 — Set rDNS/PTR correctly (and match it to your hostname)

If you send directly to recipient MX servers, rDNS is not optional in practice.

Your VPS IP should resolve back to the same hostname you present in the SMTP banner. In most cases, that hostname is mail.example.com.

Target:

  • Forward DNS: mail.example.comYOUR.VPS.IP
  • Reverse DNS (PTR): YOUR.VPS.IPmail.example.com

Set PTR in your hosting control panel/provider setting (it’s not a normal zone record).

After it’s set, verify from any Linux shell:

dig +short -x YOUR.VPS.IP
dig +short mail.example.com A

Pitfall: a PTR pointing to something generic like vps123.provider.net while your SMTP banner says mail.example.com often triggers deliverability penalties.

Step 5 — Confirm TLS for SMTP (don’t skip the certificate chain)

SMTP isn’t HTTPS, but receivers still care about opportunistic TLS.

Use a valid certificate for the mail hostname and a complete chain. Avoid half-working TLS that fails on stricter verifiers.

If you already use Let’s Encrypt for your web server, request a cert for mail.example.com as well. On a typical VPS:

sudo apt install -y certbot
sudo certbot certonly --standalone -d mail.example.com

Then configure Postfix TLS paths in /etc/postfix/main.cf (adjust if your distro stores certs differently):

smtpd_tls_cert_file=/etc/letsencrypt/live/mail.example.com/fullchain.pem
smtpd_tls_key_file=/etc/letsencrypt/live/mail.example.com/privkey.pem
smtpd_tls_security_level=may
smtp_tls_security_level=may

Reload Postfix:

sudo systemctl reload postfix

Test TLS from outside:

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

If you want a stricter HTTPS/TLS posture across services (and a safer cipher baseline), you can borrow the same thinking from: TLS Hardening Tutorial (2026).

Step 6 — Send a real test email and read the headers like a mail admin

DNS may still be propagating at this point.

Don’t guess, and don’t rely on “it seems fine.” Send a test message to an inbox you control (Gmail/Outlook is fine), then read the full headers.

Send from CLI

Install mailutils on Ubuntu/Debian:

sudo apt install -y mailutils

Send a test:

echo "VPS mail test $(date -Is)" | mail -s "VPS mail test" you@your-inbox.example

What to look for in headers

  • SPF: pass for your sending IP
  • DKIM: pass and the d=example.com domain matches your From:
  • DMARC: pass (requires SPF or DKIM pass and alignment)
  • Received: your SMTP hostname appears consistently

If DMARC fails but SPF and DKIM pass, alignment is usually the issue.

A common example: you send From: example.com, but DKIM signs as d=mail.example.com.

Another example: SPF authenticates against a different domain.

Fix the signing domain, or adjust your From strategy so they match.

Step 7 — Add a submission port (587) for apps and WordPress

Even if your server delivers mail to other MTAs on port 25, applications should submit mail on 587 with authentication.

This reduces abuse risk. It also makes troubleshooting more straightforward.

On Postfix, enable submission in /etc/postfix/master.cf by uncommenting the submission service and enforcing auth/TLS. A safe baseline looks like this:

submission inet n       -       y       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject

Reload Postfix after edits:

sudo systemctl reload postfix

WordPress note: if WordPress emails go missing, don’t “just retry” and hope.

You’ll end up fighting rate limits and inconsistent queues.

Use SMTP submission, watch the logs, and verify triggers. For scheduled mail and event timing issues, this guide helps: WordPress Cron Troubleshooting Tutorial (2026).

Step 8 — Log checks and fast troubleshooting (10-minute flow)

When mail breaks, you need a repeatable flow.

Always aim for a specific error and a specific fix.

8.1 Confirm Postfix is listening

sudo ss -lntp | egrep ':25|:587|:465'
sudo systemctl status postfix --no-pager

8.2 Watch logs while sending

On Ubuntu/Debian:

sudo tail -f /var/log/mail.log

8.3 Common errors and what they actually mean

  • “Host or domain name not found”: broken DNS for your MX/hostname or resolver issues on the VPS.
  • “TLS is required, but host did not offer STARTTLS”: the remote requires TLS; confirm Postfix TLS settings and certificate paths.
  • “SPF fail / DKIM fail”: usually a DNS typo, selector mismatch, or you’re sending from an IP not covered by SPF.
  • Timeout on port 25: firewall blocks outbound 25, upstream filtering, or remote throttling.

If you’re running cPanel/WHM and troubleshooting client-facing mail issues, keep this guide handy: cPanel Email Troubleshooting Tutorial (2026).

Step 9 — Hardening that won’t break deliverability

Email security can backfire when it changes your identity or blocks legitimate traffic.

Keep hardening focused on abuse prevention and operational hygiene.

  • Rate-limit abusive SMTP auth attempts (submission port), not server-to-server SMTP.
  • Disable open relay: never permit unauthenticated sending to arbitrary domains.
  • Keep the mail hostname stable and don’t rotate IPs casually.
  • Patch regularly and review logs for auth abuse.

If you want a practical monitoring loop for auth abuse and mail-related bans, see: VPS log monitoring tutorial (2026).

Step 10 — A deliverability checklist you can run before go-live

  • Hostname: hostname -f returns mail.example.com
  • Forward DNS: A record exists for mail.example.com → VPS IP
  • rDNS/PTR: VPS IP PTR → mail.example.com
  • SPF: includes the VPS IP and ends with -all
  • DKIM: selector record published, signature passes in test headers
  • DMARC: record published; start at p=none then enforce
  • Ports: 25 works for server-to-server, 587 works for authenticated submission
  • TLS: STARTTLS works and cert chain is valid for mail.example.com
  • Logs: you can see a full send attempt end-to-end in /var/log/mail.log

Summary: a repeatable email setup that scales with your hosting

The goal is a “boring” mail identity that receivers can verify.

Use a stable hostname, matching rDNS, strict SPF, DKIM signatures, and DMARC reporting.

This combo prevents most “why are we in spam?” incidents. It also gives you evidence when a receiver rejects a message.

If you want an environment where you can control rDNS, firewall policy, and mail services without workarounds, run this on managed VPS hosting from HostMyCode.

You’ll spend less time fighting platform limits and more time shipping reliable email for your sites and clients.

If you’re hosting client sites or running WooCommerce, email reliability is part of uptime. HostMyCode’s HostMyCode VPS plans give you the control you need for rDNS, ports, and DNS-driven authentication.

Prefer to offload routine server work while keeping performance predictable? Use managed VPS hosting so you can focus on application work, not mail queues.

FAQ

Do I need an MX record if I only send mail from my VPS?

No. MX controls where inbound mail is delivered. For outbound-only sending, focus on SPF, DKIM, DMARC, rDNS, and a stable hostname.

Why does DMARC fail even when SPF and DKIM show “pass”?

DMARC requires alignment. Either SPF must pass with an aligned domain (MAIL FROM) or DKIM must pass with an aligned d= domain that matches your From: domain.

Should I use port 25 or 587 for WordPress?

Use 587 with SMTP auth for apps and WordPress. Reserve port 25 for server-to-server delivery between MTAs.

How long does it take for DNS changes (SPF/DKIM/DMARC) to work?

It depends on your DNS TTL and resolver caching. In practice, plan for 15–60 minutes, and confirm with dig from more than one network.

What’s the fastest fix if outbound port 25 is blocked?

Use an SMTP relay provider on port 587/465. Follow the HostMyCode relay tutorial and keep your DNS auth (SPF/DKIM/DMARC) aligned.

VPS Email Setup Tutorial (2026): SPF, DKIM, DMARC, rDNS, and SMTP Ports Without Deliverability Surprises | HostMyCode