无法使用 Gmail PHP API 获取电子邮件正文
Posted
技术标签:
【中文标题】无法使用 Gmail PHP API 获取电子邮件正文【英文标题】:Cannot get the body of email with Gmail PHP API 【发布时间】:2015-12-15 19:56:05 【问题描述】:我在使用 Gmail php API 时遇到问题。
我想检索电子邮件的正文内容,但我只能检索带有附件的电子邮件!我的问题是为什么?
到目前为止,这是我的代码:
// Authentication things above...
$client = getClient();
$gmail = new Google_Service_Gmail($client);
$list = $gmail->users_messages->listUsersMessages('me', ['maxResults' => 1000]);
while ($list->getMessages() != null)
foreach ($list->getMessages() as $mlist)
$message_id = $mlist->id;
$optParamsGet2['format'] = 'full';
$single_message = $gmail->users_messages->get('me', $message_id, $optParamsGet2);
$threadId = $single_message->getThreadId();
$payload = $single_message->getPayload();
$headers = $payload->getHeaders();
$parts = $payload->getParts();
//print_r($parts); PRINTS SOMETHING ONLY IF I HAVE ATTACHMENTS...
$body = $parts[0]['body'];
$rawData = $body->data;
$sanitizedData = strtr($rawData,'-_', '+/');
$decodedMessage = base64_decode($sanitizedData); //should display my body content
if ($list->getNextPageToken() != null)
$pageToken = $list->getNextPageToken();
$list = $gmail->users_messages->listUsersMessages('me', ['pageToken' => $pageToken, 'maxResults' => 1000]);
else
break;
我知道检索内容的第二个选项是使用位于 Headers 部分中的 sn-p,但它只检索前 50 个左右的字符,这不是很有用。
【问题讨论】:
谁能帮帮我。我使用这个网址 $endpoint = "googleapis.com/gmail/v1/users/me/messages/$id?format=full";但它只在一封电子邮件中获得 194 个字符,而不是完整的电子邮件。我该怎么办? 【参考方案1】:让我们做一个小实验。我给自己发了两条消息。一个有附件,一个没有。
请求:
GET https://www.googleapis.com/gmail/v1/users/me/messages?maxResults=2
回应:
"messages": [
"id": "14fe21fd6b3fb46f",
"threadId": "14fe21fd6b3fb46f"
,
"id": "14fe21f9341ed73c",
"threadId": "14fe21f9341ed73c"
],
"nextPageToken": "08943597140129624594",
"resultSizeEstimate": 3
我只要求有效载荷,因为这是所有相关部分的所在:
fields = payload
GET https://www.googleapis.com/gmail/v1/users/me/messages/14fe21fd6b3fb46f?fields=payload
GET https://www.googleapis.com/gmail/v1/users/me/messages/14fe21f9341ed73c?fields=payload
没有附件的邮件:
"payload":
"parts": [
"partId": "0",
"mimeType": "text/plain",
"filename": "",
"headers": [
"name": "Content-Type",
"value": "text/plain; charset=UTF-8"
],
"body":
"size": 22,
"data": "aGVjaz8gTm8gYXR0YWNobWVudD8NCg=="
,
"partId": "1",
"mimeType": "text/html",
"filename": "",
"headers": [
"name": "Content-Type",
"value": "text/html; charset=UTF-8"
],
"body":
"size": 43,
"data": "PGRpdiBkaXI9Imx0ciI-aGVjaz8gTm8gYXR0YWNobWVudD88L2Rpdj4NCg=="
]
带附件的邮件:
"payload":
"parts": [
"mimeType": "multipart/alternative",
"filename": "",
"headers": [
"name": "Content-Type",
"value": "multipart/alternative; boundary=001a1142e23c551e8e05200b4be0"
],
"body":
"size": 0
,
"parts": [
"partId": "0.0",
"mimeType": "text/plain",
"filename": "",
"headers": [
"name": "Content-Type",
"value": "text/plain; charset=UTF-8"
],
"body":
"size": 9,
"data": "V293IG1hbg0K"
,
"partId": "0.1",
"mimeType": "text/html",
"filename": "",
"headers": [
"name": "Content-Type",
"value": "text/html; charset=UTF-8"
],
"body":
"size": 30,
"data": "PGRpdiBkaXI9Imx0ciI-V293IG1hbjwvZGl2Pg0K"
]
,
"partId": "1",
"mimeType": "image/jpeg",
"filename": "feelthebern.jpg",
"headers": [
"name": "Content-Type",
"value": "image/jpeg; name=\"feelthebern.jpg\""
,
"name": "Content-Disposition",
"value": "attachment; filename=\"feelthebern.jpg\""
,
"name": "Content-Transfer-Encoding",
"value": "base64"
,
"name": "X-Attachment-Id",
"value": "f_ieq3ev0i0"
],
"body":
"attachmentId": "ANGjdJ_2xG3WOiLh6MbUdYy4vo2VhV2kOso5AyuJW3333rbmk8BIE1GJHIOXkNIVGiphP3fGe7iuIl_MGzXBGNGvNslwlz8hOkvJZg2DaasVZsdVFT_5JGvJOLefgaSL4hqKJgtzOZG9K1XSMrRQAtz2V0NX7puPdXDU4gvalSuMRGwBhr_oDSfx2xljHEbGG6I4VLeLZfrzGGKW7BF-GO_FUxzJR8SizRYqIhgZNA6PfRGyOhf1s7bAPNW3M9KqWRgaK07WTOYl7DzW4hpNBPA4jrl7tgsssExHpfviFL7yL52lxsmbsiLe81Z5UoM",
"size": 100446
]
这些响应对应于您代码中的$parts
。如您所见,如果幸运的话,$parts[0]['body']->data
会给您想要的,但大多数时候不会。
通常有两种方法可以解决这个问题。你可以实现以下算法(你比我更擅长 PHP,但这是它的大致轮廓):
-
遍历
payload.parts
并检查它是否包含具有您要查找的主体的part
(text/plain
或text/html
)。如果有,您的搜索就完成了。如果您正在解析像上面这样没有附件的邮件,这就足够了。
再次执行第 1 步,但这次使用您刚刚检查的 parts
中的 parts
递归。你最终会找到你的part
。如果您正在解析带有附件的上述邮件,最终会找到您的body
。
算法可能如下所示(javascript 中的示例):
var response =
"payload":
"parts": [
"mimeType": "multipart/alternative",
"filename": "",
"headers": [
"name": "Content-Type",
"value": "multipart/alternative; boundary=001a1142e23c551e8e05200b4be0"
],
"body":
"size": 0
,
"parts": [
"partId": "0.0",
"mimeType": "text/plain",
"filename": "",
"headers": [
"name": "Content-Type",
"value": "text/plain; charset=UTF-8"
],
"body":
"size": 9,
"data": "V293IG1hbg0K"
,
"partId": "0.1",
"mimeType": "text/html",
"filename": "",
"headers": [
"name": "Content-Type",
"value": "text/html; charset=UTF-8"
],
"body":
"size": 30,
"data": "PGRpdiBkaXI9Imx0ciI-V293IG1hbjwvZGl2Pg0K"
]
,
"partId": "1",
"mimeType": "image/jpeg",
"filename": "feelthebern.jpg",
"headers": [
"name": "Content-Type",
"value": "image/jpeg; name=\"feelthebern.jpg\""
,
"name": "Content-Disposition",
"value": "attachment; filename=\"feelthebern.jpg\""
,
"name": "Content-Transfer-Encoding",
"value": "base64"
,
"name": "X-Attachment-Id",
"value": "f_ieq3ev0i0"
],
"body":
"attachmentId": "ANGjdJ_2xG3WOiLh6MbUdYy4vo2VhV2kOso5AyuJW3333rbmk8BIE1GJHIOXkNIVGiphP3fGe7iuIl_MGzXBGNGvNslwlz8hOkvJZg2DaasVZsdVFT_5JGvJOLefgaSL4hqKJgtzOZG9K1XSMrRQAtz2V0NX7puPdXDU4gvalSuMRGwBhr_oDSfx2xljHEbGG6I4VLeLZfrzGGKW7BF-GO_FUxzJR8SizRYqIhgZNA6PfRGyOhf1s7bAPNW3M9KqWRgaK07WTOYl7DzW4hpNBPA4jrl7tgsssExHpfviFL7yL52lxsmbsiLe81Z5UoM",
"size": 100446
]
;
// In e.g. a plain text message, the payload is the only part.
var parts = [response.payload];
while (parts.length)
var part = parts.shift();
if (part.parts)
parts = parts.concat(part.parts);
if(part.mimeType === 'text/html')
var decodedPart = decodeURIComponent(escape(atob(part.body.data.replace(/\-/g, '+').replace(/\_/g, '/'))));
console.log(decodedPart);
更简单的选择是只获取邮件的原始数据,然后让已经编写好的库为您完成工作:
请求:
format = raw
fields = raw
GET https://www.googleapis.com/gmail/v1/users/me/messages/14fe21fd6b3fb46f?format=raw&fields=raw
回应:
"raw": "TUlNRS1WZXJzaW9uOiAxLjANClJlY2VpdmVkOiBieSAxMC4yOC45OS4xOTYgd2l0aCBIVFRQOyBGcmksIDE4IFNlcCAyMDE1IDEzOjIzOjAxIC0wNzAwIChQRFQpDQpEYXRlOiBGcmksIDE4IFNlcCAyMDE1IDIyOjIzOjAxICswMjAwDQpEZWxpdmVyZWQtVG86IGVtdGhvbGluQGdtYWlsLmNvbQ0KTWVzc2FnZS1JRDogPENBRHNaTFJ5eGk2UGt0MHZnUS1iZHd1N2FNLWNHRmZKcEwrRHYyb3ZKOGp4SGN4VWhfQUBtYWlsLmdtYWlsLmNvbT4NClN1YmplY3Q6IFdoYXQgZGENCkZyb206IEVtaWwgVGhvbGluIDxlbXRob2xpbkBnbWFpbC5jb20-DQpUbzogRW1pbCBUaG9saW4gPGVtdGhvbGluQGdtYWlsLmNvbT4NCkNvbnRlbnQtVHlwZTogbXVsdGlwYXJ0L2FsdGVybmF0aXZlOyBib3VuZGFyeT0wMDFhMTE0NjhmMTY1YzUwNDUwNTIwMGI0YzYxDQoNCi0tMDAxYTExNDY4ZjE2NWM1MDQ1MDUyMDBiNGM2MQ0KQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFyc2V0PVVURi04DQoNCmhlY2s_IE5vIGF0dGFjaG1lbnQ_DQoNCi0tMDAxYTExNDY4ZjE2NWM1MDQ1MDUyMDBiNGM2MQ0KQ29udGVudC1UeXBlOiB0ZXh0L2h0bWw7IGNoYXJzZXQ9VVRGLTgNCg0KPGRpdiBkaXI9Imx0ciI-aGVjaz8gTm8gYXR0YWNobWVudD88L2Rpdj4NCg0KLS0wMDFhMTE0NjhmMTY1YzUwNDUwNTIwMGI0YzYxLS0="
第二种方法的最大缺点是,如果您获取原始消息,您将立即下载所有附件数据,这对于您的用例来说可能是非常多的数据。
我不擅长 PHP,但如果您想采用第二种解决方案,this 看起来很有希望!祝你好运!
【讨论】:
太棒了!非常感谢创立!我将在下周一使用第一种方法,并为未来的用户粘贴完整的代码。 @F3L1X79 没问题 :) 很高兴我能帮上忙。期待看到代码! 我正在处理这个问题几天.. 你刚刚拯救了我的一天。非常感谢! 仅供参考,检索内容的最终代码写在我自己的答案上(经过测试和批准)。 @Tholle 我明白了,谢谢!没有意识到我必须像我认为的那样将它实际放入一个数组中。现在就像一个魅力。【参考方案2】:更新:您可能想查看我在此答案下方的第二个答案以获得更完整的代码。
终于,我今天工作了,所以这是寻找尸体的完整代码答案 - 感谢 @Tholle:
// Authentication things above
/*
* Decode the body.
* @param : encoded body - or null
* @return : the body if found, else FALSE;
*/
function decodeBody($body)
$rawData = $body;
$sanitizedData = strtr($rawData,'-_', '+/');
$decodedMessage = base64_decode($sanitizedData);
if(!$decodedMessage)
$decodedMessage = FALSE;
return $decodedMessage;
$client = getClient();
$gmail = new Google_Service_Gmail($client);
$list = $gmail->users_messages->listUsersMessages('me', ['maxResults' => 1000]);
try
while ($list->getMessages() != null)
foreach ($list->getMessages() as $mlist)
$message_id = $mlist->id;
$optParamsGet2['format'] = 'full';
$single_message = $gmail->users_messages->get('me', $message_id, $optParamsGet2);
$payload = $single_message->getPayload();
// With no attachment, the payload might be directly in the body, encoded.
$body = $payload->getBody();
$FOUND_BODY = decodeBody($body['data']);
// If we didn't find a body, let's look for the parts
if(!$FOUND_BODY)
$parts = $payload->getParts();
foreach ($parts as $part)
if($part['body'])
$FOUND_BODY = decodeBody($part['body']->data);
break;
// Last try: if we didn't find the body in the first parts,
// let's loop into the parts of the parts (as @Tholle suggested).
if($part['parts'] && !$FOUND_BODY)
foreach ($part['parts'] as $p)
// replace 'text/html' by 'text/plain' if you prefer
if($p['mimeType'] === 'text/html' && $p['body'])
$FOUND_BODY = decodeBody($p['body']->data);
break;
if($FOUND_BODY)
break;
// Finally, print the message ID and the body
print_r($message_id . " : " . $FOUND_BODY);
if ($list->getNextPageToken() != null)
$pageToken = $list->getNextPageToken();
$list = $gmail->users_messages->listUsersMessages('me', ['pageToken' => $pageToken, 'maxResults' => 1000]);
else
break;
catch (Exception $e)
echo $e->getMessage();
如您所见,我的问题是,有时无法在 payload->parts 中找到 body,而是直接在 payload->body 中找到! (另外我为多个部分添加了循环)。
希望这对其他人有所帮助。
【讨论】:
这很有趣,你知道body在payload->body而不是payload->parts中的条件是什么吗? @guival,不确定,但如果我没记错,这取决于您的邮件是否有附件。好久没用这个脚本了,抱歉。 @F3L1X79 好的,谢谢,到目前为止我发现如果有效载荷mimeType
是multipart/alternative
,那么主体将在有效载荷部分中,如果mimeType
是@ 987654327@ 或 text/html
正文将在有效负载正文中。我还没有测试附件,但我会留意它们
谁能帮帮我。我使用这个网址 $endpoint = "googleapis.com/gmail/v1/users/me/messages/$id?format=full";但它只在一封电子邮件中获得 194 个字符,而不是完整的电子邮件。我该怎么办?
代码应该是递归的,请看***.com/a/54139473/439944【参考方案3】:
对于那些感兴趣的人,我大大改进了我的最后一个答案,使其与 text/html 一起使用(必要时回退到 text/plain)并将图像转换为 base64 附件,当打印为完整的 HTML 时将自动加载!
代码一点也不完美,而且太长,无法详细解释,但它对我有用。
随意接受并调整它(如有必要,可能会更正/改进它)。
// Authentication things above
/*
* Decode the body.
* @param : encoded body - or null
* @return : the body if found, else FALSE;
*/
function decodeBody($body)
$rawData = $body;
$sanitizedData = strtr($rawData,'-_', '+/');
$decodedMessage = base64_decode($sanitizedData);
if(!$decodedMessage)
$decodedMessage = FALSE;
return $decodedMessage;
$client = getClient();
$gmail = new Google_Service_Gmail($client);
$list = $gmail->users_messages->listUsersMessages('me', ['maxResults' => 1000]);
try
while ($list->getMessages() != null)
foreach ($list->getMessages() as $mlist)
$message_id = $mlist->id;
$optParamsGet2['format'] = 'full';
$single_message = $gmail->users_messages->get('me', $message_id, $optParamsGet2);
$payload = $single_message->getPayload();
$parts = $payload->getParts();
// With no attachment, the payload might be directly in the body, encoded.
$body = $payload->getBody();
$FOUND_BODY = FALSE;
// If we didn't find a body, let's look for the parts
if(!$FOUND_BODY)
foreach ($parts as $part)
if($part['parts'] && !$FOUND_BODY)
foreach ($part['parts'] as $p)
if($p['parts'] && count($p['parts']) > 0)
foreach ($p['parts'] as $y)
if(($y['mimeType'] === 'text/html') && $y['body'])
$FOUND_BODY = decodeBody($y['body']->data);
break;
else if(($p['mimeType'] === 'text/html') && $p['body'])
$FOUND_BODY = decodeBody($p['body']->data);
break;
if($FOUND_BODY)
break;
// let's save all the images linked to the mail's body:
if($FOUND_BODY && count($parts) > 1)
$images_linked = array();
foreach ($parts as $part)
if($part['filename'])
array_push($images_linked, $part);
else
if($part['parts'])
foreach ($part['parts'] as $p)
if($p['parts'] && count($p['parts']) > 0)
foreach ($p['parts'] as $y)
if(($y['mimeType'] === 'text/html') && $y['body'])
array_push($images_linked, $y);
else if(($p['mimeType'] !== 'text/html') && $p['body'])
array_push($images_linked, $p);
// special case for the wdcid...
preg_match_all('/wdcid(.*)"/Uims', $FOUND_BODY, $wdmatches);
if(count($wdmatches))
$z = 0;
foreach($wdmatches[0] as $match)
$z++;
if($z > 9)
$FOUND_BODY = str_replace($match, 'image0' . $z . '@', $FOUND_BODY);
else
$FOUND_BODY = str_replace($match, 'image00' . $z . '@', $FOUND_BODY);
preg_match_all('/src="cid:(.*)"/Uims', $FOUND_BODY, $matches);
if(count($matches))
$search = array();
$replace = array();
// let's trasnform the CIDs as base64 attachements
foreach($matches[1] as $match)
foreach($images_linked as $img_linked)
foreach($img_linked['headers'] as $img_lnk)
if( $img_lnk['name'] === 'Content-ID' || $img_lnk['name'] === 'Content-Id' || $img_lnk['name'] === 'X-Attachment-Id')
if ($match === str_replace('>', '', str_replace('<', '', $img_lnk->value))
|| explode("@", $match)[0] === explode(".", $img_linked->filename)[0]
|| explode("@", $match)[0] === $img_linked->filename)
$search = "src=\"cid:$match\"";
$mimetype = $img_linked->mimeType;
$attachment = $gmail->users_messages_attachments->get('me', $mlist->id, $img_linked['body']->attachmentId);
$data64 = strtr($attachment->getData(), array('-' => '+', '_' => '/'));
$replace = "src=\"data:" . $mimetype . ";base64," . $data64 . "\"";
$FOUND_BODY = str_replace($search, $replace, $FOUND_BODY);
// If we didn't find the body in the last parts,
// let's loop for the first parts (text-html only)
if(!$FOUND_BODY)
foreach ($parts as $part)
if($part['body'] && $part['mimeType'] === 'text/html')
$FOUND_BODY = decodeBody($part['body']->data);
break;
// With no attachment, the payload might be directly in the body, encoded.
if(!$FOUND_BODY)
$FOUND_BODY = decodeBody($body['data']);
// Last try: if we didn't find the body in the last parts,
// let's loop for the first parts (text-plain only)
if(!$FOUND_BODY)
foreach ($parts as $part)
if($part['body'])
$FOUND_BODY = decodeBody($part['body']->data);
break;
if(!$FOUND_BODY)
$FOUND_BODY = '(No message)';
// Finally, print the message ID and the body
print_r($message_id . ": " . $FOUND_BODY);
if ($list->getNextPageToken() != null)
$pageToken = $list->getNextPageToken();
$list = $gmail->users_messages->listUsersMessages('me', ['pageToken' => $pageToken, 'maxResults' => 1000]);
else
break;
catch (Exception $e)
echo $e->getMessage();
干杯。
【讨论】:
适用于所有类型的附件,但不适用于 jpg 或 jpeg。 Bmp虽然下载得很好。你能帮忙吗?? 实际上,我可以毫无问题地显示位于电子邮件正文中的所有类型的图像。对于位于附件中的那些,您可能希望在 $payload->getParts() 上循环。也许这是你的问题? 身体工作得很好。所以我需要应用 $payload->getParts() 迭代?请问您能提供额外的帮助吗? 我欠你一杯啤酒!!优秀的代码!绝对完美! 这是一个很好的解决方案!完美地在不同的情况下找到身体!谢谢!【参考方案4】:我编写此代码是为了改进 @F3L1X79 的答案,因为它可以正确过滤 html 响应。
<?php
ini_set("display_errors", 1);
ini_set("track_errors", 1);
ini_set("html_errors", 1);
error_reporting(E_ALL);
require_once __DIR__ . '/vendor/autoload.php';
session_start();
function decodeBody($body)
$rawData = $body;
$sanitizedData = strtr($rawData,'-_', '+/');
$decodedMessage = base64_decode($sanitizedData);
if(!$decodedMessage)
$decodedMessage = FALSE;
return $decodedMessage;
function fetchMails($gmail, $q)
try
$list = $gmail->users_messages->listUsersMessages('me', array('q' => $q));
while ($list->getMessages() != null)
foreach ($list->getMessages() as $mlist)
$message_id = $mlist->id;
$optParamsGet2['format'] = 'full';
$single_message = $gmail->users_messages->get('me', $message_id, $optParamsGet2);
$payload = $single_message->getPayload();
// With no attachment, the payload might be directly in the body, encoded.
$body = $payload->getBody();
$FOUND_BODY = decodeBody($body['data']);
// If we didn't find a body, let's look for the parts
if(!$FOUND_BODY)
$parts = $payload->getParts();
foreach ($parts as $part)
if($part['body'] && $part['mimeType'] == 'text/html')
$FOUND_BODY = decodeBody($part['body']->data);
break;
if(!$FOUND_BODY)
foreach ($parts as $part)
// Last try: if we didn't find the body in the first parts,
// let's loop into the parts of the parts (as @Tholle suggested).
if($part['parts'] && !$FOUND_BODY)
foreach ($part['parts'] as $p)
// replace 'text/html' by 'text/plain' if you prefer
if($p['mimeType'] === 'text/html' && $p['body'])
$FOUND_BODY = decodeBody($p['body']->data);
break;
if($FOUND_BODY)
break;
// Finally, print the message ID and the body
print_r($message_id . " <br> <br> <br> *-*-*- " . $FOUND_BODY);
if ($list->getNextPageToken() != null)
$pageToken = $list->getNextPageToken();
$list = $gmail->users_messages->listUsersMessages('me', array('pageToken' => $pageToken));
else
break;
catch (Exception $e)
echo $e->getMessage();
$client = new Google_Client();
$client->setAuthConfig('client_secrets.json');
$client->addScope(Google_Service_Gmail::GMAIL_READONLY);
if (isset($_SESSION['access_token']) && $_SESSION['access_token'])
$client->setAccessToken($_SESSION['access_token']);
$gmail = new Google_Service_Gmail($client);
$q = ' after:2016/11/7';
fetchMails($gmail, $q);
else
$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/gmail-api/oauth2callback.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
【讨论】:
这是解决问题最全面的方法。 谁能帮帮我。我使用这个网址 $endpoint = "googleapis.com/gmail/v1/users/me/messages/$id?format=full";但它只在一封电子邮件中获得 194 个字符,而不是完整的电子邮件。我该怎么办? format=full 是默认的,不需要发送。尝试不使用,您会得到不同的结果吗?另外,最好把它放在一个单独的问题中! :-)【参考方案5】:作为进一步改进,代码应该是递归的,您还需要以“完整”格式加载消息以提取正文。您可以将以下三个函数放入您自己的类中。
private function decodeBody($body)
$rawData = $body;
$sanitizedData = strtr($rawData,'-_', '+/');
$decodedMessage = base64_decode($sanitizedData);
if(!$decodedMessage)
return false;
return $decodedMessage;
private function decodeParts($parts)
foreach ($parts as $part)
if ($part->getMimeType() === 'text/html' && $part->getBody())
if ($result = $this->decodeBody($part->getBody()->getData()))
return $result;
foreach ($parts as $part)
if ($result = $this->decodeParts($part->getParts()))
return $result;
/**
* @param Google_Service_Gmail_Message $message
* @return bool|null|string
*/
public function getMessageBody($message)
$payload = $message->getPayload();
if ($result = $this->decodeBody($payload->getBody()->getData()))
return $result;
return $this->decodeParts($payload->getParts());
【讨论】:
你能举个例子吗? @dearsina 对不起,你是对的。答案是缺少一项功能。我刚刚更新了它。您可以将它们复制到您自己的班级,然后致电getMessageBody()
。【参考方案6】:
简单、可靠的解决方案
我对其他答案不满意,因为它们都有缺陷(剧透中的详细说明),而且有些答案很长,并且混合了提问者(和我)没有寻找的功能。
警告您其他答案中的潜在问题: 没有纯文本回退 或未能处理 falsy 消息正文 - 字符串“0”(不太可能发生,但不太可能发生) 或者在有效载荷树结构中缺乏足够深入的搜索
所以我想我会省去其他人的麻烦并分享我的代码(在我的整个收件箱中测试过)。
// input: the message object (not the payload!)
// output: html or plain text
function msg_body($msg)
$body = msg_body_recursive($msg->payload);
return array_key_exists('html', $body) ? $body['html'] : $body['plain'];
function msg_body_recursive($part)
if($part->mimeType == 'text/html')
return ['html' => decodeBody($part->body->data)];
else if($part->mimeType == 'text/plain')
return ['plain' => decodeBody($part->body->data)];
else if($part->parts)
$return = [];
foreach($part->parts as $sub_part)
$result = msg_body_recursive($sub_part);
$return = array_merge($return, $result);
if(array_key_exists('html', $return))
break;
return $return;
return [];
function decodeBody($encoded)
$sanitizedData = strtr($encoded,'-_', '+/');
return base64_decode($sanitizedData);
【讨论】:
这是最好的答案。谢谢 我测试了其他解决方案,效果最好。确保你传递这样的东西: $service->users_messages->get('me', $message->getId());我花了一段时间才弄清楚。其他解决方案在 80% 的情况下有效,但在对象具有子部分时失败。非常感谢@potato。 这正是我所需要的,我喜欢它简短而甜美的事实。【参考方案7】:我只是想补充@F3L1X79 的答案,在你break de foreach 循环之前,你必须检查$FOUND_BODY 变量是否为FALSE,所以我在每次break 之前添加了一个If 条件;在身体搜索中。如果你不这样做,即使没有找到主体,代码也会中断。
if($FOUND_BODY !== false) break;
【讨论】:
以上是关于无法使用 Gmail PHP API 获取电子邮件正文的主要内容,如果未能解决你的问题,请参考以下文章
GMAIL API 的 PHP 实现 - 使用多个字符串进行过滤
使用带有 Laravel PHP 的 Gmail Api 读取网站上的所有 gmail 收件箱,然后回复特定的电子邮件
Gmail API - PHP - 使用服务帐户发送电子邮件
使用 PHP 向使用 Gmail API 发送的电子邮件添加密件抄送