Contents
The PowerMTA accounting log is the primary source of truth for delivery performance analysis. Every message event — injection, delivery attempt, deferral, bounce, and expiry — is logged with SMTP response codes, source IP, destination, and timing data. Without accounting logs, operators are blind to ISP-specific performance, IP-level deferral patterns, and bounce classification data. This reference covers the complete accounting log configuration, field reference, and the analysis patterns used for production deliverability monitoring.
Enabling and Configuring the Accounting Log
# /etc/pmta/config — accounting log configurationpath /var/log/pmta/accounting format csv # Record types to log: records received,delivered,failed,deferred,bounced # File rotation: rotate-period daily max-files 30 # Keep 30 days of rotated files # Optional: gzip rotated files to save space # rotate-compress yes # Log files are named: accounting-YYYYMMDD.csv (rotated) # Current file: /var/log/pmta/accounting (no extension, current day) # Recommended: add pipeline processing for real-time alerts # (see powermta-pipe-external-script-accounting.html for pipe configuration) # Verify accounting is logging: tail -5 /var/log/pmta/accounting # Should show CSV records of recent delivery events
Accounting Log Field Reference
| Field | Description | Example Value |
|---|---|---|
otype | Record type (d=delivered, b=bounce, t=deferral, r=received, f=failed) | d |
timeLogged | Timestamp of the event | 2026-01-15T14:23:11+00:00 |
timeQueued | When message entered the queue | 2026-01-15T14:20:00+00:00 |
orig | Envelope sender (Return-Path) | bounces@mail.yourdomain.com |
rcpt | Recipient email address | user@gmail.com |
vmta | Virtual MTA name used for delivery | gmail-ip-1 |
jobId | Job/campaign identifier (from injected X-Job header) | campaign-2026-01-15 |
dsnStatus | SMTP response code class | 2.0.0 (delivered) / 5.1.1 (bad mailbox) |
dsnDiag | Full SMTP diagnostic text from remote server | 250 2.0.0 OK... |
dlvSourceIp | Source IP address used for this delivery attempt | 185.x.x.10 |
dlvDestinationIp | Destination MX IP connected to | 142.251.x.x |
dlvType | Delivery method (smtp / pipe) | smtp |
dlvDuration | Time for SMTP session in seconds | 1.234 |
Record Types Explained
| otype | Event | Meaning |
|---|---|---|
r | Received | Message accepted into queue via SMTP injection |
d | Delivered | 250 response received — message accepted by remote MTA |
t | Transient failure | 4xx deferral — will be retried per retry-after schedule |
b | Bounce | 5xx permanent failure or bounce type classification triggered |
f | Failed | Message expired from queue (expire-after exceeded) without delivery |
Accounting Log Analysis Examples
# 1. Overall delivery rate by record type
awk -F, 'NR>1 {counts[$1]++} END {
total=counts["d"]+counts["b"]+counts["t"]+counts["f"]
printf "Delivered: %d (%.1f%%)\nBounced: %d (%.1f%%)\nDeferred: %d\n",
counts["d"], counts["d"]/total*100, counts["b"], counts["b"]/total*100, counts["t"]
}' /var/log/pmta/accounting-YYYYMMDD.csv
# 2. Delivery rate by destination ISP
awk -F, 'NR>1 && $1=="d" {
split($6, a, "@"); domain[a[2]]++; total++
} NR>1 && $1=="b" {
split($6, a, "@"); bounce[a[2]]++
} END {
for(d in domain) printf "%s: %.1f%% delivered\n", d, domain[d]/(domain[d]+bounce[d])*100
}' /var/log/pmta/accounting-YYYYMMDD.csv | sort -t: -k2 -rn
# 3. Top deferral codes
awk -F, 'NR>1 && $1=="t" {codes[$9]++} END {
for(c in codes) print codes[c], c
}' /var/log/pmta/accounting-YYYYMMDD.csv | sort -rn | head -10
# 4. Delivery rate per source IP
awk -F, 'NR>1 {{
if ($1=="d") delivered[$15]++
if ($1=="b") bounced[$15]++
}} END {{
for (ip in delivered) printf "%s: %d delivered, %d bounced\n", ip, delivered[ip], bounced[ip]
}}' /var/log/pmta/accounting-YYYYMMDD.csv
dsnDiag Field Deep Dive
The dsnDiag field contains the full SMTP diagnostic text from the remote server. This is the most detailed signal available for understanding exactly why a message was deferred or rejected. Common patterns and their meanings:
# Gmail diagnostic examples: "421 4.7.0 Try again later, closing connection. (code)" → Reputation-based rate limit "550 5.7.1 [IP] Our system has detected that this message is likely spam" → Content filter "550 5.7.26 This message fails to pass DMARC checks" → DMARC failure # Microsoft diagnostics: "421 4.7.0 RP-001 The IP you're sending from..." → Reputation policy block "550 5.7.1 Unfortunately, messages from..." → IP policy block # Yahoo diagnostics: "421 4.7.0 [TSS04] Messages from..." → Throttle "554 Message not allowed - [DB] Queue/Time limit" → Quota or time limit # Greylisting pattern (common from smaller ISPs): "451 4.7.0 Please try again later" → Greylisting — retry works "450 4.2.0: Recipient address rejected: Greylisted" # Analysis: group dsnDiag by first 40 characters to find pattern clusters awk -F, 'NR>1 && $1=="t" {print substr($10,1,60)}' /var/log/pmta/accounting.csv | \ sort | uniq -c | sort -rn | head -20
Per-IP Delivery Rate Monitoring
# Monitor each sending IP independently
# dlvSourceIp field (field 15 in standard CSV format) contains the source IP
# Per-IP delivery summary:
awk -F, 'NR>1 {{
ip=$15
if($1=="d") del[ip]++
if($1=="b") bnc[ip]++
if($1=="t") def[ip]++
}} END {{
for(ip in del) {{
total=del[ip]+bnc[ip]+def[ip]
printf "IP: %s | Delivered: %d | Bounce: %.1f%% | Deferral: %.1f%%\n",
ip, del[ip], bnc[ip]/total*100, def[ip]/total*100
}}
}}' /var/log/pmta/accounting-YYYYMMDD.csv
# Alert thresholds:
# Bounce rate > 2% on any IP: investigate list quality
# high deferral rate diagnosis > 10% at specific ISP on specific IP: check reputation
# Zero delivered from an IP that should be sending: IP may be blocked
Log Rotation and Retention
# Log rotation configurationpath /var/log/pmta/accounting rotate-period daily # Rotate at midnight UTC max-files 30 # Keep 30 days of rotated files # Gzip old files to reduce disk usage: # rotate-compress yes # Requires gzip on system # At high volume: estimate log size # 100 bytes per record × 1,000,000 msgs/day = 100MB/day = 3GB/month # Ensure /var/log partition has adequate space (recommend 50GB+ for high volume) # Archive to long-term storage: # Add cron job to move files older than 7 days to S3 / backup storage 0 2 * * * find /var/log/pmta/ -name "accounting-*.csv" -mtime +7 -exec gzip {{}} \; 0 3 * * * find /var/log/pmta/ -name "accounting-*.csv.gz" -mtime +30 \ -exec aws s3 cp {{}} s3://your-bucket/pmta-logs/ \;
Frequently Asked Questions
Operating PowerMTA at production volume?
We manage PowerMTA environments for high-volume senders — configuration, IP warming schedule, daily reputation monitoring, and operational response. Fully managed. No self-service.

