You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: SMTPS support + align toolchain with echo (#62)
* fix: SMTPS support, sync.Pool copy, printf-vet warnings; align toolchain with echo
email: stdlib smtp.SendMail speaks plain + STARTTLS only; port 465 (Resend,
SendGrid, etc.) hangs on the handshake. Detect port 465 and dial TLS directly
via tls.DialWithDialer. Expose an optional TLSConfig for callers needing a
custom root pool or ServerName, and DialTimeout so misconfigured hosts fail
fast. Public Send API is unchanged. New tests cover plain dial, timeout, and
invalid addresses.
random: sync.Pool must not be copied after first use; New was copying from a
local var into the Random struct. Construct the pool directly on the struct
literal to satisfy go vet and prevent mutex corruption under concurrent use.
log: the internal (*Logger).log method overloaded three modes (Sprint,
Sprintf, JSON) via a format-or-sentinel string, which go vet flagged with
14 "call has arguments but no formatting directives" warnings. Split into
log(level, message, jsonBody) and logJSON(level, j). The new logJSON
wrapper adds one stack frame, so log bumps runtime.Caller's skip when
jsonBody is true to keep the reported file:line on the user's call site.
TestCallerFile guards against future skip drift.
toolchain: bump go directive to 1.23.0 and CI matrix to 1.23-1.26 to match
labstack/echo. Refresh direct deps: testify 1.8.4 -> 1.11.1, go-colorable
0.1.13 -> 0.1.14, go-isatty 0.0.20 -> 0.0.21. Pin x/sys at v0.29.0 (latest
that doesn't require Go 1.25+).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs: refresh README with email/random packages and Go 1.23 floor
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(bytes): use 7EiB instead of 8EiB in tests — 2^63 overflow is non-portable
Parse("8EiB") computes 2^63, which exceeds MaxInt64. The float-to-int
conversion of out-of-range values is implementation-dependent per the
Go spec, so the prior assertion `math.MaxInt64 == b-1` (relying on
two's-complement wrap) only held on some toolchains. 7EiB fits within
int64 and tests EiB parsing without depending on undefined behaviour.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(email): propagate EHLO errors; always clone TLSConfig; honest comments
- Drive c.Hello explicitly before checking the STARTTLS extension.
(*smtp.Client).Extension triggers a lazy hello() and swallows its
error, which would silently treat a failed EHLO as "STARTTLS not
advertised" and keep the connection in the clear even when the
caller configured TLS.
- Always Clone the caller's TLSConfig in dial() instead of partial-
cloning only when ServerName is empty. Removes the "sometimes
mutated" branch and the implicit "do not mutate TLSConfig
concurrently with Send" contract ambiguity.
- Reword the dial comment so STARTTLS-opportunistic-on-non-465 reads
as the honest contract it is ("stays cleartext if server doesn't
advertise"), not a guarantee of TLS.
- Expand doc comments on TLSConfig and DialTimeout to state the clone
behavior and timeout scope.
- log: note that skip++ for jsonBody must stay in sync with logJSON.
- Tests: bump TestDial_Timeout from 150ms -> 500ms to absorb CI
scheduler jitter (upper bound bumped to 3s — still well-scoped).
Document intent in TestDial_PlainAccepts by asserting STARTTLS is
not advertised on the fake server.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0 commit comments