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 ) ) ) )