Как использовать OAuth2 для использования SMTP-сервера Gmail из приложения VB. NET P C - PullRequest
0 голосов
/ 27 апреля 2020

Это очень сложная проблема, не поддерживаемая полной версией. net примеров.

Мое решение работает, но я подозреваю, что могут быть более эффективные способы. Прокомментируйте, пожалуйста. Три шага

1) Require Gmail Client Id and Gmail Client Secret. 
2) Get Token from Client Id and Gmail Client Secret 
3) Use Token to send email.

Шаг 1 Мое приложение используется многими клиентами в Великобритании, и каждый должен будет выполнить шаг 1. Я обнаружил, что мне нужно купить G Suite, чтобы сделать шаг 2 работы. Может ли это быть легко достигнуто без G Suite?

Использовать ссылку https://console.developers.google.com/cloud-resource-manager?pli=1

1. Need to be logged onto your G Suite account. Top right person icon may be used to select correct account.
2. + CREATE PROJECT
    A. Project  Name = Any Name say XProject
    B. Organisation = Here is chose part of my G Suite Id. I don't think important.
    C. Location = Here is chose part of my G Suite Id. I don't think important.
    D. CREATE

Может занять несколько секунд.

https://console.developers.google.com

  1. Необходимо войти в свою учетную запись G Suite. Для выбора правильной учетной записи можно использовать значок в правом верхнем углу.
  2. Вверху слева Выберите проект = XProject, как указано выше
  3. Экран согласия OAuth

    A. user Type = Internal (G Suite allows this and this helps token creation)
    B. CREATE
    C. OAuth consent screen
            a. Application name = GetBookedUp as above
            b. Support email =  G Suite email address
            c. Save
            d. Ignore OAuth rate limits
    
  4. Учетные данные

    A. + Create Credentials / OAuth client ID
    
    B. Application type = Other
    
    C.  Name = GetBookedUp, probably can be something else
    
    D. Create
    
        a. OAuth client created
        b. Use icon buttons to right to copy to clib board and record Client Id and Client Secret
    

Шаг 2 Получить токен

Требуется Google.Apis.Auth.OAuth2

Сервис / NuGet Packet Manager / PM> Install-Package Google.Apis.Auth

Require

Imports Google.Apis.Auth.OAuth2
Imports System.Threading

Public Function GetAccessTokenFail(ByVal strGmailClientId As String, ByVal strGmailClientSecret As String, ByRef strAccessToken As String ) As Boolean
        'based on  Example      https://www.emailarchitect.net/easendmail/sdk/html/object_oauth.htm
        Try
            Dim clientsecret As ClientSecrets = New ClientSecrets With {
            .ClientId = strGmailClientId,
            .ClientSecret = strGmailClientSecret
            }

            Dim scopes As String() = New String() {"https://mail.google.com/", "email"}
            Dim credential As UserCredential = GoogleWebAuthorizationBroker.AuthorizeAsync(clientsecret, scopes, "user", CancellationToken.None).Result

            If credential.Token.IsExpired(credential.Flow.Clock) Then
                'Console.WriteLine("The access token has expired, refreshing it")

                If credential.RefreshTokenAsync(CancellationToken.None).Result Then
                    'Console.WriteLine("The access token is now refreshed")
                Else
                    ErrorMsg = "The access token has expired but we can't refresh it." : Return True
                End If
            Else
                'Console.WriteLine("The access token is OK, continue")
            End If
            strAccessToken = credential.Token.AccessToken

            Return False
        Catch ex As Exception
            ErrorMsg = ex.Message
            If ex.InnerException IsNot Nothing Then
                ErrorMsg &= " / " & ex.InnerException.Message
            End If
            Return True
        End Try
    End Function

Когда это работает хорошо, открывается браузер, и пользователь выбирает пользователя G Suite. Список включает в себя все учетные записи Gmail, используемые в этом браузере.

Проблема с этим логом c заключается в том, что он зависает, когда некоторые данные не верны, и нелегко закрыть пользователя. Также нет полезных сообщений.

Поэтому я обертываю

Dim credential As UserCredential = GoogleWebAuthorizationBroker.AuthorizeAsync(clientsecret, scopes, "user", CancellationToken.None).Result

кодом, чтобы вытащить меня из этого. Это неряшливо, но я считаю, что альтернативу трудно понять и реализовать быстро

mblnTimeOut = False
            Dim timer As System.Timers.Timer = New System.Timers.Timer(20000)   '20 secs
            AddHandler timer.Elapsed, New Timers.ElapsedEventHandler(AddressOf TimerElapsed)
            timer.Start()
            Dim credential As UserCredential = GoogleWebAuthorizationBroker.AuthorizeAsync(clientsecret, scopes, "user", CancellationToken.None).Result
            timer.Stop()
            If mblnTimeOut Then ErrorMsg = "Timed out." : Return True

mblnTimeOut объявлено вне этого и здесь обрабатывается событие времени

Private Sub TimerElapsed(ByVal sender As Object, ByVal e As Timers.ElapsedEventArgs)
        mblnTimeOut = True
        CType(sender, System.Timers.Timer).Stop()
        MsgBox("Time out on trying to get Credentials for supplied Client Id and Secret." & vbCrLf & "System possibly locked and therefore will closedown")
        End
    End Sub

Шаг 3 отправка электронной почты.

Используется MailKit

Инструменты / NuGet Packet Manager / PM> Install-Package MailKit

Imports MailKit
Imports MailKit.Net.Smtp
Imports MimeKit
Imports MimeKit.Text
Imports MailKit.Security

Создание электронной почты в MimeMessage

Код может быть предоставлен для этого. Мне нужно было использовать BodyBuilder для обработки вложений с помощью HtmlBody

Использование strAccessToken из шага 2

strUserId - это идентификатор пользователя G Suite, выбранный на шаге 2 с помощью браузера и используемый для создания секретного клиента и клиента ID

Try
    dim SmtpClient1 = New SmtpClient

            Dim OAuth2 As New SaslMechanismOAuth2(strUserId, strAccessToken)
            SmtpClient1.Connect("smtp.gmail.com", 587, SecureSocketOptions.StartTls)

            SmtpClient1.AuthenticationMechanisms.Remove("XOAUTH2")
            SmtpClient1.Authenticate(OAuth2)
        SmtpClient1.Send(EmailMessage1.MimeMessage1)
            SmtpClient1.Disconnect(True)

        Catch ex As MailKit.Security.AuthenticationException
            ErrorMsg = "Security Authentication Exception - " & ex.Message
            Return True

        Catch ex As Exception
            ErrorMsg = "Failure to authenticate - " & ex.Message
            Return True
        End Try
...