且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Gmail API:尝试发送电子邮件时出现 400 个错误请求(PHP 代码)

更新时间:2021-09-25 07:22:42

终于可以用你的代码发送邮件了:

finally got to send Mails with your code:

我认为您对 GMail API 有点误解.

I think you have misunderstood the GMail API a little bit.

要使用它,您必须对 API 进行身份验证.为此,有两种方法:

To use it, you must authenticate to the API. To do this, there are two ways:

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

    所以您当前尝试的是从服务帐户发送邮件,但这不是 GMail 帐户.

    So what you're currently trying is to send mails from the service account, but this is not an GMail Account.

    开发者控制台使用 OAuth 方法,所以尝试这个没有问题.

    The Developer Console uses the OAuth method, so there's no problem to try this.

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

    Please also note: With regular GMail Accounts, you can not use 'Service Accounts'. You'll have to use OAuth. To use Service Accounts, you need to be a Google Apps customer.

    我不会在这里讨论 OAuth 授权,因为它完全不同,并且有很多示例.

    I won't conver OAuth authorization here, because it's completely different, and there are many examples out there.

    要授予您的服务帐户权限以代表您的 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.

    To grant your Service Account Permissions to send mails on behalf of your GMails/Google Apps accounts, please follow this document. For One or More API Scopes, you'll have to enter 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.

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

    After you've setup this, it's possible to send mails, just modify the code as follows:

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

    不起作用,因为我"指的是无法发送邮件的服务帐户(见上文).将 me 替换为应该发送邮件的帐户的用户 ID(邮件地址).:

    won't work, because 'me' referrs to the service account, which can't send mail (see above). Replace me with the user id (mail-address) of the account from which the mails should be send.:

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

    然后,您需要添加

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

    下面

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

    还请注意,$message 应该是 $msgtry...catch-Block 中.

    Please also note that $message should be $msg in the try...catch-Block.

    在下面,您将找到适合我的完整的工作代码:

    Below, you'll find the the complete, working code for me:

    <?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");
    
    
    //hmmm, really don't know whether these lines are necessary
    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; //<-- Important!
    $client->setAssertionCredentials($cred);
    
    if ($client->getAuth()->isAccessTokenExpired()) {
      $client->getAuth()->refreshTokenWithAssertion($cred);
    }
    
    //check if you want the validity of this string at: http://www.komeil.com/toolbox/base64decoder
    //it is web safe base64 encoded email
    $mime = "*censored*, same content as you posted, but another recipient ;-)";
    
    
    $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();
    }
    

    如果还有什么问题,欢迎随时提问!

    If there are any questions left, feel free to ask!