Repository navigation
fix(mailer): support SMTP AUTH LOGIN when PLAIN is unavailable - #100
Conversation
|
All contributors have signed the CLA. ✅ |
|
I have read the CLA Document and I hereby sign the CLA |
There was a problem hiding this comment.
ℹ️ No blocking issues — the mechanism selection and the
AUTH LOGINexchange are correct. One coverage suggestion and a small test nit below.
Reviewed changes
- Advertised-mechanism selection —
(*SMTP).authForMethodsreads the server's advertisedAUTHlist fromc.Extension("AUTH")and returns PLAIN when offered, else LOGIN, else a clear unsupported-mechanism error, replacing the hardcodedsmtp.PlainAuth. AUTH LOGINimplementation — a newloginAuthsmtp.Authanswers the two challenges with username then password and hard-requires TLS viaStart.- Tests + docs — unit tests cover the selection preference and the
loginAuthstate machine;docs/ARCHITECTURE.mddocuments the rule.
I verified the load-bearing assumptions against Go's net/smtp: StartTLS re-issues EHLO after the handshake (so the AUTH advertisement is post-TLS), NewClient sets tls=true for implicit-TLS connections, and Client.Auth drives a no-initial-response mechanism as AUTH LOGIN → 334 → username → 334 → password → 235 → Next(..., false). go build, go vet and go test ./internal/mailer/ all pass.
ℹ️ The LOGIN exchange is only tested in isolation, never through net/smtp
TestLoginAuthRequiresTLSAndAnswersChallenges calls loginAuth directly, so it pins the state machine but not the contract the PR actually depends on: that net/smtp's Client.Auth sends no initial response, calls Next(more=true) exactly twice, then calls Next(..., false) on the 235. A regression in that interaction (e.g. an accidental initial response, or an extra challenge) would ship undetected.
Technical details
# Add an integration test for the AUTH LOGIN exchange
## Affected sites
- `internal/mailer/smtp_test.go:38-59` — `TestLoginAuthRequiresTLSAndAnswersChallenges` exercises `loginAuth` directly; the `Send` → `c.Extension("AUTH")` → `authForMethods` → `c.Auth` path is never run.
- `internal/mailer/smtp.go:198-209` — the selection and `c.Auth` call site.
## Required outcome
- A test using a local listener (mirroring `TestSMTP_Send_timesOutOnUnresponsiveServer`) that speaks enough SMTP to advertise `AUTH LOGIN`, issue the two 334 challenges, verify the base64 username/password, return 235, then accept `MAIL FROM`/`RCPT TO`/`DATA`, asserting `Send` returns nil.
## Open questions for the human
- Whether a fuller fake SMTP server is worth the maintenance cost versus leaning on the stdlib contract.ℹ️ Nitpicks
internal/mailer/smtp_test.go:30— the PLAIN case only asserts the result is not*loginAuth, so anauthForMethodsthat returnednil, nilfor a PLAIN-capable server would pass. Assert positively, e.g. callauth.Start(&smtp.ServerInfo{Name: s.host, TLS: true})and check the mechanism is"PLAIN".docs/ARCHITECTURE.md:648— reads well; noCHANGELOG.mdentry under[Unreleased], though the repo applies that convention inconsistently.
opencode-go/deepseek-v4.1-flash | 𝕏
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
- Locked down the PLAIN selection assertion — the
LOGIN PLAINcase inTestSMTPAuthForMethodsnow callsauth.Start(&smtp.ServerInfo{Name: s.host, TLS: true})and requires mechanism"PLAIN", closing the prior hole where any non-*loginAuthresult (includingnil) would pass. - Added the SMTP AUTH LOGIN changelog entry — an
[Unreleased] → ### Fixednote describing the PLAIN-then-LOGIN selection, the TLS requirement, and the unsupported-method error.
go test ./internal/mailer/ passes.
opencode-go/deepseek-v4.1-flash | 𝕏
|
Quick follow-up now that this is on main: could you pull latest, re-run your Office 365 manual test, and confirm it's still green? CI doesn't cover a live LOGIN-only server, and you're the one with access to the real thing — your confirmation is the actual end-to-end proof here. If anything looks off, reopen or ping me and I'll dig in. Thanks again for the contribution. |
|
@pullfrog hi |

Problem
Calnode currently uses smtp.PlainAuth for SMTP credentials. During a connection to smtp.office365.com:587, Microsoft advertised AUTH LOGIN XOAUTH2 after STARTTLS, with no PLAIN option. Calnode therefore could not use the advertised password authentication method.
Change
Testing
Added tests for the Office 365 capability list, PLAIN preference, unsupported methods, LOGIN challenge responses, and the TLS requirement.