Question Comment envoyer un email dans .Net selon les nouvelles politiques de sécurité?


Pour mieux protéger vos utilisateurs, GMail et les autres fournisseurs de messagerie recommandent de mettre à niveau toutes nos applications vers OAuth 2.0.

Ai-je raison de dire que cela signifie que System.Net.Mail ne fonctionne plus et nous devons utiliser une autre bibliothèque comme MailKit?

En général, j'essaie de comprendre comment envoyer un courrier électronique sans autoriser "l'accès à des applications moins sécurisées"?

Parce que j'ai 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. Quand smtpClient.Send(message); réalisé.

Si le seul moyen de résoudre ce problème est d'utiliser MailKit, Je pense que cette question sera un bon tutoriel de changement pas à pas pratique System.Net.Mail à utiliser MailKit et Google.Apis.Auth.OAuth2. Je ne sais pas peut-être que la solution générale utilisera DotNetOpenAuth?

J'ai le cours suivant dans mon application qui correspond à envoyer un email à n'importe quelle adresse (gmail, yandex et autres):

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 => x.FailedRecipient);
            LogAndReThrowWithValidMessage(e, EmailsLocalization.EmailDeliveryFailed, failedRecipients);
        }
   }
}

Cela fonctionne bien jusqu'à la nouvelles politiques de sécurité Google.

je le sais System.Net.Mail ne supporte pas OAuth2. J'ai décidé d'utiliser MailKit's  SmtpClient pour envoyer des messages.

Après l’enquête, je comprends que mon code initial ne change pas tellement, car MailKit's L'API ressemble beaucoup (avec System.Net.Mail).

Sauf un détail: je dois avoir le jeton d'accès OAuth de l'utilisateur (MailKit n'a pas de code qui ira chercher le jeton OAuth, mais il peut l'utiliser si je l'ai).

Donc, à l'avenir, j'aurai la ligne suivante:

smtpClient.Authenticate (usersLoginName, usersOAuthToken);

J'ai une idée à ajouter GoogleCredentials comme nouveau paramètre à la SendEmail méthode:

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
}

Comment avoir usersOAuthToken? Est-ce la meilleure technique à utiliser? Google.Apis.Auth.OAuth2?

Le code que j'ai posté ci-dessus est pour GMail SEULEMENT et NE fonctionnera PAS pour yandex.ru ou d'autres fournisseurs de messagerie. Pour travailler avec d’autres, je devrai probablement utiliser une autre bibliothèque OAuth2. Mais je ne veux pas avoir beaucoup de mécanismes d'authentification dans mon code pour de nombreux fournisseurs de messagerie possibles. Je voudrais avoir une solution générale pour chaque fournisseur de messagerie. Et une bibliothèque capable d'envoyer du courrier électronique (comme .net smtpclient)


64
2018-01-18 09:40


origine


Réponses:


La solution générale est https://galleryserverpro.com/use-gmail-as-your-smtp-server-even-when-using-2-factor-authentication-2-step-verification/

1) Utilisez un navigateur pour vous connecter à votre compte Google et accédez à vos paramètres de connexion et de sécurité. Recherchez le paramètre de vérification en 2 étapes.

2) Si la vérification en 2 étapes est désactivée et que vous souhaitez la conserver de cette manière, cela signifie que vous devrez implémenter de nombreux mécanismes d'authentification, comme vous l'avez dit.

Solution: Activez-le, puis générez et utilisez le mot de passe google app. Ça devrait marcher! Vous n'avez pas besoin d'utiliser d'autres bibliothèques comme mailkit.


25
2018-01-21 07:07



Comment obtenir des utilisateursAutoToken?

La première chose à faire est de suivre Les instructions de Google pour obtenir les informations d'identification OAuth 2.0 pour votre application.

Une fois cela fait, le moyen le plus simple d’obtenir un jeton d’accès est d’utiliser Google. Google.Apis.Auth bibliothèque:

using System;
using System.Threading;
using System.Security.Cryptography.X509Certificates;

using Google.Apis.Auth.OAuth2;

using MimeKit;
using MailKit.Net.Smtp;
using MailKit.Security;

namespace Example {
    class Program
    {
        public static async void Main (string[] args)
        {
            var certificate = new X509Certificate2 (@"C:\path\to\certificate.p12", "password", X509KeyStorageFlags.Exportable);
            var credential = new ServiceAccountCredential (new ServiceAccountCredential
                .Initializer ("your-developer-id@developer.gserviceaccount.com") {
                    // Note: other scopes can be found here: https://developers.google.com/gmail/api/auth/scopes
                    Scopes = new[] { "https://mail.google.com/" },
                    User = "username@gmail.com"
                }.FromCertificate (certificate));

            // Note: result will be true if the access token was received successfully
            bool result = await credential.RequestAccessTokenAsync (CancellationToken.None);

            if (!result) {
                Console.WriteLine ("Error fetching access token!");
                return;
            }

            var message = new MimeMessage ();
            message.From.Add (new MailboxAddress ("Your Name", "username@gmail.com"));
            message.To.Add (new MailboxAddress ("Recipient's Name", "recipient@yahoo.com"));
            message.Subject = "This is a test message";

            var builder = new BodyBuilder ();
            builder.TextBody = "This is the body of the message.";
            builder.Attachments.Add (@"C:\path\to\attachment");

            message.Body = builder.ToMessageBody ();

            using (var client = new SmtpClient ()) {
                client.Connect ("smtp.gmail.com", 587, SecureSocketOptions.StartTls);

                // use the access token as the password string
                client.Authenticate ("username@gmail.com", credential.Token.AccessToken);

                client.Send (message);

                client.Disconnect (true);
            }
        }
    }
}

Est-ce la meilleure technique pour utiliser Google.Apis.Auth.OAuth2?

Pourquoi ne pas utiliser leur API pour obtenir un jeton d'authentification? Cela semble être le meilleur moyen de me le faire parvenir ...

Est-ce que je peux envoyer des emails à d'autres comptes non gmail?

Oui, tout e-mail que vous envoyez via GMail peut être envoyé à une autre adresse e-mail. à autres adresses GMail.


17
2018-01-19 19:55



Les erreurs d'authentification se produisent lors de l'utilisation du serveur smtp Gmail à partir d'applications ne mettant pas en œuvre les exigences de sécurité spécifiques de Google. Dans les paramètres du compte Gmail, activez:       "Inscription et sécurité">           "Applications et sites connectés">               "Autoriser les applications moins sécurisées">                   Sur


-1
2018-04-25 16:38