Skip to content

smtpconn: Treat wrapped dial errors as network errors - #874

Open
amlaban65 wants to merge 1 commit into
foxcpp:devfrom
amlaban65:smtpconn-dial-error-temporary
Open

amlaban65 wants to merge 1 commit into
foxcpp:devfrom
amlaban65:smtpconn-dial-error-temporary

Conversation

@amlaban65

Copy link
Copy Markdown

Fixes #872

Problem

Since fd6d880, attemptConnect wraps dial errors as fmt.Errorf("dialer: %w", err). wrapClientErr recognizes network errors with a type switch on *net.OpError, so a wrapped dial error now falls through to the default case. It is no longer turned into 450 4.4.2 Network I/O error and ends up as a permanent 554 5.0.0 Internal server error. With an LMTP target, maddy rejected RCPT permanently while the LMTP server was restarting, instead of asking the sender to retry.

Change

  • In the default case of wrapClientErr, look for a *net.OpError with errors.As.
  • Move the existing *net.OpError handling into a small wrapNetErr helper, used for both the direct and the wrapped case. The returned SMTPError keeps the full error (including the dialer: context) in Err. The codes and messages are unchanged.

Testing

  • Added TestConnectRefused in internal/smtpconn. It dials a closed local port with both Connect and ConnectLMTP and checks for a temporary 450 4.4.2 SMTPError. It fails on dev without the fix (the error comes back as exterrors.fieldsWrap: dialer: dial tcp ...: connection refused) and passes with it.
  • go test ./internal/smtpconn/... ./internal/target/smtp/ ./internal/target/remote/ passes. gofmt and go vet ./internal/smtpconn/ are clean.
  • I did not run the full test suite or the integration tests in tests/. Locally I used Go 1.25.1 with a temporary modfile (go.mod asks for 1.26), so CI is the check on the real toolchain.

Since fd6d880, attemptConnect wraps dial errors as "dialer: %w".
wrapClientErr matched *net.OpError with a type switch, so wrapped dial
errors fell through to the default case and were reported as permanent
"554 5.0.0 Internal server error" instead of "450 4.4.2 Network I/O
error". For LMTP this made maddy reject RCPT permanently while the
LMTP server was restarting, instead of asking the sender to retry.

Look for *net.OpError with errors.As in the default case, so the
wrapped error is classified as before while keeping the added context.

Fixes foxcpp#872

Signed-off-by: Ahmed Laban <amlaban@outlook.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant