Email Authentication and Security

From SME Server
Jump to navigationJump to search

A Practical Guide for AdministratorsMarch 2026

This guide documents the lessons learned configuring complete email authentication (SPF, DKIM, DMARC) and spam/security hardening across multiple production domains on Koozali SME Server v10. It is a complement to the SME documentation. Many of these issues are either specific to SME v10, or involve SME-specific behaviors that differ from generic qmail or qpsmtpd guidance.

The guide covers: getting DKIM to actually sign mail (a common stumbling block), achieving Forward Confirmed Reverse DNS alignment, hardening bounce behavior, tuning spam filtering, and understanding the limits of authentication against modern social-engineering attacks.

Commands assume root access on an SME v10 server. GoDaddy is the registrar for the domains used as examples here; other registrars may have different interfaces or requirements for DNS record management.


Important.png Note:
All persistent configuration must be applied using the SME database and template system. Editing generated files directly is inadvisable — changes will be silently overwritten on the next signal-event run.


Part 1: SPF Configuration

SPF (Sender Policy Framework) tells receiving servers which hosts are authorized to send mail for your domain. On SME v10, there are two IPs that typically need to be in scope: the server's own IP and the relay/smarthost your ISP or data center provides.

The Relay IP Problem

A common misconfiguration is publishing only the server's primary IP in the SPF record, omitting the relay. If your host routes outbound mail through a smarthost, some or all outbound messages will originate from that relay's IP — and receiving servers will see an SPF fail for your domain.

Include both the server IP and the relay in your SPF record. If your hosting provider has allocated you a subnet, use that rather than individual IP addresses to future-proof the record:

; Preferred — subnet covers all current and future IPs at this provider
v=spf1 mx ip4:206.214.166.0/24 ~all

; Also acceptable — explicit IPs if the subnet approach is not appropriate
v=spf1 mx ip4:203.0.113.10 ip4:203.0.113.6 ~all

Common Pitfalls

  • The deprecated ptr mechanism (v=spf1 ptr ...) should not be used. It is slow, unreliable, and ignored by many receivers.
  • Using -all (hard fail) is aggressive and appropriate only after you are confident your SPF record is complete. ~all (soft fail) is the safer setting during configuration and testing.
  • Each domain hosted on the server needs its own SPF record published in DNS. A record on the primary domain does not cover other hosted domains.

Part 2: DKIM on SME v10

DKIM (DomainKeys Identified Mail) signs outbound messages cryptographically, allowing receivers to verify that a message was sent by an authorized server and was not modified in transit. Getting DKIM working on SME v10 requires three things to be correct simultaneously: keys in the right location, the DKIMSigning property enabled, and a signal-event to regenerate the configuration. Missing any one of them produces the same frustrating result: dkim: skip, DKIM not configured for [domain] in your logs.

The Default Key Fallback

SME v10 also recognizes a server-wide default key at:

/home/e-smith/dkim_keys/default/

This key is used as a fallback for any domain that does not have its own per-domain key directory under /home/e-smith/dkim_keys/. If you are bringing up DKIM for the first time and want immediate coverage for all domains on the server before per-domain keys are configured, placing a key here will sign mail for all of them.

Most server will work great with this default key, you will only need to enable the signing of dkim

db configuration setprop qpsmtpd DKIMSigning enabled
signal-event email-update

then you could get the important information you need to add to your DNS provider interface for SPF, DKIM and DMARC doing:

#qpsmtpd-dns
Here are sample DNS entries you should add in your public DNS.

There are two DKIM key copies.
Depending on your provider you might be able to copy these as is.

The first has a complete DKIM key with no "" breaks.

The second has the DKIM entry broken into 255 character chunks
with quotes for providers who cannot support long strings.
You may need to separate these with either a space, a newline or 
a backslash escaped newline between the "" depending on your 
dns provider.

You should either change the reporting email address for DMARC 
or create the needed pseudonym 'dmarc-feedback'.

DKIM complete
=============
 
default._domainkey IN TXT v=DKIM1;p=YOURPUBLICKEYWILLPRINTHERE;t=y
 
DKIM in 255 character chunks
============================
 
default._domainkey IN TXT "v=DKIM1;p=YOURPUBLICKEYWILLPRINTHERE;t=y"


DMARC records
=============
@ IN SPF "v=spf1 mx a -all"
@ IN TXT "v=spf1 mx a -all"
_dmarc IN TXT "v=DMARC1; p=none; adkim=s; aspf=r; rua=mailto:dmarc-feedback@YOURDOMAIN.YOURTLD; pct=100"

Remark the t=y for test mode enabled. This will allow you to test that everything is ok, before enforce really the rejection of emails that are not signed, then change to t=n.


Per-domain keys are still the recommended architecture — they allow independent rotation and revocation per domain, and make auditing straightforward. The default key is best understood as a fallback or a starting point, not a long-term substitute on complex multiple domains installation.

The Authoritative Key Location

The SME v10 documentation contains conflicting references. Some wiki pages reference ~smtpd/config/dkim/[1] and others reference /etc/qpsmtpd/dkim/ need ref.. Neither of these is the correct location for v10.

The canonical key location for Koozali SME v10 is:

/home/e-smith/dkim_keys/[domain]/

Under that directory, SME expects two files:

/home/e-smith/dkim_keys/example.com/selector    # contains the selector string, e.g. feb2026
/home/e-smith/dkim_keys/example.com/default     # the private key (PEM format)

After signal-event email-update, SME's template system automatically creates symlinks from /var/service/qpsmtpd/config/dkim/ pointing to these source files.


Important.png Note:
Do not manage those symlinks manually — they are owned by the template system.


Generating Keys

Use openssl to generate a 2048-bit RSA keypair. Create a separate keypair for each domain — per-domain keys allow rotation, revocation, and traceability independent of other domains on the same server.

# Create the directory for this domain
mkdir -p /home/e-smith/dkim_keys/example.com

# Generate the private key
openssl genrsa -out /home/e-smith/dkim_keys/example.com/default 2048

# Extract the public key
openssl rsa -in /home/e-smith/dkim_keys/example.com/default -pubout \
  -out /home/e-smith/dkim_keys/example.com/default.pub

# Write the selector string
echo "feb2026" > /home/e-smith/dkim_keys/example.com/selector

# Set correct ownership and permissions
chown -R qpsmtpd:qpsmtpd /home/e-smith/dkim_keys/example.com
chmod 400 /home/e-smith/dkim_keys/example.com/default

The same procedure applies to create the server-wide default key. Use /home/e-smith/dkim_keys/default/ as the directory and publish the resulting public key for all domains that will rely on it.

Enabling DKIM Signing

The DKIMSigning property must be explicitly set in the qpsmtpd configuration. This is separate from having keys in place and is a common omission:

db configuration setprop qpsmtpd DKIMSigning enabled
signal-event email-update

After signal-event completes, verify that symlinks were created:

ls -la /var/service/qpsmtpd/config/dkim/
# Should show symlinks pointing to /home/e-smith/dkim_keys/[domain]/

Publishing the DNS Record

The public key is published as a TXT record under the selector._domainkey subdomain. Extract the raw public key bytes (stripping PEM headers and whitespace) and format it as follows:

; DNS TXT record name:
feb2026._domainkey.example.com

; DNS TXT record value:
v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...[base64 key]...IDAQAB

To get all the needed field easily formated for your DNS provider (there are 2 different expected output depending on the provider), you can use this command

qpsmtpd-dns exampledomain.com

Or you can try manually to extract the public key in the correct format:

openssl rsa -in /home/e-smith/dkim_keys/example.com/default \
  -pubout -outform DER 2>/dev/null | openssl base64 -A

Verifying DKIM Signing

Send a test message and check the qpsmtpd log. A successful signing entry looks like:

dkim: pass, we signed the message

If you see dkim: skip, DKIM not configured for [domain], work through this checklist:

  • Keys are in /home/e-smith/dkim_keys/[domain]/ (not /etc/qpsmtpd/dkim/)
  • Ownership is qpsmtpd:qpsmtpd on all key files
  • Private key permissions are 400
  • The selector file exists and contains only the selector string (no trailing newline issues)
  • DKIMSigning property is set to enabled (db configuration show qpsmtpd | grep DKIM)
  • signal-event email-update has been run after the above changes
  • If no per-domain key directory exists, check whether /home/e-smith/dkim_keys/default/ is present and correctly configured

Selector Naming Convention

Use dated selectors (e.g., feb2026) rather than generic names like default or mail. Dated selectors make it straightforward to track when keys were generated, facilitate audits, and simplify rotation — you can publish a new key under a new selector name and migrate gracefully without downtime.

If You Had Keys in the Wrong Location

If you previously generated keys at /etc/qpsmtpd/dkim/ or another location, copy them to the canonical location rather than regenerating. This will avoid having to re-publish DNS records.

# Copy existing keys to canonical location
cp -a /etc/qpsmtpd/dkim/example.com /home/e-smith/dkim_keys/

# Fix ownership
chown -R qpsmtpd:qpsmtpd /home/e-smith/dkim_keys/example.com

# Archive the old location — do not delete until DKIM is confirmed working
mv /etc/qpsmtpd/dkim /etc/qpsmtpd/dkim.OLD-backup

db configuration setprop qpsmtpd DKIMSigning enabled
signal-event email-update

Part 3: DMARC Configuration

DMARC (Domain-based Message Authentication, Reporting & Conformance) ties SPF and DKIM together and tells receiving servers what to do with messages that fail authentication. It also enables reporting so you can see how your domain's mail is being received in the wild.

Basic Policy Record

; Monitoring-only policy — collects reports, takes no enforcement action
_dmarc.example.com TXT "v=DMARC1; p=none; adkim=r; aspf=r; rua=mailto:dmarc@example.com"

; Quarantine policy — failed messages go to spam
_dmarc.example.com TXT "v=DMARC1; p=quarantine; adkim=r; aspf=r; rua=mailto:dmarc@example.com"

; Enforcement — failed messages rejected
_dmarc.example.com TXT "v=DMARC1; p=reject; adkim=r; aspf=r; rua=mailto:dmarc@example.com"

Alignment Tags

The adkim=r and aspf=r tags specify relaxed alignment, which allows subdomain matches. For example, relaxed DKIM alignment permits a message signed with a key for mail.example.com to satisfy DMARC for example.com. This is the correct setting for most SME installations where the MX hostname is a subdomain of the domain.

Strict alignment (adkim=s, aspf=s) requires an exact match between the authenticated domain and the From: header domain. This is appropriate only if you have complete control over all sending paths.

Reporting

The rua tag specifies where aggregate reports (XML digests of authentication results) are sent. If you are receiving reports for multiple domains, consider using a dedicated mailbox or a third-party DMARC reporting service such as EasyDMARC for parsing and visualization.

If the rua address is on a different domain than the domain being reported on, that external domain must publish a DNS record explicitly permitting the reporting:

; On the reporting domain (reportinghost.com), authorize reports for source.com:
source.com._report._dmarc.reportinghost.com TXT "v=DMARC1"

Collect at least 2–4 weeks of monitoring data at p=none before moving to p=quarantine, and a similar amount of time at quarantine before moving to p=reject.


Important.png Note:
DMARC enforcement breaks legitimate mail sent on your behalf by mailing lists, forwarding services, and marketing platforms unless those sending paths are properly authenticated.


Part 4: Forward-Confirmed Reverse DNS (FCrDNS) Alignment

Many receiving mail servers perform FCrDNS checks: they look up the PTR record for the connecting server's IP, then verify that the resulting hostname resolves back to the same IP via an A record. If this check fails, or if the PTR hostname does not match what the server announces in SMTP HELO/EHLO, the message is more likely to be flagged or rejected.

This is particularly relevant if your server is a VM running in a managed hypervisor environment, such as at a commercial hosting company. In that case, the hosting company controls PTR records — you will need to request the correct value from them.

Three things must agree:

  • The PTR record for the server's IP must resolve to its FQDN (e.g., nowata.example.com)
  • That FQDN must have an A record pointing back to the same IP
  • The server's HELO/EHLO announcement must match that FQDN

Configuring the HELO Announcement

On SME v10, the server's HELO string is controlled by the HeloHost property of qpsmtpd. Set it to the server's FQDN and run signal-event to apply:

db configuration setprop qpsmtpd HeloHost nowata.example.com
signal-event email-update

# Verify
db configuration show qpsmtpd | grep HeloHost

PTR Record

PTR records are managed by your hosting provider or ISP, not by your own DNS. Contact your provider with the desired PTR value. On servers shared with multiple domains, keep the PTR pointed to the server's own FQDN (the hostname) rather than any of the hosted domain names.

PTR instability — the record reverting to an unexpected value — is a known issue when multiple domains are hosted. Work with your provider to pin the PTR to the primary server hostname and confirm they will not automatically override it.

Diagnosing Mismatches

# Check what your server announces in HELO
db configuration show qpsmtpd | grep HeloHost

# Check PTR for your server IP
dig -x 203.0.113.10 +short

# Check A record for the PTR result
dig nowata.example.com A +short

Part 5: Bounce Chain Hygiene

qmail's bounce behavior creates a potential for unsigned mail to escape the server, which can trigger DMARC failures and harm your domain's reputation. Two specific issues deserve attention on every SME v10 installation.

Double Bounce Prevention

When a message cannot be delivered, qmail generates a bounce (a "single bounce"). If that bounce itself cannot be delivered, qmail generates a double-bounce — a notification to the envelope sender of the original bounce, which is typically the empty address. By default on SME v10, double-bounces are sent to the postmaster address.

The problem: qmail-send generates these messages internally, bypassing qpsmtpd. This means double-bounces are never DKIM-signed. When they reach a receiving server, they fail DKIM and potentially fail DMARC, generating error reports and damaging reputation.

The correct fix is to route double-bounces to /dev/null:

db configuration setprop qmail DoubleBounceTo devnull
signal-event email-update


Important.png Note:
Single bounces (delivery failure notifications to the original sender) are legitimate and should still be delivered. This change affects only double-bounces, which are almost always the result of backscatter or spam with forged envelope senders.


Junkmail Maildir Ownership

A subtle but impactful issue: if the tmp directory inside a user's junkmail Maildir is owned by root rather than the user, SpamAssassin can deliver messages to the junkmail folder at the SMTP level, but local delivery will silently fail. The message disappears, a delivery failure is generated, and a bounce is produced — which then fails DMARC as described above.

This condition can persist for years after a user account is created without any visible symptoms until spam delivery is attempted. Audit all users:

# Check ownership for all users' junkmail tmp directories
for u in $(ls /home/e-smith/files/users/); do
  dir="/home/e-smith/files/users/$u/Maildir/.junkmail/tmp"
  if [ -d "$dir" ]; then
    owner=$(stat -c "%U" "$dir")
    if [ "$owner" != "$u" ]; then
      echo "WRONG OWNER: $dir owned by $owner"
    fi
  fi
done

# Fix a specific user
chown username:username /home/e-smith/files/users/username/Maildir/.junkmail/tmp

Part 6: SpamAssassin Tuning

SME v10 ships with SpamAssassin integrated into the mail pipeline. The thresholds, Bayes state, and local rule configuration are all managed through the SME database and template system.

TagLevel and RejectLevel

TagLevel is the score at which messages are tagged as spam (X-Spam-Status header added). RejectLevel is the score at which messages are rejected at the SMTP level. View and adjust these via the database:

# View current settings
db configuration show spamassassin

# Adjust thresholds (example values)
db configuration setprop spamassassin TagLevel 3.3
db configuration setprop spamassassin RejectLevel 12
signal-event email-update

A TagLevel of 3.3 is moderately aggressive — messages scoring above this will be flagged but not rejected. A high RejectLevel (10–15) is appropriate when SpamAssassin's Bayes corpus is well-trained, since false positives are rare and you want to avoid losing legitimate mail. Watch the X-Spam-Status headers of messages you receive to calibrate.

Envelope-Stage Blocking with badmailfrom

SpamAssassin operates on message content after the full message is received. For known-bad senders, it is more efficient to reject at the envelope MAIL FROM stage, before the message body is even transferred. SME exposes this through the badmailfrom mechanism, manageable via Server Manager under Email > Blacklist.

Add the envelope domain (not just the From: header address) of known spam/phishing sources:

# Via Server Manager: Email > Blacklist > Add
# Or directly via the database:
db accounts set @quickbooks-online.info badmailfrom Blacklisted yes
signal-event email-update

This is particularly effective for recurring phishing campaigns from specific lookalike domains — the connection is terminated before SpamAssassin ever runs.

Bayes Corpus

SpamAssassin's Bayesian classifier learns from mail you have identified as spam or ham. A well-trained corpus (20,000+ spam tokens, 50,000+ ham tokens) significantly improves accuracy. Check the current state:

sa-learn --dump magic
# Look for: nspam, nham, ntokens

If the Bayes database is available, SpamAssassin will assign BAYES_* scores to messages. A message with BAYES_80 or higher is a strong spam indicator even if other rule scores are low.

Local Rules

SpamAssassin supports custom rule files for site-specific matching. On SME v10, do not edit /etc/mail/spamassassin/local.cf directly — it is generated by the template system and will be overwritten. Consult the Koozali community for the sanctioned location for local rule files that survive signal-event expansions before deploying custom rules.

When writing custom rules, use meta-rules to require multiple conditions to be true simultaneously, reducing false positives:

# Example: flag messages mentioning cryptocurrency amounts AND phone numbers
body     CRYPTO_AMOUNT   /\$[0-9,]{4,}.*(?:bitcoin|crypto|BTC|ETH)/i
body     CALLBACK_NUMBER /(?:call|contact|reach).*\+?[0-9][\s.-]?\(?[0-9]{3}\)?/i
meta     CRYPTO_CALLBACK  (CRYPTO_AMOUNT && CALLBACK_NUMBER)
score    CRYPTO_CALLBACK  3.5
describe CRYPTO_CALLBACK  Crypto scam with callback number

Part 7: ClamAV False Positives

ClamAV ships with heuristic signatures that attempt to detect phishing by analyzing link structures in HTML mail. These signatures can fire on legitimate transactional email from large financial institutions — particularly emails where the visible link text and the underlying URL domain differ, which is common in marketing and notification systems.

The signature Heuristics.Phishing.Email.SpoofedDomain is a frequent offender against alerts from banks and payment processors whose notifications are generated by third-party email platforms.

Diagnosing False Positives

# Check the qpsmtpd log for ClamAV rejections
# Look for: clamav: virus found: Heuristics.Phishing.Email.SpoofedDomain

# Scan a specific message to confirm
clamscan --debug /path/to/saved/message.eml 2>&1 | grep -i phishing

Whitelisting

ClamAV supports signature-level whitelists. Before editing any ClamAV configuration, verify the correct whitelist file location for your SME installation to ensure the change survives package updates and signal-event runs:

# One common whitelist location (verify for your installation)
# /etc/clamav/local.ign2

# Add the false-positive signature name
echo "Heuristics.Phishing.Email.SpoofedDomain" >> /etc/clamav/local.ign2

# Reload ClamAV
service clamd restart


Warning.png Warning:
A broad whitelist for Heuristics.Phishing.Email.SpoofedDomain will suppress a genuine heuristic. Consider whether the affected senders can be whitelisted by envelope address via SpamAssassin's whitelist_from instead of disabling the entire ClamAV signature.


Part 8: Authentication Bypass and Social Engineering

Passing SPF, DKIM, and DMARC is a necessary condition but is not sufficient for a message being legitimate. Sophisticated attackers have learned to send through infrastructure that authenticates cleanly — compromised legitimate accounts, legitimate marketing platforms, and cloud services that permit arbitrary content in automated messages.

Abuse of Legitimate Platforms

Several attack patterns exploit legitimate services to achieve clean authentication:

  • Microsoft Teams Events / Dynamics 365: Attackers can create event registrations or calendar invites using free or trial accounts, embedding scam content in the event title or body. The confirmation emails arrive from Microsoft's own mail infrastructure with valid DKIM/SPF/DMARC.
  • Firebase / Google Cloud: Attackers use Firebase applications to send bulk mail that authenticates under firebaseapp.com or a related Google domain. The fact that DKIM passes for firebaseapp.com is not evidence of legitimacy.
  • Compromised business accounts: A legitimate company's mail infrastructure, once compromised, can be used to send BEC (Business Email Compromise) attacks that pass all authentication checks.

Business Email Compromise (BEC)

BEC attacks often impersonate executives or trusted vendors and request wire transfers, gift card purchases, or changes to payment instructions. The technical signature is: authentication passes on a legitimate-looking domain, but the Reply-To header redirects responses to an attacker-controlled address.

Instruct staff, especially accounting personnel, to:

  • Verify any payment instruction changes by phone using a number on record, not one provided in the email
  • Be suspicious of urgency and requests for secrecy
  • Check the Reply-To header, not just the From: display name, before replying
  • Treat any request to bypass normal approval processes as a red flag regardless of the apparent sender


Important.png Note:
Technical authentication controls alone cannot stop BEC. Staff education is not optional.


Custom SpamAssassin Rules

Content analysis can catch patterns that authentication cannot. Social-engineering scams typically combine several elements that rarely appear together in legitimate mail: large sums of money, urgency language, and callback phone numbers. Meta-rules that require multiple signals simultaneously can achieve reasonable detection rates without unacceptable false positives. See Part 6 for an example rule structure.

Before deploying custom rules, test them against your existing Bayes corpus and a representative sample of your legitimate mail to verify the false positive rate.

Part 9: WordPress PHPMailer Abuse

If your SME server hosts WordPress sites with contact forms, those forms can become spam relay vectors. PHPMailer — the library used by WordPress core and most form plugins — sends mail as the server's mail user, meaning spam sent through a contact form may bypass your inbound spam filters entirely and be sent as if it originated from your server.

Attack Pattern

Attackers use automated scripts to submit contact forms. The form plugin processes the submission and passes it to PHPMailer, which sends it to whatever address the form target specifies — or, in some plugins, the attacker can manipulate form fields to inject additional recipients or override headers.

Indicators of compromise:

  • Unexpected outbound mail volume visible in qmail logs
  • Bounce messages for addresses you did not send to
  • Apache access logs showing high-rate POST requests to /wp-admin/admin-post.php, /?wpcf7-f[id], or similar form handler endpoints from unfamiliar IPs

Mitigation

  • Deploy CAPTCHA on all public contact forms. Cloudflare Turnstile integrates natively with Contact Form 7 via its official module and adds negligible friction for real users.
  • Enable rate limiting on form submission endpoints at the web server or Wordfence level.
  • Block confirmed attacker IPs at the server firewall or via Wordfence IP blocking.
  • If xmlrpc.php is not required, disable it — it is a common brute-force target.
  • Ensure Wordfence WAF is in Enforced mode (not Learning mode) on all WordPress installations.
# Apache: block xmlrpc.php globally if not needed
<Files xmlrpc.php>
  Order Deny,Allow
  Deny from all
</Files>


Important.png Note:
Divi's proprietary form system does not support direct Cloudflare Turnstile integration. For Divi-based contact pages, consider replacing with CF7 forms or use server-level rate limiting as a compensating control.


Part 10: Testing Your Configuration

End-to-End Authentication: mail-tester.com

mail-tester.com provides a disposable address you can send a test message to, then view a scored report covering SPF, DKIM, DMARC, PTR/FCrDNS, blacklist status, and several content factors. It is the most practical single test for outbound authentication.

  1. Go to mail-tester.com and copy the unique test address
  2. Send a message from the domain under test using normal server mail (not a test utility — use your actual MUA or a service that sends through the server)
  3. Return to mail-tester.com and click Check your score
  4. Review any items that did not achieve full marks

A score of 10/10 is achievable with correct SPF, DKIM, DMARC, PTR alignment, and clean content. Scores of 9/10 or lower with DMARC at p=none reflect the monitoring-only policy rather than a failure.

Verifying DKIM in Logs

# Watch qpsmtpd log output in real time (SME v10 uses multilog, not tai64nlocal)
# Adjust path as needed for your installation
tail -f /var/log/qpsmtpd/current

# In the output, look for lines like:
# dkim: pass, we signed the message
# dkim: skip, DKIM not configured for example.com   <-- problem


Important.png Note:
SME v10 does not include tai64nlocal. Log timestamps will be in TAI64N format. Use the raw multilog output or an equivalent decoder if you need human-readable timestamps.


Verifying DKIM in Received Headers

Ask a recipient to forward you the raw headers of a message, or use the message source view in a webmail client. A successfully signed message will include a DKIM-Signature header and the receiving server will add an Authentication-Results header indicating pass:

Authentication-Results: mx.google.com;
   dkim=pass header.i=@example.com header.s=feb2026 header.b=AbCdEfGh;
   spf=pass (google.com: domain of user@example.com designates 203.0.113.10 as permitted sender)
       smtp.mailfrom=user@example.com;
   dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=example.com

DMARC Reporting

Once aggregate reports are flowing, review them regularly — especially in the first few weeks after changing policy. EasyDMARC and similar services provide human-readable dashboards. Key things to look for:

  • Any source IP sending mail for your domain that is not in your SPF record
  • Any legitimate sending path where DKIM is failing (indicates a misconfigured third-party sender)
  • Volume from sources you do not recognize at all (may indicate domain abuse or compromised credentials)

Part11: The Mailstats Contrib

The mailstats contrib interrogates the logs every night and emails admin, or a specified chosen email address, a table of the breakdown of all the emails received during the day into hourly buckets, categorised by how the SMEServer mail system deals with them. Examples are Webmail, Spam, RBL, etc. This provides the administrator an overview of how many emails are being dealt with daily, plus an indication of how many of them are created as "Non conformant" or Ham, etc. It shows overall counts, plus percentages. The data is held for a period in a local MySQL table, and could be used in further analysis. It also gives details of viruses found, Black list hits, counts for each recipient, junk mail folder contents and also a number of other useful counts.

See here for more details.

Summary Checklist

Use this as a per-domain verification checklist when bringing a new domain into full authentication.

Item Reference
SPF record published with server IP and relay IP Part 1
No deprecated ptr mechanism in SPF Part 1
DKIM keys in /home/e-smith/dkim_keys/[domain]/ (or default/ fallback configured) Part 2
DKIMSigning enabled in qpsmtpd config Part 2
signal-event email-update run after key setup Part 2
Symlinks present in /var/service/qpsmtpd/config/dkim/ Part 2
DKIM DNS record published with correct selector Part 2
DMARC record published (start with p=none) Part 3
DMARC rua address configured for aggregate reports Part 3
PTR record matches server FQDN (request from hosting provider) Part 4
HeloHost matches server FQDN and PTR Part 4
FQDN A record resolves to server IP Part 4
DoubleBounceTo devnull configured Part 5
Junkmail tmp directory ownership verified for all users Part 5
SpamAssassin TagLevel and RejectLevel set appropriately Part 6
End-to-end test with mail-tester.com completed Part 10
DMARC reports reviewed and sources accounted for Part 10

SME v10 Quick Reference

Database Commands

# View full qpsmtpd configuration
db configuration show qpsmtpd

# Set DKIM signing
db configuration setprop qpsmtpd DKIMSigning enabled

# Set HELO hostname
db configuration setprop qpsmtpd HeloHost mail.example.com

# Set SpamAssassin thresholds
db configuration setprop spamassassin TagLevel 3.3
db configuration setprop spamassassin RejectLevel 12

# Set double-bounce handling
db configuration setprop qmail DoubleBounceTo devnull

# Apply all changes
signal-event email-update

Key File Locations

/home/e-smith/dkim_keys/[domain]/          # DKIM keys — per-domain (canonical location)
/home/e-smith/dkim_keys/default/           # DKIM keys — server-wide fallback
/var/service/qpsmtpd/config/dkim/          # Symlinks (created by template system — do not edit)
/etc/mail/spamassassin/local.cf            # SpamAssassin config (generated — do not edit directly)
/var/service/qpsmtpd/config/plugins        # qpsmtpd plugin configuration

Log Locations

/var/log/qpsmtpd/current      # qpsmtpd (inbound SMTP) log (multilog format)
/var/log/qmail/current        # qmail-send log


Important.png Note:
Log files use TAI64N timestamp encoding. SME v10 does not include tai64nlocal. Read timestamps as-is from current or use an external TAI64N decoder.


Template System Reminder

SME's template system regenerates configuration files during signal-event runs. Any configuration file in /etc/ or /var/service/ that is managed by a template will be overwritten. To make persistent changes, use db configuration setprop or provide e-smith template fragments. Consult the Koozali wiki and developer community for the correct template locations for any configuration not covered by db properties.