Skip to content

Escape quotes and backslashes in MailAddress display name when encoding SMTP headers#128979

Open
Copilot wants to merge 6 commits into
mainfrom
copilot/support-quotes-in-email-displayname
Open

Escape quotes and backslashes in MailAddress display name when encoding SMTP headers#128979
Copilot wants to merge 6 commits into
mainfrom
copilot/support-quotes-in-email-displayname

Conversation

Copilot AI commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

MailAddress.Encode — the path SmtpClient uses to write From/To/Cc/etc. headers — wraps the display name in "…" but does not escape RFC 5322 quoted-string specials (" and \), producing an invalid quoted-string and corrupting the header when a DisplayName like Henry "The Fonz" Winkler or C:\path\to\file is used. MailAddress.ToString() previously escaped " but not \; only the SMTP send path was missed when quote support was added in #36752.

Changes

  • MailAddress.Encode (ASCII / allowUnicode=true branch): escape embedded \ as \\ and " as \", producing a valid RFC 5322 quoted-string. The Q-encoded (non-ASCII) branch is unaffected since encoded-words don't use quoted-string syntax.
  • MailAddress.ToString: apply the same \\\ escaping alongside the existing "\" escaping, so both rendering paths are consistent.
  • Order matters in both call sites: \ is escaped first, then ", otherwise the newly inserted backslashes would themselves get double-escaped.
  • Tests: add [Theory]-based regression tests in MailAddressEncodeTest (with a DisplayNamesWithSpecialChars member-data source) covering quote-only, backslash-only, and combined cases for both MailAddress.Encode and MailAddressCollection.Encode; extend MailAddressDisplayNameTest.MailAddressTestDataQuotes with backslash variants and fix the helper that computes the expected ToString() to apply both replacements. The pre-existing range-of-chars test was updated to expect the now-escaped [\\] substring in its allowUnicode=true assertion (the Q-encoded path is unchanged).

Before vs. after for new MailAddress("test@example.com", "Henry \"The Fonz\" Winkler").Encode(0, false):

- "Henry "The Fonz" Winkler" <test@example.com>     // invalid quoted-string
+ "Henry \"The Fonz\" Winkler" <test@example.com>   // RFC 5322-compliant

Before vs. after for new MailAddress("test@example.com", "C:\\path\\to\\file").Encode(0, false):

- "C:\path\to\file" <test@example.com>              // invalid quoted-string
+ "C:\\path\\to\\file" <test@example.com>           // RFC 5322-compliant

Copilot AI self-assigned this Jun 4, 2026
Copilot AI review requested due to automatic review settings June 4, 2026 11:51
Copilot AI removed the request for review from Copilot June 4, 2026 11:51
Copilot AI linked an issue Jun 4, 2026 that may be closed by this pull request
@MihaZupan MihaZupan assigned mrek-msft and unassigned MihaZupan Jun 4, 2026
Co-authored-by: MihaZupan <25307628+MihaZupan@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot June 4, 2026 12:19
Copilot AI changed the title [WIP] Fix SmtpClient to support quotes in email DisplayName Escape quotes in MailAddress display name when encoding SMTP headers Jun 4, 2026
Copilot AI requested a review from MihaZupan June 4, 2026 12:20
@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.

@mrek-msft

Copy link
Copy Markdown
Member

@copilot please add support for escaping \ into \\ as well.

Co-authored-by: mrek-msft <188900745+mrek-msft@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot June 10, 2026 13:45

Copilot AI commented Jun 10, 2026

Copy link
Copy Markdown
Contributor Author

@copilot please add support for escaping \ into \\ as well.

Done. Both MailAddress.Encode and MailAddress.ToString now escape \\\ in addition to "\" (backslash first, then quote, to avoid double-escaping the newly inserted backslashes). Extended the MailAddressEncodeTest regression tests with a [Theory] covering quote-only, backslash-only, and combined cases (including C:\path\to\file), and the pre-existing range-of-chars test expectation was updated for the now-escaped [\\] substring. All 340 unit + 433 functional tests pass.

Note

This response was generated by GitHub Copilot.

Copilot AI changed the title Escape quotes in MailAddress display name when encoding SMTP headers Escape quotes and backslashes in MailAddress display name when encoding SMTP headers Jun 10, 2026
Copilot AI requested a review from mrek-msft June 10, 2026 13:45
@mrek-msft

Copy link
Copy Markdown
Member

@copilot, please move Replace("\\", "\\\\").Replace("\"", "\\\"") to some helper method so we do not have to maintain it on two places.

Co-authored-by: mrek-msft <188900745+mrek-msft@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot June 16, 2026 12:42

Copilot AI commented Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

@copilot, please move Replace("\\", "\\\\").Replace("\"", "\\\"") to some helper method so we do not have to maintain it on two places.

Done in 41e68cd. Extracted into a private static EscapeQuotedStringContent(string) helper on MailAddress, used by both ToString and Encode.

Note

This response was generated by GitHub Copilot.

Comment on lines +139 to +141
// The literal '\' in the input is RFC 5322-escaped as '\\' in the
// resulting quoted-string when allowUnicode permits the quoted-string
// form (i.e. no Q-encoding).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot remove this comment and add " to test input above (+ escaped into expected output below).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 52b71be. Added " to the input string (between ! and #), updated the allowUnicode=true expectation to include \", updated the Q-encoded expectation to include =22 (which shifts the line folds), and removed the comment.

Note

This response was generated by GitHub Copilot.

[MemberData(nameof(DisplayNamesWithSpecialChars))]
public void EncodeSingleMailAddress_WithDisplayNameContainingSpecials_ShouldEscapeAsQuotedPairs(string displayName, string expectedEncodedDisplayName)
{
// Regression test for https://github.com/dotnet/runtime/issues/52439:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot this link is totally wrong. It is completely unrelated issue. Do not mention any issue URL there.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed in 616dd51.

Note

This response was generated by GitHub Copilot.

Co-authored-by: mrek-msft <188900745+mrek-msft@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot June 16, 2026 15:10
Copilot AI requested a review from mrek-msft June 16, 2026 15:11
Co-authored-by: mrek-msft <188900745+mrek-msft@users.noreply.github.com>
@mrek-msft mrek-msft marked this pull request as ready for review June 17, 2026 14:09
Copilot AI review requested due to automatic review settings June 17, 2026 14:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes RFC quoted-string escaping for MailAddress display names by ensuring embedded " and \ characters are emitted as quoted-pairs in both the SMTP header encoding path (MailAddress.Encode) and the string rendering path (MailAddress.ToString).

Changes:

  • Add a shared escaping helper in MailAddress and use it from both ToString() and the ASCII / allowUnicode branch of Encode(...).
  • Update and extend unit tests to cover display names containing quotes, backslashes, and combinations thereof for both single and multiple address encoding.
  • Adjust the existing “range of chars” test expectations for the allowUnicode=true output to reflect the new escaping behavior.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddress.cs Escapes \ and " in quoted display names for both ToString() and the ASCII/allowUnicode Encode path via a shared helper.
src/libraries/System.Net.Mail/tests/Unit/MailAddressTests/MailAddressEncodeTest.cs Adds theory-based regression coverage for escaping in MailAddress.Encode, MailAddressCollection.Encode, and ToString, and updates a pre-existing expectation.
src/libraries/System.Net.Mail/tests/Unit/MailAddressTests/MailAddressDisplayNameTest.cs Extends display-name test data to include backslash cases and updates expected ToString() escaping accordingly.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support for quotes in email address DisplayName

4 participants