feat: production-ready hardening, TLS SMTP, pluggable content, docs - #8
Merged
Merged
Conversation
Core correctness and production readiness: - Fix a deadlock where Enqueue held an exclusive lock during a blocking channel send, which could block Start/Stop when the queue was full. The service now uses an RWMutex plus an atomic started flag; the queue is closed exactly once under the write lock while Enqueue holds the read lock. - Add exported read accessors to MailContent (FromName, FromAddress, ToName, ToAddress, MimeType, Subject, Body) so external MailerService backends can actually read message fields. - Reject CR/LF/NUL in header fields at build time (SMTP header-injection protection); raise address limits to RFC-compatible bounds and the body limit to 256 KiB. SMTP transport: - Add TLS: implicit TLS/SMTPS (ImplicitTLS, implied on 465) and opportunistic/required STARTTLS (RequireTLS). - Configurable DialTimeout, LocalName (EHLO), and custom TLSConfig; accept the full 1-65535 port range; render messages with CRLF and a UTF-8 Content-Type; wrap underlying errors via MailerError.Err/Unwrap. Service: - Add MailServiceConfig.QueueSize and a per-message Timeout; make Start/Stop idempotent and safe for concurrent use. Tests, docs, and tooling: - Add an in-process SMTP test server (plain, STARTTLS, implicit TLS), concurrency tests under -race, and validation/getter coverage (~92%). - Rewrite README (install, quick start, config tables, custom backends); add docs/ guides and examples; expand SECURITY.md. - Add Makefile, .golangci.yaml, DEVELOPMENT_GUIDELINES.md, CHANGELOG.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Makes
mailerproduction-ready: fixes a concurrency deadlock, adds TLS to the SMTP transport, makesMailContentusable by external backends, hardens validation, and adds documentation, tests, and public-library tooling.Highlights
Correctness & concurrency
Enqueuepreviously held an exclusive mutex during a blocking channel send, so a full queue could blockStart/Stopindefinitely (reproducible via the oldTestMailService_EnqueueBlocksWhenFull, which hung for 60s). The service now uses anRWMutex+ atomicstartedflag; the queue is closed exactly once under the write lock whileEnqueueholds the read lock — no send-on-closed-channel, no deadlock.Start/Stopare now idempotent and safe for concurrent use.Pluggable backends actually work
MailContentnow exposes read accessors (FromName,FromAddress,ToName,ToAddress,MimeType,Subject,Body). Previously all fields were unexported with no getters, so any externalMailerServiceimplementation could not read the message it was asked to send.SMTP transport (security)
ImplicitTLS, implied on port 465) and opportunistic/required STARTTLS (RequireTLS). Without this, PLAIN auth against a real server fails (stdlib refuses plaintext auth) — the transport was effectively unusable for authenticated servers.DialTimeout,LocalName(EHLO), customTLSConfig; full1–65535port range; CRLF line endings + UTF-8Content-Type; errors wrap their cause (errors.Is/errors.As).Validation & injection safety
Service ergonomics
MailServiceConfig.QueueSize(queue independent of worker count) and per-messageTimeout.Tests, docs, tooling
-race; validation/getter coverage. ~92% statement coverage (gate in.testcoverage.ymlpasses).docs/guides + examples.Makefile,.golangci.yaml(lint clean),DEVELOPMENT_GUIDELINES.md,CHANGELOG.md; expandedSECURITY.md.Compatibility
Pre-1.0. Additive API (accessors, new config fields). Behavioral changes: SMTP now negotiates TLS,
SMTPPortallowlist replaced by a range check, and validation bounds widened — all documented inCHANGELOG.md.Verification
🤖 Generated with Claude Code