Search code examples
c#amazon-web-servicessmtpsmtpclientamazon-workmail

Amazon WorkMail timeout .net core SmtpClient


I am trying to send a standard email message through AWS WorkMail using the SmtpClient in .NET Core. The configuration is very standard according to Amazon Documentation: https://docs.amazonaws.cn/en_us/general/latest/gr/workmail.html

  "Smtp": {
    "MailServer": "smtp.mail.eu-west-1.awsapps.com",
    "MailPort": "465",
    "SenderName": "Us us us",
    "FromAddress": "[email protected]",
    "Username": "[email protected]",
    "Password": "Password1$",
    "EnableSsl": "true"
  },

The settings are injected and the SmtpClient gets properly instantiated and the sending of the email is just:

        var mail = new MailMessage
        {
            From = new MailAddress(_smtpSettings.FromAddress, _smtpSettings.SenderName),
            SubjectEncoding = Encoding.UTF8,
            BodyEncoding = Encoding.UTF8,
            IsBodyHtml = true,
            Body = message,
            Subject = subject,
            Priority = MailPriority.High
        };
        mail.To.Add(new MailAddress(sendToEmail));

        _smtpClient.Send(mail);

Sadly, the sending always fails with a gateway timeout. We tried switching for 587 for STARTTLS and providing the Username without the domain (@). The server sending has proper SSL certificate installed and the mailserver is exactly the one we have our smtp on. Although this would not be a relevant solution, I also increased the timeout to 10 seconds (even though this would not be a solution).

Any idea what could be wrong? I am tearing my hair already. Seems to be an issue with AWS WorkMail.


Solution

  • So the problem is that the default .NET Core SmtpClient does not support StartSSL (implicit SSL) which is the only accepted option by WorkMail. You see, WorkMail allows only connections that start from SSL and the SmtpClient first starts from unencrypted and then switches over to encrypted if it cannot connect.

    If you are trying this, you will not get this to work using standard SmtpClient and as usually the case with Microsoft, they don't recognize it as an issue. You can either try tunneling or better just use one of the available libraries. Sadly, most of them are paid, there is AIM but it doesn't work with .NET Core and I didn't want to spend time porting not my own library to .NET Standard so I ended up using Mailkit.

    There are some issues with the library though, first, before sending you have to call Connect which takes host and port as parameter, that means you cannot just inject premade smtpclient as singleton and have to instantiate it within the place of usage. That's dope and no interface also makes it unmockable which might blow your integration tests. Moreover, you have to do an ugly line before calling send like so:

    emailClient.AuthenticationMechanisms.Remove("XOAUTH2");
    

    But at least it works.