1

我的目标是更新我域中的所有用户电子邮件签名。

我已经设置了一个具有域范围委派权限的服务帐户。但我遇到了这个错误:

{
 "error": {
  "errors": [
   {\n
    "domain": "global",
    "reason": "failedPrecondition",
    "message": "Bad Request"
   }
  ],
  "code": 400,
  "message": "Bad Request"
 }
}

我使用的请求与 API Explorer 执行的请求相同。所以它应该是格式良好的......

在 API 资源管理器中,它也不能正常工作,我有这个答案:

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "forbidden",
    "message": "Delegation denied for vivien@mydomain.com"
   }
  ],
  "code": 403,
  "message": "Delegation denied for vivien@mydomain.com"
 }
}

好像我有权限问题,但我不知道为什么。

这是我的 PHP 测试代码以供参考:

 public function updateSignAction(){

    putenv('GOOGLE_APPLICATION_CREDENTIALS='.$this->get('kernel')->getRootDir().'/../app/Resources/files/mydomain.json');

    $client = new \Google_Client();
    $client->useApplicationDefaultCredentials();
    $client->setApplicationName("demo");
    $client->addScope([
        "https://www.googleapis.com/auth/gmail.settings.basic",
        "https://www.googleapis.com/auth/gmail.settings.sharing"
    ]);
    //$client->setSubject('vivien@mydomain.com');
    $httpClient = $client->authorize();

    $response = $httpClient->put(
       'https://www.googleapis.com/gmail/v1/users/vivien@mydomain.com/settings/sendAs/test',
       [
            'json' => [
                'signature' => "test-via-api"
            ]
        ]
    );

    return $this->render('AdminBundle:GoogleApi:user/update.html.twig', array(
        'response' => $response->getBody()->getContents(),
    ));
}
4

1 回答 1

0

您必须对 API 进行身份验证。为此,有两种方法:

  • 使用 OAuth - 服务器将用户重定向到 google 的服务器,在那里他们可以登录、授予您的应用程序权限并将令牌传回给您
  • 服务帐户。这些有点复杂:
  • 首先,您必须设置一个应用程序(完成)
  • 其次,您必须设置一个服务帐户。这就是您的应用向 google 进行身份验证的方式。您已经完成了,您获得的证书包含用于身份验证的私钥
  • 第三,用户需要授予您的应用程序访问权限以代表他们执行操作。这是你还没有完成的点。

因此,您当前尝试的是从服务帐户发送邮件,但这不是 Gmail 帐户。

另请注意:使用常规 GMail 帐户,您不能使用“服务帐户”。您必须使用 OAuth。要使用服务帐户,您需要成为 Google Apps 客户。

要授予您的服务帐户权限以代表您的 GMails/Google Apps 帐户发送邮件,请遵循此文档。对于一个或多个 API 范围,您必须输入https://mail.google.com/,https://www.googleapis.com/auth/gmail.modify,https://www.googleapis.com/auth/gmail.compose,https://www.googleapis.com/auth/gmail.send.

设置好之后就可以发送邮件了,修改代码如下:

$results = $service->users_messages->send("me", $msg);

不起作用,因为“我”指的是不能发送邮件的服务帐户(见上文)。替换me为应发送邮件的帐户的用户 ID(邮件地址)。:

$results = $service->users_messages->send("senders_mail@domain.com", $msg);

然后,您需要添加

$cred->sub = 'senders_mail@domain.com';
below

$cred = new \Google_Auth_AssertionCredentials(
  $service_account_name,
  array('https://www.googleapis.com/auth/gmail.send', 'https://www.googleapis.com/auth/gmail.compose'),
  $key
);

<?php
require_once realpath(dirname(__FILE__) . '/../src/Google/autoload.php');
$client_id = '*censored*.apps.googleusercontent.com';
$service_account_name = '*censored*@developer.gserviceaccount.com';
$key_file_location = '/tmp/apiKey.p12';

$userid_from='*censored*';
$client = new \Google_Client();
$client->setApplicationName("Client_Library_Examples");

if (isset($_SESSION['service_token'])) {
  $client->setAccessToken($_SESSION['service_token']);
}

$key = file_get_contents($key_file_location);
$cred = new \Google_Auth_AssertionCredentials(
  $service_account_name,
  array('https://www.googleapis.com/auth/gmail.send', 'https://www.googleapis.com/auth/gmail.compose', 'https://www.googleapis.com/auth/gmail.modify','https://www.googleapis.com/auth/gmail.readonly'),
  $key
);
$cred->sub=$userid_from;
$client->setAssertionCredentials($cred);

if ($client->getAuth()->isAccessTokenExpired()) {
  $client->getAuth()->refreshTokenWithAssertion($cred);
}

 $mime = "*censored*";

$service = new \Google_Service_Gmail($client);

$msg = new \Google_Service_Gmail_Message();
$msg->setRaw($mime);

try {
  $results = $service->users_messages->send($userid_from, $msg);
  print 'Message with ID: ' . $results->id . ' sent.';
} catch (\Exception $e) {
  print 'An error occurred: ' . $e->getMessage();
}

如果还有任何问题,请随时提问!

于 2016-12-06T10:47:10.700 回答