Search code examples
c#asp.netsslsmtpwindows-server-2012

Cannot send emails through ASP.NET application


I have an ASP.NET application running on a dedicated server "Windows Server 2012 R2". The site uses SSL encryption throughout, the certificate is correctly installed on the server and shows as valid when accessed through different browsers.

I now want to send emails through my application, to do this I set up an SMTP server following the instructions in this article. http://www.vsysad.com/2014/09/setup-and-configure-smtp-server-on-windows-server-2012/

After setting up the SMTP server as specified above, I can send emails using powershell, and they are sent without issue. However, when I do the same through my application I get the following error

Exception Type: System.Security.Authentication.AuthenticationException
Exception: The remote certificate is invalid according to the validation procedure.
Stack Trace: 
   at System.Net.Security.SslState.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, Exception exception)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Net.TlsStream.ProcessAuthentication(LazyAsyncResult result)
   at System.Net.TlsStream.Write(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.Mail.SmtpConnection.Flush()
   at System.Net.Mail.EHelloCommand.Send(SmtpConnection conn, String domain)
   at System.Net.Mail.SmtpConnection.GetConnection(ServicePoint servicePoint)
   at System.Net.Mail.SmtpClient.Send(MailMessage message)
   at EmailSender.SendMailSingleRecipient(String recipient, String subject, String message)

The code to send the email from my application is very simple as you can see below.

MailMessage mailMessage = new MailMessage();
mailMessage.From = new MailAddress("[email protected]");
mailMessage.To.Add("[email protected]");
mailMessage.Subject = "subject"
mailMessage.Body = "message"

SmtpClient smtpClient = new SmtpClient("localhost", 25);
smtpClient.Send(mailMessage);

I have seen the same issue reported many times, but no answer which solves the issue for me. Could someone explain the reason behind this error and possible causes/solutions.


Solution

  • I managed to find a solution to my original question. Instead of sending directly from my application, I set up my SMTP server to use a pickup directory instead.

    The application code is very simple now, specifying the delivery method and pickup directory can also be moved into the configuration file.

    SmtpClient client = new SmtpClient("localhost", 25);
    client.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory;
    client.PickupDirectoryLocation = @"C:\inetpub\mailroot\Pickup";
    client.Send(mail);
    

    Another advantage with this approach is that the generation of emails from the application can be tested without setting up SMTP on a development machine. By looking in the pickup directory you can determine if the application is working correctly.

    Using this approach on my live server, I receive the email almost as soon as I send it from my application so the performance is very good.