Как правильно пройти аутентификацию с помощью GMail OAuth2.0 в MailKit? - PullRequest
0 голосов
/ 16 марта 2020

Я пытаюсь использовать Mailkit для получения писем из моего Gmail:

private readonly string[] Scopes = { GmailService.Scope.GmailReadonly };
    private UserCredential GetGmailCredential()
    {
        UserCredential credential;
        using (var stream = new FileStream("client_id.json", FileMode.Open, FileAccess.Read))
        {
            // The file token.json stores the user's access and refresh tokens, and is created
            // automatically when the authorization flow completes for the first time.
            string credPath = "token.json";
            credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                GoogleClientSecrets.Load(stream).Secrets,
                Scopes,
                "user",
                CancellationToken.None,
                new FileDataStore(credPath, true),
                new LocalServerCodeReceiver()).Result;
            Console.WriteLine($"Credential file saved to: {credPath}");
        }

        return credential;
    }

    [HttpGet("check")]
    public string GetD()
    {
        using (var client = new ImapClient())
        {
            client.Connect("imap.gmail.com", 993, SecureSocketOptions.SslOnConnect);
            UserCredential credential = GetGmailCredential();
            //var oauth2 = new SaslMechanismOAuth2("myaccount008@gmail.com", credential.Token.AccessToken);
            var oauth2 = new SaslMechanismOAuth2("myaccount008",credential.Token.AccessToken);
            client.Authenticate(oauth2);
            client.Inbox.Open(FolderAccess.ReadOnly);

            var uids = client.Inbox.Search(SearchQuery.FromContains("bill"));
            string subjects = string.Empty;

            foreach (var uid in uids)
            {
                var message = client.Inbox.GetMessage(uid);
                subjects += message.Subject + Environment.NewLine;
                // write the message to a file
                message.WriteTo(string.Format("{0}.eml", uid));
            }

            client.Disconnect(true);
            return subjects;
        }
    }

Строка: client.Authenticate (oauth2); исключение ->

enter image description here

MailKit.Security.AuthenticationException

Я следовал за этим ответом на настроить мой Gmail API, но затем я получил проблему «Ошибка аутентификации».

Обновление 1

Вот журнал:

Connected to imaps://imap.gmail.com:993/ S: * OK Gimap ready for
requests from 122.199.45.135 d3mb920463124pjs C: A00000000 CAPABILITY
S: * CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST
CHILDREN X-GM-EXT-1 XYZZY SASL-IR AUTH=XOAUTH2 AUTH=PLAIN
AUTH=PLAIN-CLIENTTOKEN AUTH=OAUTHBEARER AUTH=XOAUTH S: A00000000 OK
Thats all she wrote! d3mb920463124pjs C: A00000001 AUTHENTICATE
XOAUTH2
dXNlcj1mcmFudmEwMDhAZ21haWwuY29tAWF1dGg9QmVhcmVyIHlhMjkuYTBBZHcxeGVWZDNSWWwzcVZlblZwVm1MbDBRRVVyWkdxd05veEd0QWpcLVhHNjRBaF90eWM0NWhwSFprZHA0d3dPWlpGMVZwbGM3dGo1Tm80eVMwc2lPNE1VYmhHV1I1WE9sdWtLUGY4TF9QU0dpZjhrSWM2UXNUbTQwYjlweDNBeXE4bVYtOTM2akEtSHdXekNQVFdGMGk0NGozX2FOTmhEYk5rAQE=
S: +
eyJzdGF0dXMiOiI0MDAiLCJzY2hlbWVzIjoPQmVhcmVyIiwic2NvcGUiOiJodHRwczovL21haWwuZ29vZ2xlLmNvbS8ifQ==
C:  S: A00000001 NO [AUTHENTICATIONFAILED] Invalid credentials
(Failure)

Область, которую я использую: GmailService.Scope.GmailReadonly , поскольку мне нужно только получать электронные письма.

Обновление 2

Обновлен мой объем:

private readonly string[] Scopes = { GmailService.Scope.MailGoogleCom };
Connected to imaps://imap.gmail.com:993/
S: * OK Gimap ready for requests from 122.199.45.135 s90mb321411106pjc
C: A00000000 CAPABILITY.
S: * CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 XYZZY SASL-IR AUTH=XOAUTH2 AUTH=PLAIN AUTH=PLAIN-CLIENTTOKEN AUTH=OAUTHBEARER AUTH=XOAUTH
S: A00000000 OK Thats all she wrote! s90mb321411106pjc
C: A00000001 AUTHENTICATE XOAUTH2 dXNlcj1mcmFudmEwMDhAZ21haWwuY29tAWF1dGg9QmVhcmVyIHlhMjkuYTBBZHcxeGVWZDNSWWwzcVZlblZwVm1MbDBRRVVyWkdxd05veEd0QWpXLVhHNjRBaF90eWM0NWhwSFprZHA0d3dPWlpGMVZwbGM3dGo1Tm80eVMwc2lPNE1VYmhHV1I1WE9sdWtLUGY4TF9QU0dpZjhrSWM2UXNUbTQwYjlweDNBeXE4bVYtOTM2akEtSHdXekNQVFdGMGk0NGozX2FPTmhEYk5rAQE=
S: +
eyJzdGF0dXMiOiI0MDAiLCJzY2hlbWVzIjoiSmVhcmVyIiwic2NvcGUiOiJodHRwczovL21haWwuZ29vZ2xlLmNvbS8ifQ==
C: 
S: A00000001 NO [AUTHENTICATIONFAILED] Invalid credentials (Failure)

Обновление 3

Я сохраняю все то же самое, а также пытался использовать GmailService.Scope.ReadOnly, затем заменил ImapClient на следующий код, теперь он работает.

      // Create Gmail API service.
        service = new GmailService(new BaseClientService.Initializer()
        {
            HttpClientInitializer = credential,
            ApplicationName = ApplicationName,
        });

Этот фрагмент кода взят из Gmail Api , Было бы здорово, если бы я мог использовать Mailkit для аутентификации.

1 Ответ

2 голосов
/ 17 марта 2020

Часть проблемы заключается в том, что вы используете неправильную область. Вам нужно использовать GoogleService.Scope.MailGoogleCom.

Область действия, которую вы используете, не для доступа к IMAP или POP3, она работает только для API веб-запросов Google.

У меня работает следующий код :

const string GMailAccount = "username@gmail.com";

var clientSecrets = new ClientSecrets {
    ClientId = "XXX.apps.googleusercontent.com",
    ClientSecret = "XXX"
};

var codeFlow = new GoogleAuthorizationCodeFlow (new GoogleAuthorizationCodeFlow.Initializer {
    DataStore = new FileDataStore ("CredentialCacheFolder", false),
    Scopes = new [] { "https://mail.google.com/" },
    ClientSecrets = clientSecrets
});

var codeReceiver = new LocalServerCodeReceiver ();
var authCode = new AuthorizationCodeInstalledApp (codeFlow, codeReceiver);
var credential = await authCode.AuthorizeAsync (GMailAccount, CancellationToken.None);

if (authCode.ShouldRequestAuthorizationCode (credential.Token))
    await credential.RefreshTokenAsync (CancellationToken.None);

var oauth2 = new SaslMechanismOAuth2 (credential.UserId, credential.Token.AccessToken);

using (var client = new ImapClient ()) {
    await client.ConnectAsync ("imap.gmail.com", 993, SecureSocketOptions.SslOnConnect);
    await client.AuthenticateAsync (oauth2);
    await client.DisconnectAsync (true);
}
...