Where to find body of email depending of mimeType

后端 未结 5 1875
小蘑菇
小蘑菇 2020-12-01 09:53

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

5条回答
  •  情深已故
    2020-12-01 10:17

    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:

    1. Pull all message ids from API
    2. Get some important headers (subject & from address)
    3. Either body is directly on payload or send payload to iterateParts
    4. iterateParts is parsing each message to $msgArr with it's data, base64 encoded
    5. Push $msgArr to master array $allmsgArr
    6. Traverse master array and save each part as file according to it's MIME type and filename
    
        $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
                            )
    
                    )
            )
    )
    
    

提交回复
热议问题