Skip to content

Fix SmtpException.GetMessageForStatus: use distinct messages for unknown and defined-but-unmapped status codes#126602

Merged
rzikm merged 3 commits intomainfrom
copilot/fix-smtp-exception-command-unrecognized
Apr 8, 2026
Merged

Fix SmtpException.GetMessageForStatus: use distinct messages for unknown and defined-but-unmapped status codes#126602
rzikm merged 3 commits intomainfrom
copilot/fix-smtp-exception-command-unrecognized

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 7, 2026

SmtpException.GetMessageForStatus fell through default to SmtpStatusCode.CommandUnrecognized, so any unrecognized status value (e.g. (SmtpStatusCode)0 from an uninitialized _statusCode) produced the misleading message "Syntax error, command unrecognized." — implying an SMTP 500 response when none occurred.

Description

  • Strings.resx: Added three new resource strings:
    • SmtpUnknownStatusCode"Unknown SMTP status code." (for truly undefined status code values)
    • SmtpCannotVerifyUserWillAttemptDelivery"Cannot verify user, but will attempt delivery." (for SMTP 252)
    • SmtpGeneralFailure"General failure." (for the internal GeneralFailure = -1 sentinel)
  • SmtpException.cs: Separated default from case SmtpStatusCode.CommandUnrecognized in GetMessageForStatus, and added explicit case labels for all previously unmapped defined enum members (CannotVerifyUserWillAttemptDelivery and GeneralFailure):
    // Before
    default:
    case SmtpStatusCode.CommandUnrecognized:
        return SR.SmtpCommandUnrecognized;
    
    // After
    default:
        return SR.SmtpUnknownStatusCode;
    case SmtpStatusCode.GeneralFailure:
        return SR.SmtpGeneralFailure;
    case SmtpStatusCode.CannotVerifyUserWillAttemptDelivery:
        return SR.SmtpCannotVerifyUserWillAttemptDelivery;
    case SmtpStatusCode.CommandUnrecognized:
        return SR.SmtpCommandUnrecognized;
    // ... all other defined enum members explicitly handled
  • SmtpExceptionTest.cs: Added assertion confirming unknown status codes yield a message distinct from CommandUnrecognized.

Customer Impact

Exceptions thrown with undefined SmtpStatusCode values (e.g. during connection failures before any SMTP response is received) produce a confusing "command unrecognized" message, making diagnosis harder — particularly when the real cause is a transport/handshake failure unrelated to SMTP 500. All defined SmtpStatusCode enum members now map to their own descriptive messages; the default case exclusively handles truly undefined values.

Regression

No — this behavior has been present since the original .NET Framework implementation.

Testing

Existing SmtpExceptionTest suite (318 tests, 0 failures). Added assertion to TestConstructorWithStatusCodeArgument verifying that new SmtpException((SmtpStatusCode)666).Message differs from new SmtpException(SmtpStatusCode.CommandUnrecognized).Message.

Risk

Very low. Logic change in a switch statement; only affects diagnostic messages. All previously handled enum values retain their existing messages. The two previously unmapped defined enum values (CannotVerifyUserWillAttemptDelivery, GeneralFailure) now return descriptive messages instead of the misleading "command unrecognized" text.

…t message for unknown status codes

Separates the `default` case from `SmtpStatusCode.CommandUnrecognized` in the
`GetMessageForStatus` switch, so unknown/undefined status codes produce a
generic "Unknown SMTP status code." message rather than the misleading
"Syntax error, command unrecognized." message specific to SMTP 500.

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/a9d8afb8-cec0-448d-bc19-1f9b6bfe5b8f

Co-authored-by: rzikm <32671551+rzikm@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix misleading message for unknown SmtpStatusCode Fix SmtpException.GetMessageForStatus default case: use distinct message for unknown status codes Apr 7, 2026
Copilot AI requested a review from rzikm April 7, 2026 12:38
Copilot finished work on behalf of rzikm April 7, 2026 12:38
@rzikm rzikm marked this pull request as ready for review April 7, 2026 13:14
@rzikm rzikm requested review from a team and Copilot April 7, 2026 13:14
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates System.Net.Mail’s SmtpException status-code-to-message mapping so undefined/unknown SmtpStatusCode values no longer report the misleading “command unrecognized” (SMTP 500) message.

Changes:

  • Added a new localized resource string for unknown SMTP status codes.
  • Updated SmtpException.GetMessageForStatus to return the new resource from the default switch case.
  • Extended the functional test to assert unknown status codes don’t share the CommandUnrecognized message.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/libraries/System.Net.Mail/src/System/Net/Mail/SmtpException.cs Changes the default message mapping for unrecognized status codes.
src/libraries/System.Net.Mail/src/Resources/Strings.resx Adds SmtpUnknownStatusCode resource string.
src/libraries/System.Net.Mail/tests/Functional/SmtpExceptionTest.cs Adds assertion ensuring unknown status codes produce a distinct message.

…GeneralFailure

All defined SmtpStatusCode enum members now have explicit case labels in
GetMessageForStatus so the `default` case exclusively handles truly
undefined/unknown status code values.

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/529c4574-2800-472e-93e6-73c1439e519c

Co-authored-by: rzikm <32671551+rzikm@users.noreply.github.com>
Copilot AI changed the title Fix SmtpException.GetMessageForStatus default case: use distinct message for unknown status codes Fix SmtpException.GetMessageForStatus: use distinct messages for unknown and defined-but-unmapped status codes Apr 7, 2026
Copilot finished work on behalf of rzikm April 7, 2026 14:32
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @karelz, @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

@rzikm
Copy link
Copy Markdown
Member

rzikm commented Apr 8, 2026

/ba-g infrastructure errors are unrelated.

@rzikm rzikm enabled auto-merge (squash) April 8, 2026 08:09
@rzikm rzikm merged commit 809e569 into main Apr 8, 2026
86 of 92 checks passed
@rzikm rzikm deleted the copilot/fix-smtp-exception-command-unrecognized branch April 8, 2026 08:09
radekdoulik pushed a commit to radekdoulik/runtime that referenced this pull request Apr 9, 2026
…own and defined-but-unmapped status codes (dotnet#126602)

`SmtpException.GetMessageForStatus` fell through `default` to
`SmtpStatusCode.CommandUnrecognized`, so any unrecognized status value
(e.g. `(SmtpStatusCode)0` from an uninitialized `_statusCode`) produced
the misleading message *"Syntax error, command unrecognized."* —
implying an SMTP 500 response when none occurred.

## Description

- **`Strings.resx`**: Added three new resource strings:
- `SmtpUnknownStatusCode` → `"Unknown SMTP status code."` (for truly
undefined status code values)
- `SmtpCannotVerifyUserWillAttemptDelivery` → `"Cannot verify user, but
will attempt delivery."` (for SMTP 252)
- `SmtpGeneralFailure` → `"General failure."` (for the internal
`GeneralFailure = -1` sentinel)
- **`SmtpException.cs`**: Separated `default` from `case
SmtpStatusCode.CommandUnrecognized` in `GetMessageForStatus`, and added
explicit case labels for all previously unmapped defined enum members
(`CannotVerifyUserWillAttemptDelivery` and `GeneralFailure`):
  ```csharp
  // Before
  default:
  case SmtpStatusCode.CommandUnrecognized:
      return SR.SmtpCommandUnrecognized;

  // After
  default:
      return SR.SmtpUnknownStatusCode;
  case SmtpStatusCode.GeneralFailure:
      return SR.SmtpGeneralFailure;
  case SmtpStatusCode.CannotVerifyUserWillAttemptDelivery:
      return SR.SmtpCannotVerifyUserWillAttemptDelivery;
  case SmtpStatusCode.CommandUnrecognized:
      return SR.SmtpCommandUnrecognized;
  // ... all other defined enum members explicitly handled
  ```
- **`SmtpExceptionTest.cs`**: Added assertion confirming unknown status
codes yield a message distinct from `CommandUnrecognized`.

## Customer Impact

Exceptions thrown with undefined `SmtpStatusCode` values (e.g. during
connection failures before any SMTP response is received) produce a
confusing "command unrecognized" message, making diagnosis harder —
particularly when the real cause is a transport/handshake failure
unrelated to SMTP 500. All defined `SmtpStatusCode` enum members now map
to their own descriptive messages; the `default` case exclusively
handles truly undefined values.

## Regression

No — this behavior has been present since the original .NET Framework
implementation.

## Testing

Existing `SmtpExceptionTest` suite (318 tests, 0 failures). Added
assertion to `TestConstructorWithStatusCodeArgument` verifying that `new
SmtpException((SmtpStatusCode)666).Message` differs from `new
SmtpException(SmtpStatusCode.CommandUnrecognized).Message`.

## Risk

Very low. Logic change in a `switch` statement; only affects diagnostic
messages. All previously handled enum values retain their existing
messages. The two previously unmapped defined enum values
(`CannotVerifyUserWillAttemptDelivery`, `GeneralFailure`) now return
descriptive messages instead of the misleading "command unrecognized"
text.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: rzikm <32671551+rzikm@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

SmtpException.GetMessageForStatus default case produces misleading "command unrecognized" message for unknown status codes

5 participants