net/smtp is 1982
Go's net/smtp does exactly what the RFC says and nothing more: no HTML helpers, no auth beyond PLAIN and CRAM-MD5, and the package is frozen by design. The Go team themselves point users elsewhere.
Elsewhere is one stdlib HTTP call.
One POST, and the send is handled
body := `{"from":"[email protected]","to":"[email protected]", "subject":"Welcome","html":"<p>You're in.</p>"}` req, _ := http.NewRequest("POST", "https://api.nitrosend.com/v1/my/messages", strings.NewReader(body)) req.Header.Set("Authorization", "Bearer "+os.Getenv("NITROSEND_API_KEY")) http.DefaultClient.Do(req)
No third-party module, no SMTP dialer, no TLS negotiation to reason about. The response carries the message ID; your webhook carries the rest.
And the infrastructure behind that POST is sized like a systems engineer would want: we run on a million-a-day sending limit as a baseline, with five million a day available on request. Your Goroutines will not be the bottleneck, and neither will we.
The API design philosophy is fail-closed, which Go engineers will appreciate. We once found a misplaced scheduled_at field being silently dropped, which meant an immediate send instead of a scheduled one: a 24,000-email misfire waiting to happen. Now a wrong-shaped field fails closed with a 422 pointing at the correct one. Silent coercion is how footguns ship. The rule is a hardcoded invariant in the codebase now: audience resolution fails closed, never open.
The API key in that snippet is a server-side credential with full account access. Keep it in the environment on a backend, the way the snippet reads it, and never in anything that ships to a browser or a binary you distribute.
The same fail-closed posture runs through the mail infrastructure itself. On our forwarding relay, TCP 2525 is firewall-restricted to our API host, TLS and exact SMTP authentication are mandatory, and every single-recipient route and MX snapshot is HMAC-signed. Unsigned requests, replayed requests, extra recipients and arbitrary destinations are rejected. That list is lifted from the abuse-controls section of our own AWS infrastructure submission, not from a marketing page.
Full parameters, responses, and error codes live in the REST API docs and the API reference.
And the part no library gives you
The same account exposes an MCP server, so the agent writing your code can also run your email. Point Claude, Cursor, or Codex at api.nitrosend.com/mcp and it composes, previews, and stages sends, with a human approving every one. The API is for your code. The MCP is for your agent. One platform either way.
Every send comes back with a message ID, and delivery events follow on your webhook: delivered, opened, bounced. No dashboard required to know what happened. If you are staying on SMTP, how to set up SMTP is the setup to follow, and SPF, DKIM and DMARC authentication is what stops those sends landing in spam.