I am making a request to the User.messages endpoint. All objects returned (the emails) have a mimeType property which I\'m struggling to understand.
More specificall
I know this question is not new but I've wrote a PHP script which correctly parses messages pulled from Gmail API, including any type of attachment.
The script includes a recursive "iterateParts" function which iterates all message parts so we can be sure we extracted all available data from each message.
Script steps are:
$maxToPull = 1;
$gmailQuery = "ALL";
// Initializing Google API
$service = new Google_Service_Gmail($client);
// Pulling all gmail messages into $messages array
$user = 'me';
$msglist = $service->users_messages->listUsersMessages($user, ["maxResults"=>$maxToPull, "q"=>$gmailQuery]);
$messages = $msglist->getMessages();
// Master array that will hold all parsed messages data, including attachments
$allmsgArr = array();
// Traverse each message
foreach($messages as $message)
{
$msgArr = array();
$single_message = $service->users_messages->get('me', $message->getId());
$payload = $single_message->getPayload();
// Nice to have the gmail msg id, can be used to direct access the message in Gmail's web gui
$msgArr['gmailmsgid'] = $message->getId();
// Retrieving the subject and "from" email address
foreach($payload->getheaders() as $oneheader)
{
if($oneheader['name'] == 'Subject')
$msgArr['subject'] = $oneheader['value'];
if($oneheader['name'] == 'From')
$msgArr['fromaddress'] = substr($oneheader['value'], strpos($oneheader['value'], '<')+1, -1);
}
// If body is directly in the message payload (only for plain text messages where there's no HTML part and no attachments, normally this is not the case)
if($payload['body']['size'] > 0)
$msgArr['textplain'] = $payload['body']['data'];
// Else, iterate over each message part and continue to dig if necessary
else
iterateParts($payload, $message->getId());
// Push the parsed $msgArr (parsed by iterateParts) to master array
array_push($allmsgArr, $msgArr);
}
// Traverse each parsed message and saving it's content and attachments to files
foreach($allmsgArr as $onemsgArr)
{
$folder = "messages/".$onemsgArr['gmailmsgid'];
mkdir($folder);
if($onemsgArr['textplain'])
file_put_contents($folder."/textplain.txt", decodeData($onemsgArr['textplain']));
if($onemsgArr['texthtml'])
file_put_contents($folder."/texthtml.html", decodeData($onemsgArr['texthtml']));
if($onemsgArr['attachments'])
{
foreach($onemsgArr['attachments'] as $oneattachment)
{
if(!empty($oneattachment['filename']))
$filename = $oneattachment['filename'];
else if($oneattachment['mimetype'] == "message/rfc822" && empty($oneattachment['filename'])) // email attachments
$filename = "noname.eml";
else
$filename = "unknown";
file_put_contents($folder."/".$filename, decodeData($oneattachment['data']));
}
}
}
function iterateParts($obj, $msgid) {
global $msgArr;
global $service;
foreach($obj as $parts)
{
// if found body data
if($parts['body']['size'] > 0)
{
// plain text representation of message body
if($parts['mimeType'] == 'text/plain')
{
$msgArr['textplain'] = $parts['body']['data'];
}
// html representation of message body
else if($parts['mimeType'] == 'text/html')
{
$msgArr['texthtml'] = $parts['body']['data'];
}
// if it's an attachment
else if(!empty($parts['body']['attachmentId']))
{
$attachArr['mimetype'] = $parts['mimeType'];
$attachArr['filename'] = $parts['filename'];
$attachArr['attachmentId'] = $parts['body']['attachmentId'];
// the message holds the attachment id, retrieve it's data from users_messages_attachments
$attachmentId_base64 = $parts['body']['attachmentId'];
$single_attachment = $service->users_messages_attachments->get('me', $msgid, $attachmentId_base64);
$attachArr['data'] = $single_attachment->getData();
$msgArr['attachments'][] = $attachArr;
}
}
// if there are other parts inside, go get them
if(!empty($parts['parts']) && !empty($parts['mimeType']) && empty($parts['body']['attachmentId']))
{
iterateParts($parts->getParts(), $msgid);
}
}
}
// All data returned from API is base64 encoded
function decodeData($data)
{
$sanitizedData = strtr($data,'-_', '+/');
return base64_decode($sanitizedData);
}
This is how $allmsgArr will look like (where only one message was pulled):
Array
(
[0] => Array
(
[gmailmsgid] => 25k1asfa556x2da
[fromaddress] => john@gmail.com
[subject] => Fwd: Sea gulls picture
[textplain] => UE5SIDQxQzAwMg0KDQpBUkJFTFRFU1QxDQoNCg0K
[texthtml] => PGRpdiBkaXI9Imx0ciI-PHNwYW4gc3R5bGU9ImZi
[attachments] => Array
(
[0] => Array
(
[mimetype] => image/png
[filename] => sea_gulls.png
[attachmentId] => ANGjdJ9tmy4d8vPXhU_BjNEFEaDODOpu29W2u5OTM7a0
[data] => iVBORw0KGgoAAAANSUhEUgAABSYAAAKWCAYAAABUP
)
[1] => Array
(
[mimetype] => image/jpeg
[filename] => Outlook_Signature.jpg
[attachmentId] => ANGjdJ-CgZTK0oK44Q8j7TlN_JlaexxGKZ_wHFfoEB
[data] => 6jRXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAEa
)
)
)
)