75 votes

Comment envoyer un courriel en .Net selon les nouvelles politiques de sécurité ?

Pour mieux protéger vos utilisateurs, GMail et d'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 fonctionnent plus et nous devons utiliser une autre bibliothèque comme MailKit ?

En général, j'essaie de comprendre comment envoyer un courriel sans autoriser "l'accès aux 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. Lorsque smtpClient.Send(message); exécuté.

Si la seule façon de résoudre ce problème est d'utiliser MailKit Je pense que cette question sera un bon tutoriel pratique sur la commutation, étape par étape, à partir de System.Net.Mail à l'utilisation MailKit y Google.Apis.Auth.OAuth2 . Je ne sais pas si la solution générale sera d'utiliser DotNetOpenAuth ?

J'ai la classe suivante 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'à ce que le les nouvelles règles de sécurité de Google .

Sé que System.Net.Mail ne prend pas en charge 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, parce que MailKit's L'API est très similaire (avec System.Net.Mail ).

A un détail près : Je dois disposer du jeton d'accès OAuth de l'utilisateur (MailKit ne dispose pas de code permettant de récupérer le jeton OAuth, mais il peut l'utiliser si je l'ai).

Ainsi, à 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 obtenir 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, j'aurai probablement besoin d'utiliser une autre bibliothèque OAuth2. Mais je ne veux pas avoir de nombreux mécanismes d'authentification dans mon code pour de nombreux fournisseurs de messagerie possibles. J'aimerais avoir UNE SOLUTION GÉNÉRALE pour tous les fournisseurs de courrier électronique. Et une bibliothèque qui peut envoyer des e-mails (comme .net smtpclient).

S'il vous plaît, aidez-moi !

35voto

Anatoly Points 187

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 allez dans vos paramètres de connexion et de sécurité. Recherchez le paramètre de vérification en deux étapes.

2) Si la vérification en deux étapes est désactivée et que vous souhaitez la conserver, cela signifie que vous devrez mettre en œuvre plusieurs mécanismes d'authentification comme vous l'avez dit.

Solution : Allumez-le et utilisez le mot de passe Google. Cela devrait fonctionner ! Vous n'avez pas besoin d'utiliser d'autres bibliothèques comme mailkit .

19voto

jstedfast Points 5684

Comment obtenir usersOAuthToken ?

La première chose que vous devez faire est de suivre Les instructions de Google pour obtenir des informations d'identification OAuth 2.0 pour votre application.

Une fois que vous avez fait cela, le moyen le plus simple d'obtenir un jeton d'accès est d'utiliser le service de 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 que la technique des meilleures pratiques consiste à utiliser Google.Apis.Auth.OAuth2 ?

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

Est-ce que je peux envoyer un courriel à d'autres comptes non gmail ?

Oui, tout courrier électronique que vous envoyez par GMail peut être envoyé à n'importe quelle autre adresse électronique - il n'est pas nécessaire qu'il soit seulement à d'autres adresses GMail.

1voto

user713836 Points 11

Des erreurs d'authentification surviennent lors de l'utilisation du serveur smtp de 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 : "Connexion et sécurité" > "Applications et sites connectés" > "Autoriser les applications moins sécurisées". Sur

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X