1: <?php
2:
3: App::uses('PlancakeEmailParser', 'Email.Lib/PlancakeEmailParser');
4:
5: class MailParser {
6:
7: public static function parseFile($path) {
8: return self::parse(file_get_contents($path));
9: }
10:
11: public static function parse($content) {
12: $main = self::_parseRawMail($content);
13: $ret = array();
14: foreach (array('to', 'from', 'bcc', 'cc') as $header) {
15: $ret[$header] = empty($main['headers'][$header]) ?
16: array() :
17: self::_buildAddressList($main['headers'][$header]);
18: }
19: foreach (array('reply_to', 'sender') as $header) {
20: $ret[$header] = empty($main['headers'][$header]) ?
21: self::_buildAddressList($main['headers']['from']) :
22: self::_buildAddressList($main['headers'][$header]);
23: }
24: foreach (array('subject', 'in_reply_to', 'message-id') as $header) {
25: $ret[str_replace('-', '_', $header)] = empty($main['headers'][$header]) ? '' : $main['headers'][$header];
26: }
27:
28: $ret['date'] = new Horde_Imap_Client_DateTime($main['headers']['date']);
29: $ret['bodies'] = self::_buildBodies($main);
30: return $ret;
31: }
32:
33: private static function _mimeDecode($string) {
34: return iconv_mime_decode($string, 0, mb_internal_encoding());
35: }
36:
37: private static function _parseRawMail($content) {
38: $mimemail = mailparse_msg_create();
39: mailparse_msg_parse($mimemail, $content);
40: $parsedData = mailparse_msg_get_part_data($mimemail);
41: $parsedData['body'] = self::_extractBody($parsedData, $content);
42: if (!empty($parsedData['headers']['subject'])) {
43: $parsedData['headers']['subject'] = self::_mimeDecode($parsedData['headers']['subject']);
44: }
45: mailparse_msg_free($mimemail);
46: return $parsedData;
47: }
48:
49: private static function _buildBodies($parsedData) {
50: if (strpos($parsedData['content-type'],'multipart/') === 0) {
51: return self::_buildBodiesFromMultipart($parsedData['body'], $parsedData['content-boundary']);
52: } else {
53: return array(
54: $parsedData['content-type'] => self::_mimeDecode($parsedData['body'])
55: );
56: }
57: }
58:
59: private static function _buildBodiesFromMultipart($body, $boundary) {
60: $parts = explode("--" . $boundary, $body);
61: array_shift($parts);
62: array_pop($parts);
63: $bodies = array();
64: foreach ($parts as $part) {
65: $partRawData = preg_replace("/\r\n\$/", '', ltrim($part));
66: $parsedData = self::_parseRawMail($partRawData);
67: $bodies[$parsedData['content-type']] = $parsedData['body'];
68: }
69: return $bodies;
70: }
71:
72: private static function _extractBody($parsedData, $content) {
73: $body = substr($content, $parsedData['starting-pos-body']);
74: if (!empty($parsedData['transfer-encoding']) && $parsedData['transfer-encoding'] == 'quoted-printable') {
75: $body = quoted_printable_decode($body);
76: }
77: return $body;
78: }
79:
80: private static function _buildAddressList($string) {
81: return array_map(function($v) {
82: return $v['address'];
83: }, mailparse_rfc822_parse_addresses($string));
84: }
85:
86: }
87: