title: How to send an email in .Net according to new security policies?
body: <p>To better protect your users, GMail and others mail providers recommends to upgrade all of our applications to OAuth 2.0. </p>
  
  <p>Am I right that this means that <code>System.Net.Mail</code> don't work anymore and we need to use another library like <code>MailKit</code>?</p>
  
  <p>In general I'm trying to understand how to send an email without allowing "Access for less secure apps"? </p>
  
  <p>Because I have <code>System.Net.Mail.SmtpException: The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.5.1 Authentication Required.</code> When <code>smtpClient.Send(message);</code> executed.</p>
  
  <p>If the only way to solve this problem is using <code>MailKit</code>, I think that this question will be a good practical step-by-step switching tutorial from <code>System.Net.Mail</code> to using <code>MailKit</code> and <code>Google.Apis.Auth.OAuth2</code>. I don't know maybe general solution will be using <code>DotNetOpenAuth</code>?</p>
  
  <p>I have the following class in my application that correspond to send an email to any address(gmail, yandex and others):</p>
  
  <pre><code>public class EmailSender
  {
      public void SendEmail(SmtpServerSettings serverSettings, SendEmailRequest emailRequest)
      {
          // Usually I have 587 port, SmtpServerName = smtp.gmail.com 
          _logger.Trace("Sending message with subject '{0}' using SMTP server {1}:{2}",
                        emailRequest.Subject,
                        serverSettings.SmtpServerName,
                        serverSettings.SmtpPort);
  
          try
          {
              using (var smtpClient = new SmtpClient(serverSettings.SmtpServerName, (int)serverSettings.SmtpPort))
              {
                  smtpClient.EnableSsl = serverSettings.SmtpUseSsl; // true
                  if (!string.IsNullOrEmpty(serverSettings.UserName) || !string.IsNullOrEmpty(serverSettings.EncryptedPassword))
                  {
                      smtpClient.Credentials = new NetworkCredential(serverSettings.UserName, serverSettings.EncryptedPassword);
                  }
  
                  smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
                  smtpClient.Timeout = (int)serverSettings.SmtpTimeout.TotalMilliseconds;
  
                  using (var message = new MailMessage())
                  {
                      message.From = new MailAddress(serverSettings.FromAddress);
  
                      emailRequest.To.ForEach(message.To.Add);
                      emailRequest.CC.ForEach(message.CC.Add);
                      emailRequest.Bcc.ForEach(message.Bcc.Add);
  
                      message.Subject = emailRequest.Subject.Replace('\r', ' ').Replace('\n', ' ');
                      message.Body = emailRequest.Body;
                      message.BodyEncoding = Encoding.UTF8;
                      message.IsBodyHtml = false;
  
                      smtpClient.Send(message);
                  }
              }
  
              _logger.Trace("Sent message with subject '{0}' using SMTP server {1}:{2}",
                            emailRequest.Subject,
                            serverSettings.SmtpServerName,
                            serverSettings.SmtpPort);
          }
          catch (SmtpFailedRecipientsException e)
          {
              var failedRecipients = e.InnerExceptions.Select(x =&gt; x.FailedRecipient);
              LogAndReThrowWithValidMessage(e, EmailsLocalization.EmailDeliveryFailed, failedRecipients);
          }
     }
  }
  </code></pre>
  
  <p>It works fine until the <a href="https://support.google.com/accounts/answer/6010255?hl=en" rel="noreferrer">new Google security policies</a>.</p>
  
  <p>I know that <code>System.Net.Mail</code> does not support <code>OAuth2</code>. I decided to use <code>MailKit's</code> <code>SmtpClient</code> to send messages.</p>
  
  <p>After the investigation I understand that my initial code not change so much, because <code>MailKit's</code> API looks very similar(with <code>System.Net.Mail</code>).</p>
  
  <p>Except one detail: I need to have the user's OAuth access token (MailKit does not have code that will fetch the OAuth token, but it can use it if I have it).</p>
  
  <p>So in the future I will have the following line:</p>
  
  <pre><code>smtpClient.Authenticate (usersLoginName, usersOAuthToken);
  </code></pre>
  
  <p>I have an idea to add <code>GoogleCredentials</code> as new parameter to the <code>SendEmail</code> method:</p>
  
  <pre><code>public void SendEmail(SmtpServerSettings serverSettings, SendEmailRequest emailRequest, 
                        GoogleCredentials credentials)
  {
      var certificate = new X509Certificate2(credentials.CertificateFilePath,
                                             credentials.PrivateKey,
                                             X509KeyStorageFlags.Exportable);
  
       var credential = new ServiceAccountCredential(
                        new ServiceAccountCredential.Initializer(credentials.ServiceAccountEmail)
                               {
                                   Scopes = new[] { "https://mail.google.com/" },
                                   User = serverSettings.UserName
                               }.FromCertificate(certificate));
  
      ....
      //my previous code but with MailKit API
  }
  </code></pre>
  
  <p>How to get <code>usersOAuthToken</code>?
  Is it the best practice technique to use <code>Google.Apis.Auth.OAuth2</code>?</p>
  
  <p>The code I posted above is for GMail ONLY and WILL NOT work for yandex.ru or other mail providers. To work with others, I will probably need to use another OAuth2 librarys. But I don't want to have many authentication mechanisms in my code for many possible mail providers. I would like to have ONE GENERAL SOLUTION for every mail providers. And one library that can send email (like .net smtpclient did)</p>