Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d7beb98
Merge in 'release/6.0' changes
dotnet-bot Mar 3, 2022
14ac5c4
Merge in 'release/6.0' changes
dotnet-bot Mar 4, 2022
3e42a51
Merge in 'release/6.0' changes
dotnet-bot Mar 8, 2022
e84180a
Merge in 'release/6.0' changes
dotnet-bot Mar 8, 2022
3514d49
Merge in 'release/6.0' changes
dotnet-bot Mar 8, 2022
23cef86
Merge in 'release/6.0' changes
dotnet-bot Mar 8, 2022
a31025a
Merge in 'release/6.0' changes
dotnet-bot Mar 8, 2022
ef034e7
Merge in 'release/6.0' changes
dotnet-bot Mar 8, 2022
1565e21
Merge in 'release/6.0' changes
dotnet-bot Mar 8, 2022
288d311
Merge in 'release/6.0' changes
dotnet-bot Mar 9, 2022
828088b
Merge in 'release/6.0' changes
dotnet-bot Mar 9, 2022
e55f609
Merge in 'release/6.0' changes
dotnet-bot Mar 10, 2022
3389aa1
Merge in 'release/6.0' changes
dotnet-bot Mar 10, 2022
666e597
Merge in 'release/6.0' changes
dotnet-bot Mar 10, 2022
1188f73
Merge in 'release/6.0' changes
dotnet-bot Mar 10, 2022
e92a00f
Merge in 'release/6.0' changes
dotnet-bot Mar 10, 2022
cb56267
Merge in 'release/6.0' changes
dotnet-bot Mar 10, 2022
cfb4efd
Merge in 'release/6.0' changes
dotnet-bot Mar 10, 2022
91b82b8
Merge in 'release/6.0' changes
dotnet-bot Mar 10, 2022
e318a42
Merge in 'release/6.0' changes
dotnet-bot Mar 10, 2022
1d1ea97
Merge in 'release/6.0' changes
dotnet-bot Mar 11, 2022
8d7b562
Merge in 'release/6.0' changes
dotnet-bot Mar 11, 2022
7a7c54b
Merge in 'release/6.0' changes
dotnet-bot Mar 11, 2022
4fa64a1
Merge in 'release/6.0' changes
dotnet-bot Mar 11, 2022
1cb7505
Merge in 'release/6.0' changes
dotnet-bot Mar 14, 2022
be98e88
Merged PR 21497: [release/6.0] MSRC 68590 - newlines in domain literals
Mar 14, 2022
a37ca00
Merge commit 'be98e88c760526452df94ef452fff4602fb5bded' into internal…
vseanreesermsft Apr 12, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ namespace System.ComponentModel.DataAnnotations
AllowMultiple = false)]
public sealed class EmailAddressAttribute : DataTypeAttribute
{
private static bool EnableFullDomainLiterals { get; } =
AppContext.TryGetSwitch("System.Net.AllowFullDomainLiterals", out bool enable) ? enable : false;

public EmailAddressAttribute()
: base(DataType.EmailAddress)
{
Expand All @@ -27,6 +30,11 @@ public override bool IsValid(object? value)
return false;
}

if (!EnableFullDomainLiterals && (valueAsString.Contains('\r') || valueAsString.Contains('\n')))
{
return false;
}

// only return true if there is only 1 '@' character
// and it is neither the first nor the last character
int index = valueAsString.IndexOf('@');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ protected override IEnumerable<TestCase> InvalidValues()
yield return new TestCase(new EmailAddressAttribute(), 0);
yield return new TestCase(new EmailAddressAttribute(), "");
yield return new TestCase(new EmailAddressAttribute(), " \r \t \n" );
yield return new TestCase(new EmailAddressAttribute(), "someName@[\r\n\tsomeDomain]");
yield return new TestCase(new EmailAddressAttribute(), "@someDomain.com");
yield return new TestCase(new EmailAddressAttribute(), "@someDomain@abc.com");
yield return new TestCase(new EmailAddressAttribute(), "someName");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ namespace System.Net.Mail
//
public partial class MailAddress
{
private static bool EnableFullDomainLiterals { get; } =
AppContext.TryGetSwitch("System.Net.AllowFullDomainLiterals", out bool enable) ? enable : false;

// These components form an e-mail address when assembled as follows:
// "EncodedDisplayname" <userName@host>
private readonly Encoding _displayNameEncoding;
Expand Down Expand Up @@ -219,6 +222,12 @@ private string GetHost(bool allowUnicode)
throw new SmtpException(SR.Format(SR.SmtpInvalidHostName, Address), argEx);
}
}

if (!EnableFullDomainLiterals && domain.AsSpan().IndexOfAny('\r', '\n') >= 0)
{
throw new SmtpException(SR.Format(SR.SmtpInvalidHostName, Address));
}

return domain;
}

Expand Down
59 changes: 59 additions & 0 deletions src/libraries/System.Net.Mail/tests/Functional/SmtpClientTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@
// (C) 2006 John Luke
//

using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.DotNet.RemoteExecutor;
using Systen.Net.Mail.Tests;
using Xunit;

Expand Down Expand Up @@ -523,5 +527,60 @@ public async Task SendMail_SendQUITOnDispose(bool asyncSend)
quitReceived.Wait(TimeSpan.FromSeconds(30));
Assert.True(quitMessageReceived, "QUIT message not received");
}

[ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
[InlineData("foo@[\r\n bar]")]
[InlineData("foo@[bar\r\n ]")]
[InlineData("foo@[bar\r\n baz]")]
public void MultiLineDomainLiterals_Enabled_Success(string input)
{
RemoteExecutor.Invoke(static (string @input) =>
{
AppContext.SetSwitch("System.Net.AllowFullDomainLiterals", true);

var address = new MailAddress(@input);

// Using address with new line breaks the protocol so we cannot easily use LoopbackSmtpServer
// Instead we call internal method that does the extra validation.
string? host = (string?)typeof(MailAddress).InvokeMember("GetAddress", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod, null, address, new object[] { true });
Assert.Equal(input, host);
}, input).Dispose();
}

[Theory]
[MemberData(nameof(SendMail_MultiLineDomainLiterals_Data))]
public async Task SendMail_MultiLineDomainLiterals_Disabled_Throws(string from, string to, bool asyncSend)
{
using var server = new LoopbackSmtpServer();

using SmtpClient client = server.CreateClient();
client.Credentials = new NetworkCredential("Foo", "Bar");

using var msg = new MailMessage(@from, @to, "subject", "body");

await Assert.ThrowsAsync<SmtpException>(async () =>
{
if (asyncSend)
{
await client.SendMailAsync(msg).WaitAsync(TimeSpan.FromSeconds(30));
}
else
{
client.Send(msg);
}
});
}

public static IEnumerable<object[]> SendMail_MultiLineDomainLiterals_Data()
{
foreach (bool async in new[] { true, false })
{
foreach (string address in new[] { "foo@[\r\n bar]", "foo@[bar\r\n ]", "foo@[bar\r\n baz]" })
{
yield return new object[] { address, "foo@example.com", async };
yield return new object[] { "foo@example.com", address, async };
}
}
}
}
}