Lightweight SMTP Logger Scripts for Developers (Python, Node.js, Go)

SMTP Logger: Complete Guide to Email Delivery Debugging

What an SMTP logger is

An SMTP logger captures and records SMTP protocol traffic between a mail client or application and an SMTP server. It records commands, responses, timestamps, message envelopes, and optionally message bodies and headers so you can trace how mail flows, where it fails, and why.

When to use one

  • Email delivery fails intermittently (bounces, delays).
  • You need to debug authentication, TLS/STARTTLS, or delivery errors.
  • Verifying headers, DKIM signatures, or custom envelope addresses.
  • Testing a new mail server, relay, or third-party SMTP provider.
  • Auditing or reproducing issues reported by users or services.

What SMTP loggers record

  • Session-level events: connection start/end, TLS negotiation, authentication attempts.
  • SMTP commands: EHLO/HELO, MAIL FROM, RCPT TO, DATA, QUIT, and extensions (8BITMIME, SIZE).
  • Server responses: status codes and human-readable messages (250, 421, 550, etc.).
  • Timestamps and connection metadata (source/destination IP, ports).
  • Message envelope (envelope sender/recipient) and optionally headers/body.
  • Errors and retries including transient (4xx) and permanent (5xx) failures.

Privacy & security considerations

  • Logs may contain sensitive data (email addresses, message bodies, authentication tokens). Treat them as sensitive: encrypt at rest, restrict access, and redact or mask personal data where possible.
  • Avoid logging full message bodies in production unless necessary; capture headers and envelope data first.
  • Ensure TLS is validated in production: logging should not disable certificate checks.

How to enable SMTP logging (common environments)

Postfix
  • Increase verbosity in main.cf: debug_peer_level = 2 and set smtpd_tls_loglevel = 1 or 2.
  • Use postconf -e to edit; view logs in syslog (/var/log/maillog or /var/log/mail.log).
  • For per-connection debugging, run postfix stop then start postfix -v start or run smtpd in foreground for interactive debug.
Exim
  • Enable verbose logging with log_selector = +all in exim.conf or run exim -d -v for one-off debugging.
  • Logs typically appear in /var/log/exim/mainlog.
Sendmail
  • Use sendmail -v for verbose client mode or increase syslog level for daemon.
  • View /var/log/maillog.
Application libraries (examples)
  • Python smtplib: enable debugging with smtp.set_debuglevel(1) to print commands/responses to stdout.
  • JavaMail: set mail.debug=true or configure a session debug output stream.
  • Node.js nodemailer: set logger: true and debug: true in transporter options.
Intercepting traffic
  • Use tcpdump or tshark to capture server port (25/465/587) traffic; decrypt if you control TLS keys.
  • Run a local SMTP proxy or fake SMTP server (see tools below) to capture unencrypted traffic without changing production.

Tools & utilities

  • Debugging SMTP servers: MailHog, MailTrap, smtp4dev — capture mail without delivering.
  • Local proxies: Haraka (extensible), msmtp (client), or custom proxy scripts.
  • Network capture: tcpdump, Wireshark/tshark for packet-level inspection.
  • Log analyzers: pflogsumm for Postfix, custom scripts (awk, sed, Python) for parsing logs.
  • Libraries: Python’s smtplib, Node’s nodemailer, Go’s net/smtp for instrumented clients.

Step-by-step debugging checklist

  1. Reproduce the problem in a controlled environment.
  2. Enable logging only at required verbosity; avoid full body logging in production.
  3. Capture connection-level data: timestamps, client IP, HELO/EHLO values.
  4. Observe SMTP commands/responses to find rejection codes (4xx vs 5xx).
  5. Check TLS/auth: confirm STARTTLS negotiation and AUTH success.
  6. Inspect envelope vs header: ensure MAIL FROM/RCPT TO match headers as expected.
  7. Follow server logs for MTA handoffs (queue IDs) and delivery retries.
  8. Search for DNS/SPF/DKIM/DMARC issues if receiving servers reject mail.
  9. If network-related, capture packets for latency, reset (RST), or firewall drops.
  10. Apply fix, then rerun tests and retain logs for future reference.

Common SMTP error codes and likely causes

  • 421 — Service not available; server busy or temporary.
  • 450 / 451 / 452 — Temporary local issues (mailbox unavailable, quota).
  • 550 — Permanent failure (recipient unknown, blocked).
  • 554 — Transaction failed (spam rejection, policy).
  • 535 / 534 — Authentication/authorization failures.
    Interpret server response text alongside code for precise cause.

Examples: Quick debug commands

  • Telnet SMTP: telnet smtp.example.com 25 then manually issue EHLO/MAIL FROM/RCPT TO/DATA to observe responses.
  • Verify TLS: openssl s_client -starttls smtp -crlf -connect smtp.example.com:587 to inspect certificates.
  • Capture traffic: sudo tcpdump -i any port 25 or port 587 -w smtp.pcap then open in Wireshark.

Prescriptive recommendations

  • For development, use MailHog or smtp4dev to capture without risk.
  • In production, log envelopes and headers, redact bodies, rotate logs, and enforce strict access controls.
  • Implement structured logging (JSON) to make parsing and alerting straightforward.
  • Correlate SMTP logs with application logs using unique message IDs or queue IDs.

Quick reference table

Topic Command / Tool
Verbose Postfix postconf -e ‘debug_peer_level=2’
Python client debug smtp.set_debuglevel(1)
TLS check openssl s_client -starttls smtp -connect host:587
Local capture MailHog, smtp4dev
Packet capture tcpdump -w smtp.pcap ‘port 25 or port 587’

Wrap-up

An SMTP logger is essential for diagnosing delivery, authentication, and policy issues. Use targeted logging, secure stored logs, and combine protocol traces with application and DNS checks to find root causes quickly.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *