2

The goal: generate a draft email with body content and attachments and drop it into my current user's GMail account.

The environment: ASP.NET Core 3.1

I'm already using Google Authentication in my web app and am successfully requesting the Gmail Compose scope:

services
    .AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; })
    .AddCookie()
    .AddGoogle(options =>
    {
        IConfigurationSection googleAuthSection = Configuration.GetSection("Authentication:Google");
        options.ClientId = googleAuthSection["ClientId"];
        options.ClientSecret = googleAuthSection["ClientSecret"];
        options.Scope.Add(Google.Apis.Gmail.v1.GmailService.Scope.GmailCompose);
    });

From the various samples online, this is what I've found I need to do to generate a draft and save it to a gmail account:

var draft = new Draft();
draft.Message = new Message();
draft.Message.Payload = new MessagePart { Body = new MessagePartBody { Data = "hello world".ToBase64Url() } };

var clientSecrets = new ClientSecrets
{
    ClientId = _googleAuthSettings.ClientId,
    ClientSecret = _googleAuthSettings.ClientSecret
};
UserCredential credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
    clientSecrets,
    new[] { Google.Apis.Gmail.v1.GmailService.Scope.GmailCompose },
    user.Data.EmailAddress,
    CancellationToken.None);

var gservice = new Google.Apis.Gmail.v1.GmailService(
    new BaseClientService.Initializer
    {
        HttpClientInitializer = credential,
        ApplicationName = "Aeon"
    });

var createRequest = gservice.Users.Drafts.Create(draft, user.Data.EmailAddress);

The problem is that the call to GoogleWebAuthorizationBroker.AuthorizeAsync is a brand new auth request that pops a new browser window to auth against Google (which doesn't work because redirect urls and such). I've already authed the user through my existing startup/login process.

The two GmailService constructors take either no arguments or this BaseClientService.Initializer class, which itself takes a Google.Apis.Services.IConfigurableHttpClientInitializer object. In the sample above, the UserCredential class implements this interface. How do I use my existing login process' credentials to construct a gmail service? Alternatively, is there a way to do what I'm looking to do without having to construct a GmailService instance?

Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
minameismud
  • 91
  • 1
  • 9

1 Answers1

2

Answer:

You need to use Google.Apis.Auth.Mvc for web services, as GoogleWebAuthorizationBroker.AuthorizeAsync can not be used to create the authorization flow for web apps.

More Information:

As per the documentation on OAuth in Web Applications:

After creating a new web application project in your IDE, add the right Google.Apis NuGet package for Drive, YouTube, or the other service you want to use. Then, add the Google.Apis.Auth.MVC package.

The page also demonstrates an ASP.NET MVC application that queries a Google API service.

If you want to deploy GmailService on the web you need to make use of the Google.Apis.Auth.MVC package to make an implementation of the controllers.

Also from the source for the GoogleWebAuthorizationBroker class:

/// This class is only suitable for client-side use, as it starts a local browser 
/// that requires user interaction.
/// Do not use this class when executing on a web server, or any cases where the 
/// authenticating end-user is not able to do directly interact with a launched 
/// browser.

References:

Nimantha
  • 6,405
  • 6
  • 28
  • 69
Rafa Guillermo
  • 14,474
  • 3
  • 18
  • 54
  • That package - Google.Apis.Auth.MVC - is only for .NET Framework 4.5+, and I'm using .NET Core 3.1. However, I did find [Google.Apis.Auth.AspNetCore](https://www.nuget.org/packages/Google.Apis.Auth.AspNetCore/1.46.0?_src=template) which might be useful. – minameismud Jun 24 '20 at 13:09
  • 2
    Update: Google.Apis.Auth.AspNetCore is only for up to Core 2.1 due to breaking changes in .NET Core 3's auth handling. To support Core 3, there's a beta library named [Google.Apis.Auth.AspNetCore3](https://www.nuget.org/packages/Google.Apis.Auth.AspNetCore3/1.46.0-beta01?_src=template). Found that by googling the error message you get trying to use the first library and got it from [this GitHub issue link](https://github.com/googleapis/google-api-dotnet-client/issues/1413) and then [this GitHub issue link](https://github.com/googleapis/google-api-dotnet-client/issues/1434). – minameismud Jun 24 '20 at 13:27