7
votes

I'm getting an exception when using SmtpClient in an Azure Web or Worker role.

I created a console app to manually run on the role VMs via RDP to reproduce:

using System;
using System.Net;
using System.Net.Mail;
using System.Text;

namespace ConsoleApplication1
{
   class Program
   {
      static void Main()
      {
         var mailClient = new SmtpClient("mail.redacted.com", 587);
         mailClient.EnableSsl = true;
         mailClient.DeliveryFormat = SmtpDeliveryFormat.International;
         mailClient.DeliveryMethod = SmtpDeliveryMethod.Network;

         mailClient.UseDefaultCredentials = false;//SET THIS FIRST OR IT WIPES OUT CREDENTIALS
         NetworkCredential netCreds = new NetworkCredential("[email protected]", "12345 same combination on my luggage");
         mailClient.Credentials = netCreds;

         MailMessage message = new MailMessage();
         message.SubjectEncoding = Encoding.UTF8;
         message.BodyEncoding = Encoding.UTF8;
         message.IsBodyHtml = false;

         message.From = new MailAddress("[email protected]");
         message.To.Add(new MailAddress("[email protected]"));

         message.Subject = "testing " + DateTime.UtcNow;
         message.Body = "The quick brown fox jumped over the lazy dogs.";

         mailClient.Send(message);
      }
   }
}

Locally it sends an email just fine. On Azure I get this:

    Unhandled Exception: System.Net.Mail.SmtpException: Failure sending mail. ---> System.ComponentModel.Win32Exception: The function requested is not supported
       at System.Net.NTAuthentication.GetOutgoingBlob(Byte[] incomingBlob, Boolean throwOnError, SecurityStatus& statusCode)
       at System.Net.NTAuthentication.GetOutgoingBlob(String incomingBlob)
       at System.Net.Mail.SmtpNtlmAuthenticationModule.Authenticate(String challenge, NetworkCredential credential, Object sessionCookie, String spn, ChannelBinding channelBindingToken)
       at System.Net.Mail.SmtpConnection.GetConnection(ServicePoint servicePoint)
       at System.Net.Mail.SmtpClient.Send(MailMessage message)
       --- End of inner exception stack trace ---
       at System.Net.Mail.SmtpClient.Send(MailMessage message)
       at ConsoleApplication1.Program.Main() in c:\development\ConsoleApplication1\ConsoleApplication1\Program.cs:line 39

I've confirmed that the Azure machines can access port 587 on the mail server by running TCPing.exe on the Azure roles via RDP.

1

1 Answers

5
votes

So apparently the problem was a mismatched NTLM version between servers.

After logging into the Azure roles and disabling the setting "Require NTLMv2 security" for clients, then it worked:

enter image description here

(Thanks to this answer and this answer for inspiration.)

Currently seeing if we can get our SMTP server upgraded to be NTLMv2-compatible. Otherwise we'll have to set up some automated code to somehow disable that setting on each generated role instance.

Apparently this code worked last month. So I'm guessing a recent Azure OS upgrade changed the default settings.

FYI: The registry key for this setting is

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0] "NtlmMinClientSec"=dword:20000000

To automate setting the registry key add a startup task containing a reg add command like this:

reg add HKLM\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0 ^
 /v NtlmMinClientSec ^
 /t REG_DWORD ^
 /d 0x20000000 ^
 /f

where /f forces the current setting to be overwritten and ^ just allows to break the command into multiple lines for better readability. Also make sure to save the command in ASCII encoding to prevent issues during role startup.