17

我有一个桌面应用程序,可以通过 REST 接口使用 GMAIL API 来阅读邮件。我想使用服务帐户,以便我们可以使用域设置下载邮件,并且用户交互为空。我成功地创建了 Gmail 服务实例,但是当我尝试访问任何 Gmail API 方法(如获取邮件列表或任何其他方法)时,我得到一个异常说

Google.Apis.Auth.OAuth2.Responses.TokenResponseException:错误:“access_denied”,描述:“请求的客户端未授权。”

我完成了开发者控制台上的所有设置,并为我的 gapps 域添加了范围。

Gmail API 是否支持服务帐户?使用相同的设置和服务帐户,我可以使用 Drive 服务和 API 获取 Google 驱动器中所有文件的列表。

4

6 回答 6

16

我使用以下 C# 代码从服务帐户访问 Gmail

String serviceAccountEmail =
    "999999999-9nqenknknknpmdvif7onn2kvusnqct2c@developer.gserviceaccount.com";

var certificate = new X509Certificate2(
    AppDomain.CurrentDomain.BaseDirectory +
        "certs//fe433c710f4980a8cc3dda83e54cf7c3bb242a46-privatekey.p12",
    "notasecret",
    X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);

string userEmail = "user@domainhere.com.au";

ServiceAccountCredential credential = new ServiceAccountCredential(
    new ServiceAccountCredential.Initializer(serviceAccountEmail)
    {
        User = userEmail,
        Scopes = new[] { "https://mail.google.com/" }
    }.FromCertificate(certificate)
);

if (credential.RequestAccessTokenAsync(CancellationToken.None).Result)
{   
    GmailService gs = new GmailService(
        new Google.Apis.Services.BaseClientService.Initializer()
        {
            ApplicationName = "iLink",
            HttpClientInitializer = credential
        }
    );

    UsersResource.MessagesResource.GetRequest gr =
        gs.Users.Messages.Get(userEmail, msgId);
    gr.Format = UsersResource.MessagesResource.GetRequest.FormatEnum.Raw;
    Message m = gr.Execute();

    if (gr.Format == UsersResource.MessagesResource.GetRequest.FormatEnum.Raw)
    {
        byte[] decodedByte = FromBase64ForUrlString(m.Raw);
        string base64Encoded = Convert.ToString(decodedByte);
        MailMessage msg = new MailMessage();
        msg.LoadMessage(decodedByte);
    }
}
于 2014-07-17T05:04:19.290 回答
3

如果您想“阅读邮件”,您将需要更新的 Gmail API(而不是指出的“丢失二进制”的旧管理设置 API)。是的,您可以使用 oauth2 和较新的 Gmail API 执行此操作,您需要在 Cpanel 中将开发人员列入白名单并创建一个密钥,您可以使用它来签署您的请求——设置需要一点时间: https ://developers.google.com /accounts/docs/OAuth2ServiceAccount#formingclaimset

于 2014-07-16T15:51:38.100 回答
3

这是python 3.7的一点点:

from google.oauth2 import service_account
from googleapiclient.discovery import build

def setup_credentials():
    key_path = 'gmailsignatureproject-zzz.json'
    API_scopes =['https://www.googleapis.com/auth/gmail.settings.basic',
                 'https://www.googleapis.com/auth/gmail.settings.sharing']
    credentials = service_account.Credentials.from_service_account_file(key_path,scopes=API_scopes)
    return credentials


def test_setup_credentials():
    credentials = setup_credentials()
    assert credentials


def test_fetch_user_info():
    credentials = setup_credentials()
    credentials_delegated = credentials.with_subject("tim@vci.com.au")
    gmail_service = build("gmail","v1",credentials=credentials_delegated)
    addresses = gmail_service.users().settings().sendAs().list(userId='me').execute()
    assert gmail_service
于 2019-01-21T08:56:33.633 回答
2

是的,您可以...检查委派设置...

https://developers.google.com/admin-sdk/directory/v1/guides/delegation#delegate_domain-wide_authority_to_your_service_account

编辑:使用 Eric DeFrez 共享的链接。

于 2014-07-16T13:05:12.207 回答
2

对于 C# Gmail API v1,您可以使用以下代码获取 gmail 服务。使用 gmail 服务阅读电子邮件。在 Google Console 站点中创建服务帐户后,下载 json 格式的密钥文件。假设文件名为“service.json”。

    public static GoogleCredential GetCredenetial(string serviceAccountCredentialJsonFilePath)
    {
        GoogleCredential credential;

        using (var stream = new FileStream(serviceAccountCredentialJsonFilePath, FileMode.Open, FileAccess.Read))
        {
            credential = GoogleCredential.FromStream(stream)
                .CreateScoped(new[] {GmailService.Scope.GmailReadonly})
                .CreateWithUser(**impersonateEmail@email.com**);
        }

        return credential;
    }

    public static GmailService GetGmailService(GoogleCredential credential)
    {
        return new GmailService(new BaseClientService.Initializer()
        {
            HttpClientInitializer = credential,                
            ApplicationName = "Automation App",                
        });
    }

   // how to use
   public static void main()
   {
        var credential = GetCredenetial("service.json");
        var gmailService = GetGmailService(credential);

        // you can use gmail service to retrieve emails. 
        var mMailListRequest = gmailService.Users.Messages.List("me");
        mMailListRequest.LabelIds = "INBOX";

        var mailListResponse = mMailListRequest.Execute();            
   }
于 2019-09-18T19:11:41.537 回答
1

您可以使用新的 Gmail API 访问任何 user@YOUR_DOMAIN.COM 邮件/标签/线程等:

https://developers.google.com/gmail/api/

通过模拟服务帐户(服务帐户正在访问 api,就好像它是您域中的特定用户一样)。

在此处查看详细信息: https ://developers.google.com/identity/protocols/OAuth2ServiceAccount

以下是 Dartlang 中的相关代码:

import 'package:googleapis_auth/auth_io.dart' as auth;
import 'package:googleapis/gmail/v1.dart' as gmail;
import 'package:http/http.dart' as http;

 ///credentials created with service_account here  https://console.developers.google.com/apis/credentials/?project=YOUR_PROJECT_ID 
final String creds = r'''
{
  "private_key_id": "FILL_private_key_id",
  "private_key": "FILL_private_key",
  "client_email": "FILL_service_account_email",
  "client_id": "FILL_client_id",
  "type": "service_account"
}''';


Future<http.Client> createImpersonatedClient(String impersonatedUserEmail, List scopes) async {
  var impersonatedCredentials = new auth.ServiceAccountCredentials.fromJson(creds,impersonatedUser: impersonatedUserEmail);
  return auth.clientViaServiceAccount(impersonatedCredentials  , scopes);
}



getUserEmails(String userEmail) async { //userEmail from YOUR_DOMAIN.COM
  var client = await  createImpersonatedClient(userEmail, [gmail.GmailApi.MailGoogleComScope]);
  var gmailApi = new gmail.GmailApi(client);
  return gmailApi.users.messages.list(userEmail, maxResults: 5);
}
于 2015-10-28T15:31:37.057 回答