How To

Configure Postfix as Send-Only SMTP Server on Ubuntu 24.04 / 22.04

Postfix is the default mail transfer agent (MTA) on Ubuntu and one of the most widely deployed in production. A send-only Postfix configuration handles outgoing email from your server, such as system alerts, cron job notifications, application emails – without accepting inbound mail. This guide walks through installing and hardening Postfix on Ubuntu 24.04 / 22.04 with TLS encryption, SPF, DKIM, and DMARC authentication so your emails actually reach inboxes instead of spam folders.

Original content from computingforgeeks.com - post 4029

Without proper email authentication, most providers (Gmail, Outlook, Yahoo) will reject or spam-folder your messages. We cover every step needed to get legitimate email delivery from a Linux server.

What You Need

  • Ubuntu 24.04 or 22.04 server with root or sudo access
  • A domain name with DNS access (to set SPF, DKIM, DMARC records)
  • Port 25 outbound open (some cloud providers block this by default – check with your provider)
  • A valid FQDN hostname (e.g. mail.example.com) with an A record pointing to your server IP

Step 1: Set Server Hostname

Postfix uses the system hostname in outgoing email headers and the EHLO greeting. Set it to a fully qualified domain name that has a matching DNS A record:

sudo hostnamectl set-hostname mail.example.com

Verify the hostname is set correctly:

hostname -f

Step 2: Install Postfix and Mail Utilities

Update the package index and install Postfix along with the mailutils package for command-line email sending:

sudo apt update
sudo apt install -y mailutils

The mailutils package pulls in Postfix as a dependency. During installation, the Postfix configuration dialog appears. Select Internet Site and set the system mail name to your domain.

If you want to skip the interactive prompts entirely, pre-seed the answers and install non-interactively:

sudo debconf-set-selections <<< "postfix postfix/mailname string mail.example.com"
sudo debconf-set-selections <<< "postfix postfix/main_mailer_type string 'Internet Site'"
sudo DEBIAN_FRONTEND=noninteractive apt install -y mailutils

Verify Postfix is installed and running:

postconf mail_version
systemctl is-active postfix

On Ubuntu 24.04, this installs Postfix 3.8.x. Ubuntu 22.04 ships Postfix 3.6.x.

Step 3: Configure Postfix as Send-Only

The default Postfix installation listens on all interfaces and accepts incoming mail. For a send-only server, lock it down to the loopback interface so it only processes emails originating from the local system.

Open the main Postfix configuration file:

sudo vim /etc/postfix/main.cf

Set the following directives. You can also apply them directly using postconf -e:

sudo postconf -e 'myhostname = mail.example.com'
sudo postconf -e 'mydomain = example.com'
sudo postconf -e 'myorigin = $myhostname'
sudo postconf -e 'inet_interfaces = loopback-only'
sudo postconf -e 'inet_protocols = all'
sudo postconf -e 'mydestination = $myhostname, localhost.$mydomain, localhost'
sudo postconf -e 'mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128'
sudo postconf -e 'default_transport = smtp'
sudo postconf -e 'relay_transport = smtp'
sudo postconf -e 'smtp_tls_security_level = may'
sudo postconf -e 'smtp_tls_loglevel = 1'
sudo postconf -e 'smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt'
sudo postconf -e 'smtpd_banner = $myhostname ESMTP'
sudo postconf -e 'mailbox_size_limit = 0'
sudo postconf -e 'recipient_delimiter = +'
sudo postconf -e 'biff = no'
sudo postconf -e 'append_dot_mydomain = no'

Here is what each key setting does:

DirectivePurpose
inet_interfaces = loopback-onlyOnly listen on 127.0.0.1 – blocks all incoming SMTP from the network
myorigin = $myhostnameSets the sender domain in outgoing mail headers
smtp_tls_security_level = mayUse TLS when the receiving server supports it (opportunistic encryption)
smtpd_banner = $myhostname ESMTPMinimal banner – hides Postfix version from scanners
mynetworks = 127.0.0.0/8Only localhost can relay through this server

Restart Postfix to apply the configuration:

sudo systemctl restart postfix

Confirm Postfix is listening only on the loopback interface:

ss -tlnp | grep :25

You should see it bound to 127.0.0.1 only:

LISTEN 0      100        127.0.0.1:25         0.0.0.0:*
LISTEN 0      100            [::1]:25            [::]:*

Step 4: Set Up DNS Records (SPF and DMARC)

Email authentication starts with DNS. Without SPF and DMARC records, Gmail and other providers will reject or junk your messages. You need three DNS records for your sending domain.

A Record

Create an A record for your mail hostname pointing to your server IP. This must match the myhostname value in Postfix:

mail.example.com.    IN    A    192.168.1.10

SPF Record

SPF (Sender Policy Framework) tells receiving servers which IPs are authorized to send email for your domain. Add a TXT record to your domain’s DNS:

mail.example.com.    IN    TXT    "v=spf1 ip4:192.168.1.10 -all"

The -all (hard fail) means any server not listed should be rejected. Use ~all (soft fail) during initial testing if you are not sure about your setup.

DMARC Record

DMARC tells receiving servers what to do when SPF or DKIM checks fail. Add a TXT record at _dmarc.mail.example.com:

_dmarc.mail.example.com.    IN    TXT    "v=DMARC1; p=quarantine; rua=mailto:[email protected]; pct=100"

The p=quarantine policy sends failing emails to spam. Once you confirm everything works, change to p=reject for maximum protection. The rua address receives aggregate DMARC reports.

Verify your DNS records have propagated:

dig +short mail.example.com A
dig +short mail.example.com TXT
dig +short _dmarc.mail.example.com TXT

Step 5: Configure DKIM with OpenDKIM

DKIM (DomainKeys Identified Mail) adds a cryptographic signature to every outgoing email, proving it came from your server and was not modified in transit. This is mandatory for reliable delivery to Gmail and Outlook.

Install OpenDKIM and the key generation tools:

sudo apt install -y opendkim opendkim-tools

Generate the DKIM Key Pair

Create the key directory and generate a 2048-bit RSA key pair:

sudo mkdir -p /etc/opendkim/keys/mail.example.com
sudo opendkim-genkey -b 2048 -d mail.example.com -D /etc/opendkim/keys/mail.example.com -s default -v
sudo chown -R opendkim:opendkim /etc/opendkim
sudo chmod 600 /etc/opendkim/keys/mail.example.com/default.private

Display the public key that needs to be added to DNS:

sudo cat /etc/opendkim/keys/mail.example.com/default.txt

The output contains the DKIM public key in DNS TXT record format. Copy the value inside the quotes and create a TXT record at default._domainkey.mail.example.com in your DNS provider. Combine all quoted strings into one continuous value without spaces.

Configure OpenDKIM

Replace the default OpenDKIM configuration:

sudo vim /etc/opendkim.conf

Add the following configuration:

AutoRestart             Yes
AutoRestartRate         10/1h
Syslog                  yes
SyslogSuccess           Yes
LogWhy                  Yes
Canonicalization        relaxed/simple
ExternalIgnoreList      refile:/etc/opendkim/TrustedHosts
InternalHosts           refile:/etc/opendkim/TrustedHosts
KeyTable                refile:/etc/opendkim/KeyTable
SigningTable            refile:/etc/opendkim/SigningTable
Mode                    sv
PidFile                 /run/opendkim/opendkim.pid
SignatureAlgorithm      rsa-sha256
UserID                  opendkim:opendkim
Socket                  inet:12301@localhost

Create the trusted hosts file. This defines which hosts are allowed to send mail through OpenDKIM:

sudo vim /etc/opendkim/TrustedHosts

Add the following entries:

127.0.0.1
localhost
mail.example.com

Create the key table that maps selectors to key files:

sudo vim /etc/opendkim/KeyTable

Add this line (all on one line):

default._domainkey.mail.example.com mail.example.com:default:/etc/opendkim/keys/mail.example.com/default.private

Create the signing table that maps sender addresses to DKIM selectors:

sudo vim /etc/opendkim/SigningTable

Add this line to sign all mail from your domain:

*@mail.example.com default._domainkey.mail.example.com

Connect Postfix to OpenDKIM

Tell Postfix to pass all outgoing mail through the OpenDKIM milter for signing:

sudo postconf -e 'milter_protocol = 6'
sudo postconf -e 'milter_default_action = accept'
sudo postconf -e 'smtpd_milters = inet:localhost:12301'
sudo postconf -e 'non_smtpd_milters = inet:localhost:12301'

Create the OpenDKIM runtime directory and restart both services:

sudo mkdir -p /run/opendkim
sudo chown opendkim:opendkim /run/opendkim
sudo systemctl restart opendkim
sudo systemctl restart postfix

Verify both services are running:

sudo systemctl status opendkim --no-pager | head -5
sudo systemctl status postfix --no-pager | head -5

Test the DKIM key against DNS to confirm the public key matches:

sudo opendkim-testkey -d mail.example.com -s default -vvv

You should see key OK in the output. The key not secure warning is normal and just means DNSSEC is not configured for your domain.

Step 6: Test Email Delivery

Send a test email to verify everything works end-to-end – Postfix sends the email, OpenDKIM signs it, and the receiving server validates SPF, DKIM, and DMARC:

echo "Test email from Postfix on Ubuntu 24.04 with SPF, DKIM, and DMARC." | mail -s "Postfix Authentication Test" [email protected]

Check the mail log to confirm delivery:

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

A successful delivery looks like this in the logs:

opendkim[4512]: DB62740470: DKIM-Signature field added (s=default, d=mail-test.computingforgeeks.com)
postfix/smtp[4925]: Trusted TLS connection established to gmail-smtp-in.l.google.com[142.251.127.27]:25: TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
postfix/smtp[4925]: DB62740470: to=<[email protected]>, relay=gmail-smtp-in.l.google.com[142.251.127.27]:25, delay=0.63, dsn=2.0.0, status=sent (250 2.0.0 OK)

Three things to verify in the log: the DKIM signature was added, the connection used TLS (TLSv1.3), and the status is sent with a 250 response code.

Verify Authentication in Gmail

Open the received email in Gmail and click the three dots menu, then Show original. Look for these headers:

SPF:   PASS
DKIM:  PASS
DMARC: PASS

All three should show PASS. If SPF fails, check your DNS TXT record contains the correct server IP. If DKIM fails, verify the public key in DNS matches the one generated by opendkim-genkey.

Using Postfix in Scripts and Applications

A send-only Postfix server is most useful for automated notifications. Here are common integration patterns.

Sending from Cron Jobs

Cron can email job output directly. Set the MAILTO variable in your crontab:

sudo crontab -e

Add the MAILTO line at the top, then your cron job:

[email protected]
0 2 * * * /usr/local/bin/backup.sh

Any output from the script (stdout or stderr) gets emailed automatically. For a cleaner approach, send explicit emails from your script:

echo "Backup completed at $(date). Size: $(du -sh /backups/latest | cut -f1)" | mail -s "Daily Backup Report" [email protected]

Sending from Python Applications

Python’s built-in smtplib can connect to the local Postfix instance on port 25:

import smtplib
from email.mime.text import MIMEText

msg = MIMEText("Server disk usage is above 90%")
msg["Subject"] = "Disk Alert: /dev/sda1"
msg["From"] = "[email protected]"
msg["To"] = "[email protected]"

with smtplib.SMTP("localhost", 25) as server:
    server.send_message(msg)

Relaying Through Gmail SMTP

If your cloud provider blocks port 25 or you want to send email through your Gmail account instead of directly, configure Postfix to relay through Gmail’s SMTP servers. This avoids IP reputation issues common with cloud server IPs.

Managing the Mail Queue

Postfix queues emails that cannot be delivered immediately. Use the Postfix administration commands to manage the queue:

sudo mailq

An empty queue means all emails have been delivered. If emails are stuck, force a delivery attempt or clear them:

sudo postqueue -f
sudo postsuper -d ALL deferred

Check Postfix mail statistics from logs to monitor delivery rates and identify issues over time.

Troubleshooting Common Issues

Gmail rejects with “550-5.7.26 unauthenticated sender”

This means SPF or DKIM failed. Check that your SPF TXT record contains the correct server IP and that the myorigin domain in Postfix matches the domain in your SPF record. Verify DKIM with sudo opendkim-testkey -d your.domain -s default -vvv.

Emails stuck in deferred queue with “Connection timed out”

Your server cannot reach port 25 on the destination mail server. Many cloud providers (AWS, GCP, Azure) block outbound port 25 by default. Request port 25 unblock from your provider, or configure Postfix to relay through an external SMTP service on port 587.

OpenDKIM fails with “key not found in DNS”

DNS propagation can take up to an hour. Verify the record exists with dig +short default._domainkey.mail.example.com TXT. If empty, check that you created the TXT record at the correct subdomain in your DNS provider. Also ensure the DKIM public key value was copied completely without any line breaks or missing characters.

Postfix sends email from wrong domain

The myorigin directive controls the default sender domain. If emails show user@localhost or user@hostname instead of your domain, set myorigin to your FQDN and restart Postfix. Also check that /etc/mailname contains the correct domain.

Conclusion

Your Ubuntu server now has a properly configured send-only Postfix installation with TLS encryption and full email authentication (SPF, DKIM, DMARC). Every outgoing email is cryptographically signed and verifiable, which means it will pass Gmail, Outlook, and Yahoo authentication checks. For servers that need to receive email as well, check our guide on setting up a full mail server with Postfix, Dovecot, and Roundcube.

Related Articles

Ubuntu How To Install Tor Browser on Ubuntu 24.04 Storage Install Pydio Cells File Sharing on Ubuntu 24.04 Automation Setup Consul Cluster on Ubuntu 24.04 / Debian 13 Ubuntu How To Setup Flarum discussion forum on Ubuntu 22.04

Leave a Comment

Press ESC to close