Go · SMTP · Performance testing
smtp-load-test: SMTP load testing tool in Go
smtp-load-test is an open-source command-line tool written in Go that generates SMTP traffic and reports how mail submission behaves under load. It connects my work on Linux mail services and network troubleshooting with an implementation that can be inspected on GitHub.
What the tool measures
A successful TCP connection is only one part of submitting an email. Every test message is sent over its own connection, and the tool records whether the submission succeeded and how long each of seven stages took.
| Stage | What is timed |
|---|---|
DIAL | Opening the TCP connection, or the TLS connection when implicit TLS is enabled. |
TOUCH | Creating the SMTP session and reading the server greeting. |
HELO | The HELO/EHLO exchange. |
MAIL | The MAIL FROM command. |
RCPT | The RCPT TO command. |
DATA | The DATA command and the transfer of the message. |
QUIT | Closing the session with QUIT. |
STARTTLS and authentication run between HELO and MAIL when they are enabled. They are part of every submission but are not reported as separate stages.
Running a load test
The tool is a single Go binary. Build it from the repository and point it at a mail server you operate:
git clone https://github.com/ennesuysal/smtp-load-test.git
cd smtp-load-test
go build -o smtp-load-test .
./smtp-load-test -smtpServer mail.example.com -smtpPort 587 \
-senderMail sender@example.com -smtpPassword "$SMTP_PASSWORD" \
-receiverMail receiver@example.com \
-workerSize 20 -jobCount 1000 -dataSize 25KThis example sends 1,000 messages with a 25 KB body through 20 concurrent workers. STARTTLS and authentication are enabled by default. The other defaults are 10 messages of 5 KB, 10 workers and port 587.
Command-line options
The command-line interface exposes separate controls for the load and the target server. These settings make it possible to compare different test configurations while keeping the server and message parameters explicit.
| Flags | Purpose |
|---|---|
-workerSize, -batchSize, -jobCount | Number of concurrent workers, capacity of the task queue that feeds them and total number of messages to send. |
-smtpServer, -smtpPort, -helo | Target host, port and the name sent in the SMTP greeting. |
-senderName, -senderMail, -receiverMail, -dataSize | Sender name and address, recipient and size of the generated message body, for example 512B, 5K or 2M. |
-sslEnabled, -startTLS, -authEnabled, -smtpPassword | Implicit TLS, STARTTLS and PLAIN authentication with the sender address and password. Boolean flags take the form -startTLS=false. |
Reading the results
The report starts with the number of successful and failed submissions, then lists the minimum, average, maximum and total duration of every stage in seconds, followed by the total duration of the test.
When evaluating a controlled test, compare the success and failure counts alongside the protocol timings. Changing one load parameter at a time makes differences easier to interpret. Server-side CPU, disk and mail queue observations provide context that the client-side report alone cannot supply.
Implementation and scope
The entry point parses the flags, creates the SMTP test client, runs SendTestMails and prints the statistics. Concurrency comes from go-thread-pooling, my worker pool module for Go, in which a fixed number of goroutines take send jobs from a buffered channel. The SMTP client is built on Go’s net/smtp and crypto/tls packages, and the statistics package aggregates stage timings and counters behind mutexes.
TLS certificate verification is skipped so that test servers with self-signed certificates can be measured. The repository focuses on load generation and client-side measurements. Server monitoring and verification of inbox delivery remain separate parts of evaluating a mail system.
Explore the source
Review the current implementation and available options in the repository before running a test on a mail server you operate.
Related experience
Explore my work with Linux mail services, Kubernetes, observability and database reliability.
DevOps and SRE experience