copy, paste, run

Recipes

Complete commands for the things people actually use SMTPBench for. Each one runs as written. Change the addresses and the host and you have a working test.

Accurate as of SMTPBench 1.2.1

Safe first run, sending nothing

Evaluate composition with zero delivery risk, then open an .eml in any mail client. Nothing connects, so there is no way to send by accident.

smtpbench [email protected] threads=2 messages=5 \
          eml_out_dir=./eml-output

Realistic mixed traffic

Reproducible variety: selection is seeded from the run UUID.

smtpbench [email protected] port=587 threads=10 messages=100 \
          attachment_dir=./corpus \
          attachment_probability=0.7 \
          attachment_count=1-3 \
          body_text_dir=./text-corpus

Polite sustained load

Runs until interrupted, capped at 20 msg/s across all threads regardless of thread count. The combination to reach for when testing a relay you would rather not harm.

smtpbench [email protected] port=587 threads=10 messages=0 rate=20

Multi-recipient run through a fixed relay

recipient_file requires lb_host; roundrobin gives even coverage across the run.

smtpbench recipient_file=recipients.txt recipient_file_order=roundrobin \
          from_file=senders.txt from_file_order=random \
          lb_host=smtp.dev.lets.qa port=587 threads=5 messages=100

Authenticated TLS run, credentials off the command line

Credentials resolve from the environment, so they stay out of ps, top, and shell history.

export SMTPBENCH_USER=myuser
export SMTPBENCH_PASS=mypassword
smtpbench [email protected] port=587 threads=5 messages=50 \
          tls_mode=starttls rate=10

Journaling with a recipient list

Needs an explicit journal_address, because there is no single recipient to fall back to.

smtpbench recipient_file=recipients.txt \
          journal=true [email protected] \
          lb_host=smtp.dev.lets.qa port=587 threads=5 messages=100

MX failover verification

No lb_host, so DNS decides and hosts are walked in priority order. Read per_mx in the summary afterwards to prove the secondary took over and see how much it absorbed.

smtpbench [email protected] port=25 threads=10 messages=100

CI latency gate

A mail path regression-gated like any other service. Note the or {} guard, because latency_ms is null when nothing succeeded.

smtpbench [email protected] lb_host=smtp.dev.lets.qa port=587 \
          threads=5 messages=20 rate=5

python -c "import json,glob,os,sys; \
  f=max(glob.glob('logs/summary_*.json'), key=os.path.getmtime); \
  d=json.load(open(f)); \
  sys.exit(1 if (d['latency_ms'] or {}).get('p95',0) > 2000 else 0)"

Single-message connectivity check

The smallest useful run, and a good troubleshooting entry point. The debug log carries the full SMTP exchange, with the AUTH step suppressed.

smtpbench [email protected] port=587 threads=1 messages=1 debug=true

If a combination is rejected

A few options genuinely cannot be combined, and a few need each other. Details has the full set of rules, and features documents every option with its default.