API Gmail: 400 плохих запросов при попытке отправить электронное письмо (код PHP)
Я ожидал, что код ниже отправит электронное письмо, но я получаю только это:
Произошла ошибка: ошибка при вызове POST https://www.googleapis.com/gmail/v1/users/me/messages/send: (400) Плохо Запрос
Я получаю 200 OK
с помощью Google Developers Console здесь внизу. Любая помощь?
$client_id = '599901532082-js1r50n20q6n5mir9fo1g81qkj9kfn3j.apps.googleusercontent.com';
$service_account_name = '[email protected]account.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:
это объект запроса. Он также включает в себя данные ответа:
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
Ответы
Ответ 1
наконец-то, чтобы отправить Mails с вашим кодом:
Я думаю, вы немного поняли API GMail.
Чтобы использовать его, вы должны пройти аутентификацию в API. Для этого существует два способа:
- использовать OAuth - сервер перенаправляет пользователя на серверы Google, где они могут войти, предоставить разрешение вашему приложению и передать вам токен.
- Учетные записи служб. Это немного сложнее:
- Сначала вам нужно настроить приложение (сделано)
- Во-вторых, вам нужно будет настроить учетную запись службы. Таким образом ваше приложение аутентифицируется в Google. вы сделали это, и у имеющегося у вас сертификата есть закрытый ключ для аутентификации
- В-третьих, пользователь должен предоставить вашему приложению доступ к действию от их имени. Это тот момент, который вы еще не сделали.
Итак, вы пытаетесь отправить почту из учетной записи службы, но это не учетная запись GMail.
Консоль разработчика использует метод OAuth, поэтому нет проблем, чтобы попробовать это.
Также обратите внимание: с помощью обычных учетных записей GMail вы не можете использовать "Учетные записи службы". Вам нужно будет использовать OAuth.
Чтобы использовать учетные записи служб, вы должны быть клиентом Google Apps.
Я не буду конвертировать авторизацию OAuth здесь, потому что он совершенно другой, и есть много примеров.
Чтобы предоставить разрешения вашей учетной записи службы для отправки писем от имени ваших счетов GMail/Google Apps, выполните следующие действия:
этот документ. Для One or More API Scopes
вам нужно будет ввести
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
идентификатором пользователя (почтовым адресом) учетной записи, с которой следует отправлять почту.:
$results = $service->users_messages->send("[email protected]", $msg);
Затем вам нужно добавить
$cred->sub = '[email protected]';
ниже
$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
должен быть $msg
в try...catch
-Block.
Ниже вы найдете полный рабочий код для меня:
<?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();
}
Если у вас остались вопросы, не стесняйтесь спрашивать!
Ответ 2
Одна вещь, которая мне нужна для того, чтобы мой клиент учетной записи службы, который не был очевиден, добавлял это:
// you MUST do this to avoid 400 error
$user_to_impersonate = '[email protected]';
$client->setSubject($user_to_impersonate);
Ответ 3
Я думаю, вы забываете назначить $client_id
вашей переменной $client
.
$client = new Google_Client();
$client->setApplicationName('Gmail API test');
$client->setDeveloperKey('<YOUR_API_KEY>');
$client->setClientSecret('<YOUR_CLIENT_SECRET>');
$client->SetClientId('599901532082-js1r50n20q6n5mir9fo1g81qkj9kfn3j.apps.googleusercontent.com');
$client->setScopes(array('https://www.googleapis.com/auth/gmail.send'));
$client->setAccessToken('{"access_token":"<YOUR_ACCESS_TOKEN>",
"token_type":"Bearer","expires_in":3600,
"refresh_token":"<YOUR_REFRESH_TOKEN>","created":12344556}');
$service = new Google_Service_Gmail($client);
$raw = "RnJvbTogSm9obiBEb2UgPHRpcmVuZ2FyZmlvQGdtYWlsLmVzPiANClRvOiBNYXJ5IFNtaXRoIDx0aXJlbmdhcmZpb0BnbWFpbC5jb20-IA0KU3ViamVjdDogU2F5aW5nIEhlbGxvIA0KRGF0ZTogRnJpLCAyMSBOb3YgMTk5NyAwOTo1NTowNiAtMDYwMCANCk1lc3NhZ2UtSUQ6IDwxMjM0QGxvY2FsLm1hY2hpbmUuZXhhbXBsZT4NCg0KVGhpcyBpcyBhIG1lc3NhZ2UganVzdCB0byBzYXkgaGVsbG8uIFNvLCAiSGVsbG8iLg==";
$msg = new Google_Service_Gmail_Message();
$msg->setRaw($raw);
$results = $service->users_messages->send("me", $msg);
print 'Message with ID: ' . $message->getId() . ' sent.';
Ответ 4
Это полный рабочий пример, просто не забудьте изменить всю необходимую информацию и использовать PHPMailer для форматирования действительной почты.
<?php
// this the link to gmail-api-client or whatever you have...
require 'vendor/autoload.php';
// download PHPMailer
// https://github.com/PHPMailer/PHPMailer and uncomment the line below.
// require 'PHPMailer/PHPMailerAutoload.php';
define('FROM', '[email protected]'); //email of sender
define('TO', '[email protected]');//email of receiver
$client_email = '[email protected]';
$private_key = file_get_contents('tmp/XXXXXXX.p12');
$scopes = array(
'https://www.googleapis.com/auth/gmail.send',
'https://www.googleapis.com/auth/gmail.compose'
);
$credentials = new \Google_Auth_AssertionCredentials($client_email, $scopes, $private_key);
$credentials->sub = FROM;
$client = new Google_Client();
$client->setAssertionCredentials($credentials);
if ($client->getAuth()->isAccessTokenExpired()) {
$client->getAuth()->refreshTokenWithAssertion();
}
function create_message() {
$mail = new PHPMailer();
$mail->setFrom(FROM, 'John Doe 1');
$mail->addAddress(TO, 'John Doe 2');
$mail->Subject = 'Saying Hello';
$mail->Body = 'This is a message just to say hello. So, "Hello"';
$mail->preSend();
$mime = $mail->getSentMIMEMessage();
return urlsafe_b64encode($mime);
}
function sendMessage($service, $userId, $message) {
try {
$message = $service->users_messages->send($userId, $message);
print 'Message with ID: ' . $message->getId() . ' sent.';
return $message;
}
catch(Exception $e) {
print 'An error occurred: ' . $e->getMessage();
}
}
function urlsafe_b64encode($string) {
$data = base64_encode($string);
$data = str_replace(array('+','/','=') , array('-','_','') , $data);
return $data;
}
$service = new \Google_Service_Gmail($client);
$msg = new \Google_Service_Gmail_Message();
$msg->setRaw(create_message());
sendMessage($service, 'me', $msg);
?>
Ответ 5
использовать URL Endocde в строке и URL.
Эта ошибка - это пробел в URL-адресе.
Ответ 6
Вы можете проверить Устранить все ошибки с кодом по этому URL.
https://developers.google.com/drive/api/v3/handle-errors