Это очень сложная проблема, не поддерживаемая полной версией. 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
- Необходимо войти в свою учетную запись G Suite. Для выбора правильной учетной записи можно использовать значок в правом верхнем углу.
- Вверху слева Выберите проект = XProject, как указано выше
Экран согласия 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
Учетные данные
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