I expected the code below to send an email, but I'm only getting this:
An error occurred: Error calling POST https://www.googleapis.com/gmail/v1/users/me/messages/send: (400) Bad Request
I get a 200 OK
using the Google Developers Console here at the bottom. Any help?
$client_id = '599901532082-js1r50n20q6n5mir9fo1g81qkj9kfn3j.apps.googleusercontent.com';
$service_account_name = '599901532082-js1r50n20q6n5mir9fo1g81qkj9kfn3j@developer.gserviceaccount.com';
$key_file_location = '/tmp/APIProject-cb6558ba6435.p12';
$client = new \Google_Client();
$client->setApplicationName("Client_Library_Examples");
$service = new \Google_Service_Gmail($client);
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'),
$key
);
$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 = "RnJvbTogSm9obiBEb2UgPHRpcmVuZ2FyZmlvQGdtYWlsLmVzPiANClRvOiBNYXJ5IFNtaXRoIDx0aXJlbmdhcmZpb0BnbWFpbC5jb20-IA0KU3ViamVjdDogU2F5aW5nIEhlbGxvIA0KRGF0ZTogRnJpLCAyMSBOb3YgMTk5NyAwOTo1NTowNiAtMDYwMCANCk1lc3NhZ2UtSUQ6IDwxMjM0QGxvY2FsLm1hY2hpbmUuZXhhbXBsZT4NCg0KVGhpcyBpcyBhIG1lc3NhZ2UganVzdCB0byBzYXkgaGVsbG8uIFNvLCAiSGVsbG8iLg==";
$service = new \Google_Service_Gmail($client);
$msg = new \Google_Service_Gmail_Message();
$msg->setRaw($mime);
try {
$results = $service->users_messages->send("me", $msg);
print 'Message with ID: ' . $message->getId() . ' sent.';
return $message;
} catch (\Exception $e) {
print 'An error occurred: ' . $e->getMessage();
}
EDIT:
this is the request object. It includes the response data also:
object(Google_Http_Request)[508]
private 'batchHeaders' =>
array (size=3)
'Content-Type' => string 'application/http' (length=16)
'Content-Transfer-Encoding' => string 'binary' (length=6)
'MIME-Version' => string '1.0' (length=3)
protected 'queryParams' =>
array (size=0)
empty
protected 'requestMethod' => string 'POST' (length=4)
protected 'requestHeaders' =>
array (size=3)
'content-type' => string 'application/json; charset=UTF-8' (length=31)
'authorization' => string 'Bearer ya29.8gEUMiBLfxS8OLdSmpiQ-EcumeATo2qFAfPtPqwTw9fQ2zVrfZaA1X5OLoBmQccrXr8V8g' (length=82)
'accept-encoding' => string 'gzip' (length=4)
protected 'baseComponent' => string 'https://www.googleapis.com' (length=26)
protected 'path' => string '/gmail/v1/users/me/messages/send' (length=32)
protected 'postBody' => string '{"raw":"RnJvbTogSm9obiBEb2UgPHRpcmVuZ2FyZmlvQGdtYWlsLmVzPg0KVG86IE1hcnkgU21pdGggPHRpcmVuZ2FyZmlvQGdtYWlsLmNvbT4NClN1YmplY3Q6IFNheWluZyBIZWxsbw0KDQpUaGlzIGlzIGEgbWVzc2FnZSBqdXN0IHRvIHNheSBoZWxsby4gU28sICdIZWxsbycu"}' (length=214)
protected 'userAgent' => string 'Client_Library_Examples google-api-php-client/1.0.6-beta (gzip)' (length=63)
protected 'canGzip' => boolean true
protected 'responseHttpCode' => null
protected 'responseHeaders' => null
protected 'responseBody' => null
protected 'expectedClass' => string 'Google_Service_Gmail_Message' (length=28)
public 'accessKey' => null
object(Google_Http_Request)[508]
private 'batchHeaders' =>
array (size=3)
'Content-Type' => string 'application/http' (length=16)
'Content-Transfer-Encoding' => string 'binary' (length=6)
'MIME-Version' => string '1.0' (length=3)
protected 'queryParams' =>
array (size=0)
empty
protected 'requestMethod' => string 'POST' (length=4)
protected 'requestHeaders' =>
array (size=4)
'content-type' => string 'application/json; charset=UTF-8' (length=31)
'authorization' => string 'Bearer ya29.8gEUM***fxS8OLdSmpiQ-EcumeATo2qFAfPtPqwTw9fQ2zVrfZaA1X5OLoBmQccrXr8V8g' (length=82)
'accept-encoding' => string 'gzip' (length=4)
'content-length' => int 214
protected 'baseComponent' => string 'https://www.googleapis.com' (length=26)
protected 'path' => string '/gmail/v1/users/me/messages/send' (length=32)
protected 'postBody' => string '{"raw":"RnJvbTogSm9obiBEb2UgPHRpcmVuZ2FyZmlvQGdtYWlsLmVzPg0KVG86IE1hcnkgU21pdGggPHRpcmVuZ2FyZmlvQGdtYWlsLmNvbT4NClN1YmplY3Q6IFNheWluZyBIZWxsbw0KDQpUaGlzIGlzIGEgbWVzc2FnZSBqdXN0IHRvIHNheSBoZWxsby4gU28sICdIZWxsbycu"}' (length=214)
protected 'userAgent' => string 'Client_Library_Examples google-api-php-client/1.0.6-beta (gzip)' (length=63)
protected 'canGzip' => boolean true
protected 'responseHttpCode' => int 400
protected 'responseHeaders' =>
array (size=13)
'vary' => string 'Origin
X-Origin' (length=15)
'content-type' => string 'application/json; charset=UTF-8' (length=31)
'content-encoding' => string 'gzip' (length=4)
'date' => string 'Fri, 18 Sep 2015 08:34:25 GMT' (length=29)
'expires' => string 'Fri, 18 Sep 2015 08:34:25 GMT' (length=29)
'cache-control' => string 'private, max-age=0' (length=18)
'x-content-type-options' => string 'nosniff' (length=7)
'x-frame-options' => string 'SAMEORIGIN' (length=10)
'x-xss-protection' => string '1; mode=block' (length=13)
'server' => string 'GSE' (length=3)
'alternate-protocol' => string '443:quic,p=1' (length=12)
'alt-svc' => string 'quic=":443"; p="1"; ma=604800' (length=29)
'transfer-encoding' => string 'chunked' (length=7)
protected 'responseBody' => string '{
"error": {
"errors": [
{
"domain": "global",
"reason": "failedPrecondition",
"message": "Bad Request"
}
],
"code": 400,
"message": "Bad Request"
}
}
' (length=179)
protected 'expectedClass' => string 'Google_Service_Gmail_Message' (length=28)
public 'accessKey' => null
Resolve a 403 error: User rate limit exceeded To fix this error, try to optimize your application code to make fewer requests or retry requests. For information on retrying requests, refer to Retry failed requests to resolve errors. For additional information on Gmail limits, refer to Usage limits.
finally got to send Mails with your code:
I think you have misunderstood the GMail API a little bit.
To use it, you must authenticate to the API. To do this, there are two ways:
So what you're currently trying is to send mails from the service account, but this is not an GMail Account.
The Developer Console uses the OAuth method, so there's no problem to try this.
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.
I won't conver OAuth authorization here, because it's completely different, and there are many examples out there.
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);
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("[email protected]", $msg);
Then, you'll need to add
$cred->sub = '[email protected]';
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
);
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!
One thing that I needed to get my service account client working that wasn't obvious was adding this:
// you MUST do this to avoid 400 error
$user_to_impersonate = '[email protected]';
$client->setSubject($user_to_impersonate);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With