Skip to content

fix(email): SMTP sends ignore the caller's context, so the 30s failure-alert timeout can't cut off a hung mail server #1433

Closed

Description

@IAmJSD

Leftover from #1195 (one of its "smaller items"). #1245 fixed the main gap and closed #1195, but not this.

What happens

The purchase-failed alert gets a 30-second budget: failureNotifyTimeout (internal/purchase/failure_notify.go:26), applied with ctxutil.DetachedWithTimeout at :71. The SMTP sender (used on GCP via SendGrid and on Azure via ACS) never looks at that context:

  • the SMTPSender send methods take ctx, but dispatchSMTP (internal/email/smtp_sender.go:321, main at 6b586cc) has no context parameter;
  • the STARTTLS path calls smtp.Dial(addr) (:379) and the plain path calls smtp.SendMail (:336). Neither has a deadline, so a mail server that accepts the TCP connection and then stops answering blocks the call until the OS gives up or the function is killed.

Impact

A hung mail server can hold a purchase or scheduler invocation well past the 30 seconds meant for the alert. On AWS Lambda that eats into the remaining time; see #1434. The log marker that drives the failure alarm is written before the send, so the alarm itself still fires. The email may never arrive, and the invocation can time out.

Suggested fix

Pass ctx through to dispatchSMTP. Dial with net.Dialer{}.DialContext(ctx, ...) and smtp.NewClient, for both the TLS and plain paths (replacing smtp.SendMail). Set a connection deadline from ctx.Deadline() so the SMTP conversation after the dial is bounded too. Close the connection when ctx is cancelled.

Acceptance criteria

  • A send whose context expires while the SMTP server is unresponsive (a test stub that accepts and then stalls) returns within about the context deadline, with an error that wraps context.DeadlineExceeded.
  • Both the STARTTLS path and the plain AllowInsecure test path honor the context.
  • Existing SMTP sender tests still pass.

Refs #1195, #1245, #1094.

Filed by IAmJSD's agent at IAmJSD's request (acting owner while the maintainers are away).

Activity

  1. IAmJSD commented on Oct 26, 2026

    @IAmJSD
    CollaboratorAuthor

    Claiming: working on this

  2. self-assigned this
    on Oct 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions