Self-Hosting a Production Mail Server (Postfix, Dovecot & DMARC)
Created: 2026-11-05 Last updated: 2026-11-06
Running your own email infrastructure is widely considered the supreme discipline of Linux system administration. Unlike a standalone web server, email is a globally federated system built on strict cryptographic trust, IP reputation, and multi-layered protocol verification.
While commercial providers (Gmail, Microsoft 365) scan metadata and lock you into proprietary ecosystems, operating your own hardened mail stack grants you 100% sovereignty over your private communications, unlimited aliases, custom server-side Sieve filtering, and zero third-party data mining.
1. Architecture, Protocols & Pre-Flight Requirements
An enterprise-grade Linux mail server is not a single monolithic binary—it is a modular pipeline of specialized daemons working in concert:
```mermaid
%%{init: {'flowchart': {'wrappingWidth': 350, 'subGraphTitleMargin': {'top': 15, 'bottom': 15}}}}%%
flowchart TB
Sender["🌐 External Sender MTA
(Gmail / Corporate)"]
Postfix["📮 Postfix Listener (:25)
TLS 1.3 · DNSBL · SPF"]
Filter["🔐 Spam & Malware Filter
Rspamd & ClamAV"]
Dovecot["📬 Dovecot LMTP
Server-Side Sieve"]
Maildir[("💾 Encrypted Maildir
/var/vmail/domain/user/")]
Sender ==>|"SMTP :25 (STARTTLS)"| Postfix
Postfix -->|"Milter Scan"| Filter
Filter -->|"Clean Email"| Dovecot
Dovecot ==>|"Atomic Storage"| Maildir
```
%%{init: {'flowchart': {'wrappingWidth': 350, 'subGraphTitleMargin': {'top': 15, 'bottom': 15}}}}%%
flowchart TB
Client["💻 Mail Client<br/>(Thunderbird / Mobile)"]
subgraph InboundAccess ["Mailbox Access (IMAP)"]
DovecotImap["📬 Dovecot IMAPS (:993)<br/>Encrypted Access"]
MaildirStore[("💾 Maildir Storage<br/>/var/vmail/")]
DovecotImap <==> MaildirStore
end
subgraph OutboundFlow ["Email Dispatch (SMTP)"]
PostfixOut["📮 Postfix Submission (:587)<br/>SASL Auth + TLS 1.3"]
DKIM["✍️ OpenDKIM Milter<br/>Cryptographic Signature"]
Recipient["🌍 Recipient MTA (:25)<br/>Internet Delivery"]
PostfixOut --> DKIM --> Recipient
end
Client <==>|"Fetch Mail (:993)"| InboundAccess
Client ==>|"Send Mail (:587)"| OutboundFlow
InboundAccess ==> OutboundFlow
The Four Core Building Blocks
-
MTA — Mail Transfer Agent (
Postfix)
The SMTP router. Accepts incoming messages on port
25, authenticates outbound user submissions on ports587/465, enforces TLS, and routes mail across the internet via DNSMXlookups. -
MDA & IMAP — (
Dovecot)
Stores incoming emails into structured
Maildirfolders, executes server-side Sieve sorting rules, serves mailboxes to clients via IMAPS (993), and acts as the central SASL authentication backend. -
Trust & Crypto Layer (
SPF / DKIM / DMARC)
Cryptographically proves to Gmail, Outlook, and Yahoo that your server is authorized to send mail for your domain (
SPF) and that headers/bodies were not forged in transit (DKIM+DMARC). -
Anti-Spam & Malware (
Amavis / Rspamd + ClamAV)
Inspects every inbound message against real-time DNS blocklists (DNSBLs), Bayesian spam heuristics, and ClamAV virus signature databases before delivery.
Essential Network Ports Reference
| Protocol / Role | Port | Transport & Encryption | Purpose & Exposure |
|---|---|---|---|
| SMTP (Server-to-Server) | 25/tcp |
Opportunistic STARTTLS |
Mandatory for receiving mail from other MTAs and sending outbound mail. |
| SMTPS (Submission Wrapper) | 465/tcp |
Implicit TLS 1.3 (RFC 8314) |
Modern standard for mail clients (MUAs) submitting outgoing mail. |
| SMTP Submission | 587/tcp |
Mandatory STARTTLS |
Classic authenticated port for mail clients submitting outgoing mail. |
| IMAPS (Mailbox Access) | 993/tcp |
Implicit TLS 1.3 (RFC 8314) |
Encrypted mailbox synchronization for Thunderbird, iOS, Android, and Webmail. |
Pre-Flight Checklist: Do Not Skip These 4 Requirements!
- Unblocked Port 25: Many cloud providers block outbound TCP port
25by default to prevent spam. Verify outbound port 25 is open before starting: - Static Public IPv4 (and IPv6) Address: Dynamic residential IPs are listed on spam blocklists (Spamhaus PBL) and will be rejected by 99% of receiving mail servers.
- Forward-Confirmed Reverse DNS (
FCrDNS / PTR): Your VPS provider's Reverse DNS (PTR) record for your IP address must resolve tomail.yourdomain.com, andmail.yourdomain.com(A/AAAA) must resolve back to that exact IP! - Clean IP Reputation: Check your server's IP on MXToolbox Blacklist Check to ensure a previous VPS tenant didn't burn the IP's reputation.
Architecture Choice: Native Stack vs. Containerized Mail Suites
In this guide, we build the native Postfix + Dovecot stack step by step so you master every socket, config file, and protocol layer. If you later prefer a pre-packaged container suite for multi-domain management, check out Docker Mailserver (DMS), Mailcow, or the Rust-based Stalwart Mail Server.
2. DNS Foundation: A, AAAA, MX & PTR
Before installing a single package, configure your domain's DNS zone and your VPS provider's Reverse DNS (PTR). Replace yourdomain.com and 198.51.100.10 with your real domain and IP.
| Record Type | Name / Host | Value / Target | Priority | TTL |
|---|---|---|---|---|
A |
mail |
198.51.100.10 |
— | 3600 |
AAAA |
mail |
2001:db8::10 (if IPv6 enabled) |
— | 3600 |
MX |
@ (Root Domain) |
mail.yourdomain.com. |
10 |
3600 |
PTR (at VPS Hoster) |
198.51.100.10 |
mail.yourdomain.com. |
— | — |
# 1. Install dig utility if missing
sudo apt update && sudo apt install -y dnsutils
# 2. Verify A record and MX record
dig A mail.yourdomain.com +short
dig MX yourdomain.com +short
# 3. Verify Reverse DNS (PTR) matches your mail hostname!
dig -x 198.51.100.10 +short
3. Core Stack: Installing & Configuring Postfix & Dovecot
Step 1: Set the System Hostname & Install Packages
Your server's system hostname (FQDN) must match your PTR and A record (mail.yourdomain.com):
# 1. Set FQDN hostname
sudo hostnamectl set-hostname mail.yourdomain.com
# 2. Install Postfix, Dovecot (IMAP + LMTP + Sieve), and testing utilities
sudo apt update
sudo DEBIAN_PRIORITY=low apt install -y \
postfix dovecot-core dovecot-imapd dovecot-lmtpd dovecot-sieve mailutils swaks
(During the Postfix prompt, select Internet Site and set the System mail name to yourdomain.com).
Step 2: Configure Postfix (main.cf) & Dovecot Mailboxes
Instead of outdated mbox single-file storage, we configure the resilient Maildir/ format (one atomic file per email) and set up Dovecot 2.3's native folder auto-creation (Trash, Sent, Drafts, Junk).
sudo postconf -e "myhostname = mail.yourdomain.com"
sudo postconf -e "mydomain = yourdomain.com"
sudo postconf -e "myorigin = \$mydomain"
sudo postconf -e "mydestination = \$myhostname, \$mydomain, localhost.\$mydomain, localhost"
sudo postconf -e "inet_interfaces = all"
sudo postconf -e "home_mailbox = Maildir/"
sudo postconf -e "recipient_delimiter = +"
Sub-Addressing (recipient_delimiter = +)
Setting recipient_delimiter = + automatically enables instant disposable aliases! Any mail sent to nejat+github@yourdomain.com or nejat+shopping@yourdomain.com is delivered directly into nejat@yourdomain.com.
Now configure Dovecot's Maildir path in /etc/dovecot/conf.d/10-mail.conf and verify native folder auto-creation in /etc/dovecot/conf.d/15-mailboxes.conf:
namespace inbox {
mailbox Drafts {
auto = subscribe
special_use = \Drafts
}
mailbox Junk {
auto = subscribe
special_use = \Junk
}
mailbox Trash {
auto = subscribe
special_use = \Trash
}
mailbox Sent {
auto = subscribe
special_use = \Sent
}
}
4. Transport Encryption (Let's Encrypt TLS 1.3) & Firewall
Never transmit passwords or emails in cleartext. We obtain a trusted Let's Encrypt certificate via certbot and enforce modern TLS 1.2 / TLS 1.3 across both Postfix and Dovecot.
Step 1: Open Firewall Ports & Obtain Certificate
# 1. Allow Mail Ports (25=SMTP, 465=SMTPS, 587=Submission, 993=IMAPS) & HTTP (for Certbot)
sudo ufw allow 25,80,465,587,993/tcp
# 2. Install Certbot and obtain certificate for mail.yourdomain.com
sudo apt install -y certbot
sudo certbot certonly --standalone -d mail.yourdomain.com \
--non-interactive --agree-tos --email admin@yourdomain.com \
--deploy-hook "systemctl reload postfix; systemctl reload dovecot"
Automatic Zero-Downtime Certificate Renewal
Adding --deploy-hook "systemctl reload postfix; systemctl reload dovecot" writes a permanent hook into /etc/letsencrypt/renewal/mail.yourdomain.com.conf. Every time Certbot renews your certificate in the background, Postfix and Dovecot automatically reload the new keys without dropping a single connection!
Step 2: Harden Postfix & Dovecot TLS Ciphers
Apply modern TLS settings to Postfix using postconf:
sudo postconf -e "smtpd_tls_cert_file = /etc/letsencrypt/live/mail.yourdomain.com/fullchain.pem"
sudo postconf -e "smtpd_tls_key_file = /etc/letsencrypt/live/mail.yourdomain.com/privkey.pem"
sudo postconf -e "smtpd_tls_security_level = may"
sudo postconf -e "smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1"
sudo postconf -e "smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1"
sudo postconf -e "smtpd_tls_mandatory_ciphers = high"
sudo postconf -e "smtp_tls_security_level = may"
sudo postconf -e "smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1"
sudo postconf -e "smtp_tls_CApath = /etc/ssl/certs"
And configure /etc/dovecot/conf.d/10-ssl.conf:
ssl = required
ssl_cert = </etc/letsencrypt/live/mail.yourdomain.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.yourdomain.com/privkey.pem
ssl_min_protocol = TLSv1.2
ssl_prefer_server_ciphers = yes
5. SASL Authentication & Preventing Open Relays
An unauthenticated mail server that relays mail to external domains is an Open Relay—bots will discover it within minutes and flood the internet with spam, destroying your IP reputation.
Instead of maintaining two separate user databases, Postfix delegates SMTP authentication to Dovecot's SASL socket:
%%{init: {'flowchart': {'wrappingWidth': 350}}}%%
flowchart TB
Client["💻 Mail Client (MUA)"] ==>|"1. Port 587/465"| Postfix["📮 Postfix smtpd"]
Postfix <==>|"2. UNIX Socket"| DovecotAuth["🔐 Dovecot Auth Service"]
DovecotAuth <==>|"3. Verify"| Backend[("🗄️ PAM / Virtual SQL DB")]
Postfix ==>|"4. Auth OK"| Outbound(("🌍 Outbound Delivery"))
Step 1: Expose the Dovecot SASL Socket to Postfix
Edit /etc/dovecot/conf.d/10-auth.conf to allow plain and login over TLS:
And enable the Postfix UNIX socket inside /etc/dovecot/conf.d/10-master.conf:
service auth {
unix_listener /var/spool/postfix/private/auth {
mode = 0660
user = postfix
group = postfix
}
}
Step 2: Connect Postfix to Dovecot SASL & Enable Ports 587 / 465
sudo postconf -e "smtpd_sasl_type = dovecot"
sudo postconf -e "smtpd_sasl_path = private/auth"
sudo postconf -e "smtpd_sasl_auth_enable = yes"
sudo postconf -e "smtpd_sasl_security_options = noanonymous"
sudo postconf -e "smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination"
Uncomment the submission (587) and smtps (465) blocks in /etc/postfix/master.cf:
submission inet n - y - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_tls_auth_only=yes
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
smtps inet n - y - - smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_relay_restrictions=permit_sasl_authenticated,reject
sudo systemctl restart dovecot postfix
sudo ls -la /var/spool/postfix/private/auth
Hands-On Lab 1: Testing Authenticated TLS Submission with swaks
Create a test user and verify end-to-end STARTTLS + SASL authentication on Port 587 using the Swiss Army Knife for SMTP (swaks):
# 1. Test STARTTLS + SASL Authentication on Port 587
swaks --server mail.yourdomain.com --port 587 \
--tls \
--auth LOGIN \
--auth-user testuser \
--auth-password 'YourStrongPassword' \
--from testuser@yourdomain.com \
--to external.recipient@gmail.com \
--header "Subject: TLS + SASL Test from Sovereign Mail Server" \
--body "Authenticated over TLS 1.3 via Dovecot SASL!"
# 2. Verify TLS 1.3 handshake on IMAPS Port 993
openssl s_client -connect mail.yourdomain.com:993 -servername mail.yourdomain.com </dev/null 2>/dev/null | grep -E "Protocol|Cipher|Verify return code"
6. Deliverability Mastery: SPF, DKIM & DMARC
Without cryptographic sender authentication, Gmail, Microsoft Outlook, and Apple iCloud will immediately route your outgoing emails to the Spam folder or reject them outright with 550-5.7.26.
How the Cryptographic Trust Triangle Works
%%{init: {'flowchart': {'wrappingWidth': 350}}}%%
flowchart TB
Email["📧 Outgoing Email<br/>user@yourdomain.com"]
RecvServer["🛡️ Receiving Mail Server<br/>Inbound Authentication"]
SPF["1️⃣ SPF Check (DNS TXT)<br/>Authorized IP Check"]
DKIM["2️⃣ DKIM Check (Crypto)<br/>Signature Match DNS"]
DMARC["3️⃣ DMARC Alignment<br/>Policy Enforcement"]
Inbox["🟢 Deliver to Inbox<br/>Authentication Passed"]
Reject["🔴 Quarantine or Reject<br/>SMTP 550 Rejection"]
Email ==>|"SMTP :25 Delivery"| RecvServer
RecvServer --> SPF
RecvServer --> DKIM
SPF --> DMARC
DKIM --> DMARC
DMARC ==>|"PASS"| Inbox
DMARC ==>|"FAIL"| Reject
Step 1: Publish Your SPF Record in DNS
Create a TXT record on your root domain (@ / yourdomain.com) that authorizes only your MX server and explicitly rejects (-all) all spoofed IPs:
Name: @ (or yourdomain.com)
Type: TXT
Value: "v=spf1 mx a:mail.yourdomain.com -all"
Step 2: Install & Configure OpenDKIM (2048-bit RSA Signing)
# 1. Install OpenDKIM and tools
sudo apt install -y opendkim opendkim-tools
# 2. Allow Postfix user to access the OpenDKIM socket inside the Postfix chroot
sudo usermod -aG opendkim postfix
sudo mkdir -p /var/spool/postfix/opendkim
sudo chown opendkim:postfix /var/spool/postfix/opendkim
sudo chmod 750 /var/spool/postfix/opendkim
# 3. Create key directory and generate a 2048-bit RSA key pair with selector 'default'
sudo mkdir -p /etc/opendkim/keys/yourdomain.com
sudo opendkim-genkey -b 2048 -d yourdomain.com -s default -D /etc/opendkim/keys/yourdomain.com/
sudo chown -R opendkim:opendkim /etc/opendkim
sudo chmod 600 /etc/opendkim/keys/yourdomain.com/default.private
Configure /etc/opendkim.conf to use the chroot-safe UNIX socket /var/spool/postfix/opendkim/opendkim.sock:
Syslog yes
UMask 007
Mode sv
Canonicalization relaxed/simple
Socket local:/var/spool/postfix/opendkim/opendkim.sock
UserID opendkim
PidFile /run/opendkim/opendkim.pid
KeyTable refile:/etc/opendkim/KeyTable
SigningTable refile:/etc/opendkim/SigningTable
InternalHosts refile:/etc/opendkim/TrustedHosts
ExternalIgnoreList refile:/etc/opendkim/TrustedHosts
Populate the three mapping tables:
cat << 'EOF' | sudo tee /etc/opendkim/KeyTable
default._domainkey.yourdomain.com yourdomain.com:default:/etc/opendkim/keys/yourdomain.com/default.private
EOF
cat << 'EOF' | sudo tee /etc/opendkim/SigningTable
*@yourdomain.com default._domainkey.yourdomain.com
EOF
cat << 'EOF' | sudo tee /etc/opendkim/TrustedHosts
127.0.0.1
localhost
::1
*.yourdomain.com
EOF
sudo chown opendkim:opendkim /etc/opendkim/KeyTable /etc/opendkim/SigningTable /etc/opendkim/TrustedHosts
Connect Postfix to the OpenDKIM milter:
sudo postconf -e "milter_default_action = accept"
sudo postconf -e "milter_protocol = 6"
sudo postconf -e "smtpd_milters = local:opendkim/opendkim.sock"
sudo postconf -e "non_smtpd_milters = \$smtpd_milters"
sudo systemctl restart opendkim postfix
Display your generated DKIM public key and add it as a TXT record under default._domainkey.yourdomain.com:
Step 3: Publish Your DMARC Record in DNS
Create a TXT record for _dmarc.yourdomain.com. Start with p=quarantine (or p=none during initial testing) and transition to p=reject once verified:
Name: _dmarc
Type: TXT
Value: "v=DMARC1; p=quarantine; rua=mailto:postmaster@yourdomain.com; adkim=r; aspf=r; pct=100"
7. Anti-Spam & Malware Defense Pipeline
An internet-facing port 25 receives constant automated spam and malware probes. We filter incoming mail through a multi-stage inspection pipeline:
%%{init: {'flowchart': {'wrappingWidth': 350}}}%%
flowchart TB
In(("🌐 Port :25")) --> RBL["1️⃣ Postfix DNSBLs<br/>(Drop botnet IPs)"]
RBL --> DKIM_V["2️⃣ OpenDKIM<br/>(Verify signature)"]
DKIM_V --> AV["3️⃣ ClamAV Daemon<br/>(Block malware)"]
AV --> Spam["4️⃣ SpamAssassin / Rspamd<br/>(Heuristic scoring)"]
Spam --> Sieve["5️⃣ Dovecot Sieve<br/>(Move to Junk)"]
sudo apt install -y amavisd-new spamassassin clamav-daemon clamav-freshclam \
pyzor razor libnet-dns-perl libmail-dkim-perl
# Grant ClamAV and Amavis mutual socket access
sudo adduser clamav amavis
sudo adduser amavis clamav
# Enable SpamAssassin rule updates and start services
sudo sa-update
sudo systemctl enable --now clamav-daemon clamav-freshclam spamassassin amavis
Enable virus and spam checks in /etc/amavis/conf.d/15-content_filter_mode:
On servers with limited RAM, Rspamd (written in C) replaces both Amavis, SpamAssassin, and OpenDKIM in a single ultra-fast daemon with a built-in web dashboard (127.0.0.1:11334):
sudo apt install -y rspamd redis-server
sudo postconf -e "smtpd_milters = inet:127.0.0.1:11332"
sudo postconf -e "non_smtpd_milters = inet:127.0.0.1:11332"
sudo postconf -e "milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen}"
sudo systemctl restart rspamd postfix
Hands-On Lab 2: Testing Anti-Spam (GTUBE) & Anti-Virus (EICAR) Detection
Never test filters with real malware! Use the industry-standard, harmless GTUBE (spam trigger) and EICAR (antivirus trigger) test strings:
# 1. Test Spam Filter with the standard GTUBE signature
swaks --to testuser@yourdomain.com --from spamtest@example.org --server localhost \
--header "Subject: GTUBE Spam Filter Test" \
--body "XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X"
# 2. Test ClamAV Antivirus with the standard EICAR signature
swaks --to testuser@yourdomain.com --from virustest@example.org --server localhost \
--header "Subject: EICAR Antivirus Test" \
--body 'X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*'
# 3. Inspect /var/log/mail.log to verify detection
sudo tail -n 25 /var/log/mail.log
8. Webmail Access with Roundcube
To access your mailboxes from any browser with a modern interface, deploy Roundcube Webmail connected locally to Dovecot (IMAPS :993) and Postfix (Submission :587):
Since your VPS already runs Nginx, running Roundcube in an isolated container bound to 127.0.0.1:8090 keeps PHP and Apache dependencies off your host OS:
services:
roundcube:
image: docker.io/roundcube/roundcubemail:latest
container_name: roundcube-webmail
restart: unless-stopped
ports:
- "127.0.0.1:8090:80"
environment:
- ROUNDCUBEMAIL_DEFAULT_HOST=ssl://mail.yourdomain.com
- ROUNDCUBEMAIL_DEFAULT_PORT=993
- ROUNDCUBEMAIL_SMTP_SERVER=tls://mail.yourdomain.com
- ROUNDCUBEMAIL_SMTP_PORT=587
- ROUNDCUBEMAIL_UPLOAD_MAX_FILESIZE=25M
volumes:
- roundcube_db:/var/roundcube/db
- roundcube_config:/var/roundcube/config
volumes:
roundcube_db:
roundcube_config:
9. Operations: Queue Management, Logs & Troubleshooting
Postfix Queue Management Cheat Sheet
| Command | Action & Purpose |
|---|---|
mailq or postqueue -p |
List all messages currently waiting in the active, deferred, or hold queues. |
sudo postcat -q <QUEUE_ID> |
Inspect the full headers and body of a specific queued message. |
sudo postqueue -f |
Flush the queue: immediately retry delivery for all deferred messages. |
sudo postsuper -h <QUEUE_ID> |
Place a suspicious message on hold so Postfix stops retrying it. |
sudo postsuper -d <QUEUE_ID> |
Permanently delete a specific message from the queue. |
sudo postsuper -d ALL deferred |
Emergency cleanup: delete all deferred messages from the queue. |
Common Troubleshooting Scenarios
1. Gmail Rejects Outgoing Mail with 550-5.7.1 or 550-5.7.26
Cause: Google strictly enforces two requirements for all senders:
1. Valid Forward-Confirmed Reverse DNS (PTR) matching your EHLO hostname (mail.yourdomain.com).
2. Passing SPF (v=spf1 ...) AND DKIM (2048-bit RSA) signatures with a published _dmarc policy.
Fix: Test your live score at mail-tester.com and verify dig -x <YOUR_IP> +short returns mail.yourdomain.com..
2. Mail Client Cannot Send: SASL authentication failure: cannot connect to Dovecot auth
Cause: Postfix runs inside a chroot jail at /var/spool/postfix on Debian/Ubuntu. If Dovecot creates its socket at /var/run/dovecot/auth-client instead of inside the Postfix chroot, Postfix cannot reach it.
Fix: Ensure /etc/dovecot/conf.d/10-master.conf creates the listener at /var/spool/postfix/private/auth with user = postfix, group = postfix, and mode = 0660.
3. Outbound Emails Stay Stuck in deferred Queue (Connection timed out on port 25)
Cause: Your cloud/VPS provider has a platform-level firewall blocking outbound TCP port 25.
Fix: Open a support ticket with your VPS provider (e.g., Hetzner, Netcup, DigitalOcean) to request unblocking outbound Port 25 after verifying your account, or configure an authenticated SMTP Relay (relayhost = [smtp.relayprovider.com]:587) in main.cf.
4. How Do I Verify My Server achieves a 10/10 Deliverability Score?
Run this quick verification checklist from your terminal: