Why Your Server Emails Land in Spam
If you have ever sent a password reset email, an order confirmation, or a notification from your web server and watched it disappear into a recipient's spam folder, you are not alone. Email delivery failures from servers are one of the most common technical problems small businesses and developers encounter when building automated email features into websites or applications.
The root causes are usually straightforward: the sending server has no established reputation, the domain lacks proper authentication records, and the email content may trigger spam filters without those safeguards in place. Fixing these issues requires configuring your mail server correctly and publishing the right DNS records.
Understanding Email Authentication on Linux Servers
When a mail server receives an incoming email, it performs several checks to decide whether to deliver it to the inbox or mark it as spam. These checks look at the sending server's IP reputation, whether the domain has authorised that server to send email, and whether the message content appears legitimate.
Three protocols work together to verify email authenticity: SPF, DKIM, and DMARC. Together they tell receiving servers that your emails genuinely come from your domain and have not been tampered with in transit. Configuring all three is the foundation of reliable email delivery.
For a detailed walkthrough of setting up the full email stack on Ubuntu, the guide to configuring email systems and SMTP on Ubuntu covers the foundational steps before diving into authentication records.
SPF: Specifying Which Servers Can Send Email for Your Domain
Sender Policy Framework (SPF) is a DNS record that lists every server permitted to send email on behalf of your domain. When a receiving server gets an email from your domain, it looks up your SPF record and checks whether the sending server's IP address appears on the approved list.
An SPF record is a TXT record added to your domain's DNS settings. A basic record that authorises only your own server looks like this:
v=spf1 mx ip4:YOUR_SERVER_IP ~all
This record states that the MX servers listed in your DNS and the specific IP address you specify are the only servers allowed to send email for your domain. The ~all directive marks any email from unlisted servers as a softfail, which is the standard approach for most configurations. Use -all only when you are certain you have accounted for every legitimate sending source.
If you use Google Workspace or Microsoft 365 for your primary business email but send transactional emails from your own server, include both in the SPF record:
v=spf1 include:_spf.google.com ip4:YOUR_SERVER_IP ~all
SPF has a lookup limit of 10 DNS queries per check. Exceeding this limit causes the record to fail silently. Use include: directives sparingly and avoid nested includes that multiply lookups.
DKIM: Adding a Digital Signature to Outgoing Emails
DomainKeys Identified Mail (DKIM) attaches a cryptographic signature to every outgoing email. The receiving server uses a public key published in your DNS to verify that signature. If the signature is valid, the email was not modified after leaving your server and originated from an authorised system.
OpenDKIM is the standard implementation for adding DKIM signing on Linux servers running Postfix. The process involves installing the software, generating a key pair, publishing the public key, and configuring Postfix to sign outgoing mail.
Install OpenDKIM and its tools:
sudo apt install opendkim opendkim-tools
sudo mkdir -p /etc/opendkim/keys/yourdomain.com
sudo opendkim-genkey -b 2048 -d yourdomain.com -D /etc/opendkim/keys/yourdomain.com -s mail -v
sudo chown -R opendkim:opendkim /etc/opendkim/keys/yourdomain.com
sudo chmod 600 /etc/opendkim/keys/yourdomain.com/mail.private
The key generation command creates two files: mail.private (the private key used for signing) and mail.txt (the public key to publish in DNS). View the public key:
cat /etc/opendkim/keys/yourdomain.com/mail.txt
Publish the contents of mail.txt as a TXT record in your DNS. The record name follows the format mail._domainkey.yourdomain.com, where mail is the selector specified during key generation.
Configure OpenDKIM by editing its configuration file:
sudo nano /etc/opendkim.conf
Domain yourdomain.com
KeyFile /etc/opendkim/keys/yourdomain.com/mail.private
Selector mail
Socket inet:8891@localhost
Connect OpenDKIM to Postfix by adding these settings to your Postfix main configuration:
sudo nano /etc/postfix/main.cf
milter_protocol = 2
milter_default_action = accept
smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891
Restart both services to apply the changes:
sudo systemctl restart opendkim postfix
DMARC: Defining Your Domain's Email Policy
DMARC builds on SPF and DKIM by instructing receiving servers on how to handle emails that fail authentication. It also sends aggregate reports back to you, showing how many emails were sent on behalf of your domain and how many passed or failed authentication checks.
A basic DMARC TXT record at _dmarc.yourdomain.com looks like this:
v=DMARC1; p=quarantine; rua=mailto:[email protected]; pct=100
This record instructs receiving servers to quarantine emails that fail DMARC checks, and to send aggregate reports to the specified address. Setting pct=100 applies the policy to all emails; you can lower this value during initial testing to apply the policy to only a percentage of messages.
Once you have verified that SPF and DKIM are working correctly over a period of observation, you can tighten the policy to reject failing emails outright:
v=DMARC1; p=reject; rua=mailto:[email protected]; pct=100
Switching to p=reject is the strictest option and prevents any server that fails authentication from delivering mail to your domain's recipients. Only make this change after confirming your authentication setup is solid.
Configuring Postfix for Better Email Delivery
Postfix is the default mail transfer agent on Ubuntu and many other Linux distributions. Beyond authentication records, Postfix itself has settings that affect how emails are treated by receiving servers. Proper configuration ensures your server behaves as a trustworthy sender.
Edit the Postfix main configuration file:
sudo nano /etc/postfix/main.cf
Set the following parameters to define your server's identity and enforce TLS encryption:
myhostname = mail.yourdomain.com
mydomain = yourdomain.com
myorigin = $mydomain
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
relayhost =
smtp_tls_security_level = encrypt
smtp_tls_wrappermode = no
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
smtp_header_checks = regexp:/etc/postfix/smtp_header_checks
Add header rewrite rules to ensure the From address always matches your domain, which prevents emails from appearing to come from third-party services without proper authentication:
/etc/postfix/smtp_header_checks:
/^From:.*@yourdomain.com/ OK
/^From:.*/ REPLACE From: [email protected]
Compile and apply the header check rules:
sudo postmap /etc/postfix/smtp_header_checks
sudo systemctl restart postfix
A complete walkthrough of configuring Postfix with SMTP authentication covers these steps in more detail alongside additional hardening options for production servers.
Testing Your Email Authentication Setup
Before sending emails to real recipients, verify that your authentication records are correctly published and working. Testing early catches configuration errors before they affect real deliveries.
The mail-tester.com service from Sinch analyses emails for spam indicators and reports on SPF, DKIM, and DMARC status. Install a simple SMTP testing tool and send a test message:
sudo apt install swaks
swaks --to [email protected] --from [email protected] \
--server mail-tester.com --port 25 --tls
The service returns a score out of ten with specific advice on what to fix. Aiming for 8/10 or higher before sending production email gives you a reasonable baseline for deliverability.
You can also verify your DNS records directly from the command line using the dig utility:
dig TXT yourdomain.com +short # SPF record
dig TXT mail._domainkey.yourdomain.com +short # DKIM public key
dig TXT _dmarc.yourdomain.com +short # DMARC record
If these commands return no output, the records have not been published or are still propagating. DNS changes typically become visible within minutes, though full global propagation can take up to 48 hours in some cases.
Why Emails May Still Land in Spam After Configuration
Even with SPF, DKIM, and DMARC correctly configured, some emails may still end up in spam. Authentication records are foundational, but they do not override every spam filter signal.
IP reputation issues: If the server IP was previously used for bulk mailing or was flagged for abuse, its reputation may be poor. Check the IP against major blocklists using tools like the MX Toolbox blacklist checker. Many hosting providers will assign a different IP if you explain the situation and demonstrate the IP was not intentionally misused.
Email content triggers: Certain words, phrases, and formatting patterns activate spam filters. Avoid excessive capitalisation, multiple exclamation marks, words like "free", "click here", "act now", and other patterns commonly associated with marketing spam. Include genuine plain text alongside any HTML content.
Missing plain text alternative: HTML-only emails with no plain text version are frequently flagged by spam filters. When using PHPMailer or similar libraries, always set both a HTML body and a plain text alternative:
$mail->Body = '<html><body>...</body></html>';
$mail->AltBody = 'Plain text version of your message.';
Sudden volume spikes: Sending a large volume of email from a new server IP raises immediate suspicion. Warm up new sending infrastructure by gradually increasing volume over two to four weeks, starting with a small number of daily emails and building up steadily.
When to Use a Transactional Email Service Instead
For high-volume sending or business-critical email delivery, transactional email services are often a better choice than managing your own server. Services such as SendGrid, Mailgun, Postmark, and Amazon SES maintain established sender reputations, provide delivery analytics, and handle authentication configuration automatically.
If your application already uses PHPMailer or a similar library, switching to a transactional service requires only changing the SMTP settings. Your application code remains largely the same:
$mail->isSMTP();
$mail->Host = 'smtp.sendgrid.net';
$mail->SMTPAuth = true;
$mail->Username = 'apikey';
$mail->Password = 'your_sendgrid_api_key';
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 587;
The API key replaces a traditional password, and these services provide detailed reporting dashboards, webhook integrations, and bounce handling that would require significant development work to replicate on a self-managed server.
For UK businesses considering email relay services, setting up a secure email relay with Mailgun and Postfix combines the control of self-managed infrastructure with the reputation benefits of a dedicated email service.
Building a Reliable Email Setup
Getting email reliably delivered from a self-managed Linux server takes more than installing Postfix and sending messages. SPF, DKIM, and DMARC work together to prove your domain's identity to receiving mail servers. Postfix configuration ensures your server presents itself correctly and uses modern encryption. Testing before sending to real recipients catches configuration errors early.
If you have followed the steps above and emails are still not reaching inboxes, or if you would prefer hands-on help setting up your server's email configuration, you can get in touch with details of your current setup and what you are trying to achieve.