Search code examples
c#asp.netgoogle-apigmail-apiserver-side

Sending emails via Google API from a ASP.NET application


So I have been sending emails from my .NET WebApp via GmailService for the past 2 years and now it suddently stopped working. Here's my piece of code sending emails.

It breaks on the line

var renew = credential.GetAccessTokenForRequestAsync().Result;

with the following error:

{Error:"invalid_grant", Description:"Bad Request", Uri:""}

var tokenResponse = new TokenResponse { RefreshToken = sendData.refreshToken };
UserCredential credential = new UserCredential(new ForceOfflineGoogleAuthorizationCodeFlow(
        new GoogleAuthorizationCodeFlow.Initializer
        {
            ClientSecrets = new ClientSecrets
            {
                ClientId = sendData.clientID,
                ClientSecret = sendData.clientSecret
            },
            Scopes = Scopes
        }
        ),
        "me",
        tokenResponse);

var renew = credential.GetAccessTokenForRequestAsync().Result;

// Create service
var service = new GmailService(new BaseClientService.Initializer()
{
    ApplicationName = "MySuperNonWorkingApplication",
    HttpClientInitializer = credential,
});

var message = CreateRawMessageSystemNet(sendData.sendToAddresses,sendData.subject,sendData.body,sendData.email,sendData.emailDisplayName,sendData.attachments);

var result = service.Users.Messages.Send(new Message
{
    Raw = message
}, "me").Execute();

For the UserCredential IAuthorizationCodeFlow parameter I'm using class

internal class ForceOfflineGoogleAuthorizationCodeFlow : GoogleAuthorizationCodeFlow
{
    public ForceOfflineGoogleAuthorizationCodeFlow(GoogleAuthorizationCodeFlow.Initializer initializer) : base(initializer) { }

    public override AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest(string redirectUrl)
    {
        return new GoogleAuthorizationCodeRequestUrl(new Uri(AuthorizationServerUrl))
        {
            ClientId = ClientSecrets.ClientId,
            Scope = string.Join(" ", Scopes),
            RedirectUri = redirectUrl,
            AccessType = "offline",
            ApprovalPrompt = "force"
        };
    }
}

If you're wondering about the content of the object credential when sending it looks like this: enter image description here The Scopes variable is "https://mail.google.com/"

Thank you very much in advance!


Solution

  • Looks like I managed to resolve the issue. It was nothing wrong with the code, the code works perfectly fine. The problem was the refresh token. To resolve the issue I had to go to https://developers.google.com/oauthplayground. Then on the right side click the cog wheel, "Use your own OAuth credentials" and had to insert to ClientID and Client secret. On the left side, underneath step 1 I had to choose Gmail API (https://mail.google.com/) and click "Authorize API". By doing so, underneath step 2 I received a new Authorization Code and upon clicking "Exchange authorization code for tokens" I received new refresh token. Now upon inserting the new refresh token into

    var tokenResponse = new TokenResponse { RefreshToken = sendData.refreshToken };
    

    the code works as it's supposted to.