Prevent Setting SmtpClient.UseDefaultCredentials clearing Credentials (dotnet/corefx...
authorNabeel Valley <36758308+nabeelvalley@users.noreply.github.com>
Wed, 2 Oct 2019 01:07:26 +0000 (03:07 +0200)
committerDavid Shulman <david.shulman@microsoft.com>
Wed, 2 Oct 2019 01:07:26 +0000 (18:07 -0700)
* Ensure setting UseDefaultCredentials to False does not clear Credentials

* Remove reference comments

* Rename tests to align with convention

* Correctly set _transport.Credentials

* Include SmtpClient._transport.Credentials in tests, move tests to own file

* Change filename and refactor UN/PW

Commit migrated from https://github.com/dotnet/corefx/commit/dcc9f626eeb0751d4ba4499f623aac42d2e95c10

src/libraries/System.Net.Mail/src/System/Net/Mail/SmtpClient.cs
src/libraries/System.Net.Mail/tests/Functional/SmtpClientCredentialsTest.cs [new file with mode: 0644]
src/libraries/System.Net.Mail/tests/Functional/SmtpClientTest.cs
src/libraries/System.Net.Mail/tests/Functional/System.Net.Mail.Functional.Tests.csproj

index 8852e4b..d67a266 100644 (file)
@@ -61,6 +61,8 @@ namespace System.Net.Mail
         // ports above this limit are invalid
         private const int MaxPortValue = 65535;
         public event SendCompletedEventHandler SendCompleted;
+        private bool _useDefaultCredentials;
+        private ICredentialsByHost _customCredentials;
 
         public SmtpClient()
         {
@@ -229,7 +231,7 @@ namespace System.Net.Mail
         {
             get
             {
-                return ReferenceEquals(_transport.Credentials, CredentialCache.DefaultNetworkCredentials);
+                return _useDefaultCredentials;
             }
             set
             {
@@ -238,7 +240,8 @@ namespace System.Net.Mail
                     throw new InvalidOperationException(SR.SmtpInvalidOperationDuringSend);
                 }
 
-                _transport.Credentials = value ? CredentialCache.DefaultNetworkCredentials : null;
+                _useDefaultCredentials = value;
+                UpdateTransportCredentials();
             }
         }
 
@@ -255,10 +258,16 @@ namespace System.Net.Mail
                     throw new InvalidOperationException(SR.SmtpInvalidOperationDuringSend);
                 }
 
-                _transport.Credentials = value;
+                _customCredentials = value;
+                UpdateTransportCredentials();
             }
         }
 
+        private void UpdateTransportCredentials()
+        {
+            _transport.Credentials = _useDefaultCredentials ? CredentialCache.DefaultNetworkCredentials : _customCredentials;
+        }
+
         public int Timeout
         {
             get
diff --git a/src/libraries/System.Net.Mail/tests/Functional/SmtpClientCredentialsTest.cs b/src/libraries/System.Net.Mail/tests/Functional/SmtpClientCredentialsTest.cs
new file mode 100644 (file)
index 0000000..4b2d507
--- /dev/null
@@ -0,0 +1,130 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace System.Net.Mail.Functional.Tests
+{
+    public class SmtpClientCredentialsTest
+    {
+        private readonly string UserName = "user";
+        private readonly string Password = Guid.NewGuid().ToString(); 
+
+        [Fact]
+        public void Credentials_Unset_Null()
+        {
+            SmtpClient client = new SmtpClient();
+
+            ICredentialsByHost transportCredentials = GetTransportCredentials(client);
+
+            Assert.Null(client.Credentials);
+            Assert.Null(transportCredentials);
+        }
+
+        [Fact]
+        public void DefaultCredentials_True_DefaultCredentials()
+        {
+            NetworkCredential expectedCredentials = CredentialCache.DefaultNetworkCredentials;
+
+            SmtpClient client = new SmtpClient();
+            client.UseDefaultCredentials = true;
+
+            ICredentialsByHost transportCredentials = GetTransportCredentials(client);
+
+            Assert.Equal(expectedCredentials, client.Credentials);
+            Assert.Equal(expectedCredentials, transportCredentials);
+        }
+
+        [Fact]
+        public void UseDefaultCredentials_False_Null()
+        {
+            SmtpClient client = new SmtpClient();
+            client.UseDefaultCredentials = false;
+
+            ICredentialsByHost transportCredentials = GetTransportCredentials(client);
+
+            Assert.Null(client.Credentials);
+            Assert.Null(transportCredentials);
+        }
+
+        [Fact]
+        public void Credentials_UseDefaultCredentialsSetFalseBeforeCredentials_Credentials()
+        {
+            NetworkCredential expectedCredentials = new NetworkCredential(UserName, Password);
+
+            SmtpClient client = new SmtpClient();
+            client.UseDefaultCredentials = false;
+            client.Credentials = expectedCredentials;
+
+            ICredentialsByHost transportCredentials = GetTransportCredentials(client);
+
+            Assert.NotNull(client.Credentials);
+            Assert.Equal(expectedCredentials, client.Credentials);
+            Assert.Equal(expectedCredentials, transportCredentials);
+        }
+
+        [Fact]
+        public void Credentials_UseDefaultCredentialsSetFalseAfterCredentials_Credentials()
+        {
+            NetworkCredential expectedCredentials = new NetworkCredential(UserName, Password);
+
+            SmtpClient client = new SmtpClient();
+            client.Credentials = expectedCredentials;
+            client.UseDefaultCredentials = false;
+
+            ICredentialsByHost transportCredentials = GetTransportCredentials(client);
+
+            Assert.NotNull(client.Credentials);
+            Assert.Equal(expectedCredentials, client.Credentials);
+            Assert.Equal(expectedCredentials, transportCredentials);
+        }
+
+        [Fact]
+        public void Credentials_UseDefaultCredentialsSetTrueBeforeCredentials_DefaultNetworkCredentials()
+        {
+            NetworkCredential expectedCredentials = CredentialCache.DefaultNetworkCredentials;
+
+            SmtpClient client = new SmtpClient();
+            client.UseDefaultCredentials = true;
+            client.Credentials = new NetworkCredential(UserName, Password);
+
+            ICredentialsByHost transportCredentials = GetTransportCredentials(client);
+
+            Assert.Equal(expectedCredentials, client.Credentials);
+            Assert.Equal(expectedCredentials, transportCredentials);
+        }
+
+        [Fact]
+        public void Credentials_UseDefaultCredentialsSetTrueAfterCredentials_DefaultNetworkCredentials()
+        {
+            NetworkCredential expectedCredentials = CredentialCache.DefaultNetworkCredentials;
+
+            SmtpClient client = new SmtpClient();
+            client.Credentials = new NetworkCredential(UserName, Password);
+            client.UseDefaultCredentials = true;
+
+            ICredentialsByHost transportCredentials = GetTransportCredentials(client);
+
+            Assert.Equal(expectedCredentials, client.Credentials);
+            Assert.Equal(expectedCredentials, transportCredentials);
+        }
+
+        private ICredentialsByHost GetTransportCredentials(SmtpClient client)
+        {
+            Type smtpTransportType = (typeof(SmtpClient)).Assembly.GetType("System.Net.Mail.SmtpTransport");
+
+            var transport = typeof(SmtpClient)
+                .GetField("_transport", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance)
+                .GetValue(client);
+
+            var transportCredentials = smtpTransportType
+                .GetProperty("Credentials", BindingFlags.NonPublic | BindingFlags.GetProperty | BindingFlags.Instance)
+                .GetValue(transport);
+
+            return (ICredentialsByHost)transportCredentials;
+        }
+    }
+}
index 675daeb..dd72e7e 100644 (file)
@@ -9,7 +9,6 @@
 // (C) 2006 John Luke
 //
 
-using System.Collections.Generic;
 using System.IO;
 using System.Net.NetworkInformation;
 using System.Net.Sockets;
index 5d0f22f..2380601 100644 (file)
@@ -10,6 +10,7 @@
     <Compile Include="AttachmentTest.cs" />
     <Compile Include="ContentDispositionTest.cs" />
     <Compile Include="ContentTypeTest.cs" />
+    <Compile Include="SmtpClientCredentialsTest.cs" />
     <Compile Include="HeaderCollectionTest.cs" />
     <Compile Include="LinkedResourceCollectionTest.cs" />
     <Compile Include="LinkedResourceTest.cs" />