1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
14: class Whups_Mail
15: {
16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34:
35: static public function processMail($text, array $info, $auth_user = null)
36: {
37: global $conf;
38:
39: $message = Horde_Mime_Part::parseMessage($text);
40:
41: if (preg_match("/^(.*?)\r?\n\r?\n/s", $text, $matches)) {
42: $hdrText = $matches[1];
43: } else {
44: $hdrText = $text;
45: }
46: $headers = Horde_Mime_Headers::parseHeaders($hdrText);
47:
48:
49: if ($headers->getValue('X-Whups-Generated')) {
50: return true;
51: }
52:
53:
54: $from = $headers->getValue('from');
55: if (strpos($headers->getValue('Content-Type'), 'multipart/report') !== false ||
56: stripos($from, 'mailer-daemon@') !== false ||
57: stripos($from, 'postmaster@') !== false ||
58: !is_null($headers->getValue('X-Failed-Recipients'))) {
59: return true;
60: }
61:
62:
63: $info['summary'] = trim($headers->getValue('subject'));
64: if (empty($info['summary'])) {
65: $info['summary'] = _("[No Subject]");
66: }
67:
68:
69: $comment = _("Received message:") . "\n\n";
70: if (!empty($GLOBALS['conf']['mail']['include_headers'])) {
71: foreach ($headers->toArray(array('nowrap' => true)) as $name => $vals) {
72: if (!in_array(strtolower($name), array('subject', 'from', 'to', 'cc', 'date'))) {
73: if (is_array($vals)) {
74: foreach ($vals as $val) {
75: $comment .= $name . ': ' . $val . "\n";
76: }
77: } else {
78: $comment .= $name . ': ' . $vals . "\n";
79: }
80: }
81: }
82:
83: $comment .= "\n";
84: }
85:
86:
87: $body_id = $message->findBody();
88: if ($body_id) {
89: $part = $message->getPart($body_id);
90: $content = Horde_String::convertCharset(
91: $part->getContents(), $part->getCharset(), 'UTF-8');
92: switch ($part->getType()) {
93: case 'text/plain':
94: $comment .= $content;
95: break;
96: case 'text/html':
97: $comment .= Horde_Text_Filter::filter(
98: $content, array('Html2text'), array(array('width' => 0)));;
99: break;
100: default:
101: $comment .= _("[ Could not render body of message. ]");
102: break;
103: }
104: } else {
105: $comment .= _("[ Could not render body of message. ]");
106: }
107:
108: $info['comment'] = $comment . "\n";
109:
110:
111: if (empty($auth_user)) {
112: $auth_user = self::_findAuthUser(Horde_Mime_Address::bareAddress($from));
113: }
114: $author = $auth_user;
115:
116: if (empty($auth_user) && !empty($info['default_auth'])) {
117: $auth_user = $info['default_auth'];
118: if (!empty($from)) {
119: $info['user_email'] = $from;
120: }
121: }
122:
123: if (empty($auth_user) && !empty($conf['mail']['username'])) {
124: $auth_user = $conf['mail']['username'];
125: if (!empty($from)) {
126: $info['user_email'] = $from;
127: }
128: }
129:
130:
131: if (!empty($auth_user) && $auth_user != $GLOBALS['registry']->getAuth()) {
132: $GLOBALS['registry']->setAuth($auth_user, array());
133: }
134:
135:
136: $attachments = array();
137: $dl_list = array_slice(array_keys($message->contentTypeMap()), 1);
138: foreach ($dl_list as $key) {
139: $part = $message->getPart($key);
140: if (($key == $body_id && $part->getType() == 'text/plain') ||
141: $part->getType() == 'multipart/alternative' ||
142: $part->getType() == 'multipart/mixed') {
143: continue;
144: }
145: $tmp_name = Horde::getTempFile('whups');
146: $fp = @fopen($tmp_name, 'wb');
147: if (!$fp) {
148: Horde::logMessage(sprintf('Cannot open file %s for writing.',
149: $tmp_name), 'ERR');
150: return $ticket;
151: }
152: fwrite($fp, $part->getContents());
153: fclose($fp);
154: $part_name = $part->getName(true);
155: if (!$part_name) {
156: $ptype = $part->getPrimaryType();
157: switch ($ptype) {
158: case 'multipart':
159: case 'application':
160: $part_name = sprintf(_("%s part"), ucfirst($part->getSubType()));
161: break;
162: default:
163: $part_name = sprintf(_("%s part"), ucfirst($ptype));
164: break;
165: }
166: if ($ext = Horde_Mime_Magic::mimeToExt($part->getType())) {
167: $part_name .= '.' . $ext;
168: }
169: }
170: $attachments[] = array(
171: 'name' => $part_name,
172: 'tmp_name' => $tmp_name);
173: }
174:
175:
176: if ($ticket = self::_findTicket($info)) {
177: $ticket->change('comment', $info['comment']);
178: $ticket->change('comment-email', $from);
179: if ($attachments) {
180: $ticket->change('attachments', $attachments);
181: }
182: $ticket->commit($author);
183: } elseif (!empty($info['ticket'])) {
184:
185:
186: throw new Whups_Exception(
187: sprintf(_("Could not find ticket \"%s\"."), $info['ticket']));
188: } else {
189: if (!empty($info['guess-queue'])) {
190:
191:
192: $queues = $GLOBALS['whups_driver']->getQueues();
193: foreach ($queues as $queueId => $queueName) {
194: if (preg_match('/\b' . preg_quote($queueName, '/') . '\b/i',
195: $info['summary'])) {
196: $info['queue'] = $queueId;
197: break;
198: }
199: }
200: }
201: $info['attachments'] = $attachments;
202:
203:
204: $ticket = Whups_Ticket::newTicket($info, $author);
205: }
206: }
207:
208: 209: 210: 211: 212: 213: 214: 215:
216: static protected function _findTicket(array $info)
217: {
218: if (!empty($info['ticket'])) {
219: $ticketnum = $info['ticket'];
220: } elseif (preg_match('/\[[\w\s]*#(\d+)\]/', $info['summary'], $matches)) {
221: $ticketnum = $matches[1];
222: } else {
223: return false;
224: }
225:
226: try {
227: return Whups_Ticket::makeTicket($ticketnum);
228: } catch (Whups_Exception $e) {
229: return false;
230: }
231: }
232:
233: 234: 235: 236: 237: 238: 239: 240: 241: 242:
243: static protected function _findAuthUser($from)
244: {
245: $auth = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Auth')->create();
246:
247: if ($auth->hasCapability('list')) {
248: foreach ($auth->listUsers() as $user) {
249: $identity = $GLOBALS['injector']
250: ->getInstance('Horde_Core_Factory_Identity')
251: ->create($user);
252: $addrs = $identity->getAll('from_addr');
253: foreach ($addrs as $addr) {
254: if (strcasecmp($from, $addr) == 0) {
255: return $user;
256: }
257: }
258: }
259: }
260:
261: return false;
262: }
263:
264: }
265: