c# - 없이 - smtp 서버에 보안 연결이 필요하거나 클라이언트가 인증되지 않았습니다.




새로운 보안 정책에 따라.Net에서 이메일을 보내는 방법은 무엇입니까? (2)

사용자를보다 효과적으로 보호하기 위해 GMail 및 기타 메일 제공 업체는 모든 응용 프로그램을 OAuth 2.0으로 업그레이드 할 것을 권장합니다.

이것이 System.Net.Mail 이 더 이상 작동하지 않으며 MailKit 과 같은 다른 라이브러리를 사용해야한다는 것을 의미합니까?

일반적으로 "보안 수준이 낮은 앱에 액세스"를 허용하지 않고 이메일을 보내는 방법을 이해하려고합니까?

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. 있기 때문에 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. 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. smtpClient.Send(message);smtpClient.Send(message); 처형.

이 문제를 해결하는 유일한 방법이 MailKit 사용하는 MailKit 이 질문은 System.Net.Mail 에서 MailKitGoogle.Apis.Auth.OAuth2 사용으로 전환하는 좋은 실용적인 단계별 전환 자습서라고 생각합니다. 어쩌면 일반적인 솔루션이 DotNetOpenAuth 사용 DotNetOpenAuth .

내 응용 프로그램에 다음 주소가있어 모든 주소 (gmail, yandex 및 기타)로 이메일을 보냅니다.

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);
        }
   }
}

새로운 Google 보안 정책 까지 제대로 작동합니다.

System.Net.MailOAuth2 지원하지 않는다는 것을 알고 있습니다. MailKit's SmtpClient 를 사용하여 메시지를 보내기로 결정했습니다.

조사 후 MailKit's API가 System.Net.Mail 과 매우 유사하게 보이기 때문에 초기 코드가 크게 변경되지 않는다는 것을 알고 있습니다.

한 가지 세부 사항을 제외하고 : 사용자의 OAuth 액세스 토큰이 필요합니다 (MailKit에는 OAuth 토큰을 가져올 코드가 없지만 가지고 있으면 사용할 수 있습니다).

앞으로 나는 다음 줄을 가질 것입니다.

smtpClient.Authenticate (usersLoginName, usersOAuthToken);

SendEmail 메소드에 GoogleCredentials 를 새 매개 변수로 추가하는 아이디어가 있습니다.

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
}

usersOAuthToken 을 얻는 방법? Google.Apis.Auth.OAuth2 를 사용하는 것이 가장 좋은 방법입니까?

위에 게시 한 코드는 Gmail 전용이며 yandex.ru 또는 다른 메일 제공 업체에서는 작동하지 않습니다. 다른 사람들과 협력하려면 다른 OAuth2 라이브러리를 사용해야 할 것입니다. 그러나 가능한 많은 메일 공급자를 위해 코드에 많은 인증 메커니즘을 갖고 싶지 않습니다. 모든 메일 제공 업체에 대해 하나의 일반 솔루션을 원합니다. 그리고 이메일을 보낼 수있는 하나의 라이브러리 (.net smtpclient처럼)


usersOAuthToken을 얻는 방법?

가장 먼저해야 할 일은 애플리케이션의 OAuth 2.0 자격 증명을 얻기위한 Google의 지침 을 따르는 것입니다.

일단 액세스 토큰을 얻는 가장 쉬운 방법은 Google의 Google.Apis.Auth 라이브러리를 사용하는 것입니다.

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 ("[email protected]") {
                    // Note: other scopes can be found here: https://developers.google.com/gmail/api/auth/scopes
                    Scopes = new[] { "https://mail.google.com/" },
                    User = "[email protected]"
                }.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", "[email protected]"));
            message.To.Add (new MailboxAddress ("Recipient's Name", "[email protected]"));
            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 ("[email protected]", credential.Token.AccessToken);

                client.Send (message);

                client.Disconnect (true);
            }
        }
    }
}

Google.Apis.Auth.OAuth2를 사용하는 것이 가장 좋은 방법입니까?

인증 토큰을 얻기 위해 API를 사용하지 않는 이유는 무엇입니까? 나에게 그것을 얻는 가장 좋은 방법 인 것 같습니다 ...

Gmail이 아닌 다른 계정으로 이메일을 보낼 수 있습니까?

예, GMail을 통해 보내는 모든 전자 메일은 다른 전자 메일 주소로 보낼 수 있습니다. 다른 GMail 주소 만있을 필요는 없습니다.


Google의 특정 보안 요구 사항을 구현하지 않는 애플리케이션에서 Gmail smtp 서버를 사용할 때 인증 오류가 발생합니다. Gmail 계정 설정에서 "로그인 및 보안"> "연결된 앱 및 사이트"> "보안 수준이 낮은 앱 허용"> 설정





.net