]>
Commit | Line | Data |
---|---|---|
2ac10c6e ER |
1 | Handle broken headers like double encoded personal field of email in Mail_API::getAddressInfo() |
2 | Fix typo in Mail_API::getAddressInfo(). | |
3 | ||
4 | --- eventum-1.7.1/include/class.mail.php 2006-04-12 00:48:18.349874724 +0300 | |
5 | +++ /home/glen/class.mail.php 2006-04-12 00:52:33.195568053 +0300 | |
6 | @@ -245,12 +245,22 @@ | |
7 | $address = Mime_Helper::encodeValue($address); | |
8 | include_once(APP_PEAR_PATH . "Mail/RFC822.php"); | |
9 | $t = Mail_RFC822::parseAddressList($address, null, null, false); | |
10 | + if (PEAR::isError($t)) { | |
11 | + Error_Handler::logError(array($t->getMessage(), $t->getDebugInfo()), __FILE__, __LINE__); | |
12 | + // ugly hack: remove double quotes and retry. | |
13 | + $address = str_replace('""', '"', $address); | |
14 | + $t = Mail_RFC822::parseAddressList($address, null, null, false); | |
15 | + } | |
16 | + if (PEAR::isError($t)) { | |
17 | + Error_Handler::logError(array($t->getMessage(), $t->getDebugInfo()), __FILE__, __LINE__); | |
18 | + } | |
19 | + | |
20 | if ($multiple) { | |
21 | $returns = array(); | |
22 | for ($i = 0; $i < count($t); $i++) { | |
23 | $returns[] = array( | |
24 | 'sender_name' => $t[$i]->personal, | |
25 | - 'email' => $t[$i]->mailbox . '@' . $t[0]->host, | |
26 | + 'email' => $t[$i]->mailbox . '@' . $t[$i]->host, | |
27 | 'username' => $t[$i]->mailbox, | |
28 | 'host' => $t[$i]->host | |
29 | ); | |
30 | ||
31 | ------------------------------------------------------------------------------------------------------- | |
32 | Detect and log possibly corrupted MIME emails. | |
33 | ||
34 | --- eventum-1.7.1/include/class.mime_helper.php 2006-04-12 00:48:18.579879862 +0300 | |
35 | +++ /home/glen/class.mime_helper.php 2006-04-12 00:52:33.225568723 +0300 | |
36 | @@ -39,6 +39,7 @@ | |
37 | */ | |
38 | ||
39 | include_once(APP_PEAR_PATH . "Mail/mimeDecode.php"); | |
40 | +include_once(APP_INC_PATH . "class.error_handler.php"); | |
41 | ||
42 | /** | |
43 | * Class to handle the business logic related to the MIME email | |
44 | @@ -88,6 +89,10 @@ | |
45 | { | |
46 | $parts = array(); | |
47 | Mime_Helper::parse_output($output, $parts); | |
48 | + if (empty($parts)) { | |
49 | + Error_Handler::logError(array("Mime_Helper::parse_output failed. Corrupted MIME in email?", $output), __FILE__, __LINE__); | |
50 | + // we continue as if nothing happened until it's clear it's right check to do. | |
51 | + } | |
52 | $str = ''; | |
53 | $is_html = false; | |
54 | if (isset($parts["text"])) { | |
55 | ||
56 | ------------------------------------------------------------------------------------------------------- | |
57 | Rewrite routing part to have consistent API for matching issue_ids from mail headers. | |
58 | Add new method Routing::getMatchingIssueIDs(). | |
59 | ||
60 | --- eventum-1.7.1/include/class.routing.php 2006-04-12 00:48:18.189871149 +0300 | |
61 | +++ /home/glen/class.routing.php 2006-04-12 00:52:33.295570287 +0300 | |
62 | @@ -104,35 +104,29 @@ | |
63 | if ($setup['email_routing']['status'] != 'enabled') { | |
64 | return array(78, "Error: The email routing interface is disabled.\n"); | |
65 | } | |
66 | - $prefix = $setup['email_routing']['address_prefix']; | |
67 | - // escape plus signs so 'issue+1@example.com' becomes a valid routing address | |
68 | - $prefix = str_replace('+', '\+', $prefix); | |
69 | - $mail_domain = quotemeta($setup['email_routing']['address_host']); | |
70 | - $mail_domain_alias = quotemeta(@$setup['email_routing']['host_alias']); | |
71 | - if (!empty($mail_domain_alias)) { | |
72 | - $mail_domain = "(?:" . $mail_domain . "|" . $mail_domain_alias . ")"; | |
73 | - } | |
74 | - if (empty($prefix)) { | |
75 | + if (empty($setup['email_routing']['address_prefix'])) { | |
76 | return array(78, "Error: Please configure the email address prefix.\n"); | |
77 | } | |
78 | - if (empty($mail_domain)) { | |
79 | + if (empty($setup['email_routing']['address_host'])) { | |
80 | return array(78, "Error: Please configure the email address domain.\n"); | |
81 | } | |
82 | + | |
83 | $structure = Mime_Helper::decode($full_message, true, true); | |
84 | ||
85 | // find which issue ID this email refers to | |
86 | - @preg_match("/$prefix(\d*)@$mail_domain/i", $structure->headers['to'], $matches); | |
87 | - @$issue_id = $matches[1]; | |
88 | + if (isset($structure->headers['to'])) { | |
89 | + $issue_id = Routing::getMatchingIssueIDs($structure->headers['to'], 'email'); | |
90 | + } | |
91 | // validation is always a good idea | |
92 | - if (empty($issue_id)) { | |
93 | + if (empty($issue_id) and isset($structure->headers['cc'])) { | |
94 | // we need to try the Cc header as well | |
95 | - @preg_match("/$prefix(\d*)@$mail_domain/i", $structure->headers['cc'], $matches); | |
96 | - if (!empty($matches[1])) { | |
97 | - $issue_id = $matches[1]; | |
98 | - } else { | |
99 | - return array(65, "Error: The routed email had no associated Eventum issue ID or had an invalid recipient address.\n"); | |
100 | - } | |
101 | + $issue_id = Routing::getMatchingIssueIDs($structure->headers['cc'], 'email'); | |
102 | + } | |
103 | + | |
104 | + if (empty($issue_id)) { | |
105 | + return array(65, "Error: The routed email had no associated Eventum issue ID or had an invalid recipient address.\n"); | |
106 | } | |
107 | + | |
108 | if (empty($email_account_id)) { | |
109 | $issue_prj_id = Issue::getProjectID($issue_id); | |
110 | if (empty($issue_prj_id)) { | |
111 | @@ -305,30 +299,26 @@ | |
112 | if (@$setup['note_routing']['status'] != 'enabled') { | |
113 | return array(78, "Error: The internal note routing interface is disabled.\n"); | |
114 | } | |
115 | - $prefix = $setup['note_routing']['address_prefix']; | |
116 | - // escape plus signs so 'note+1@example.com' becomes a valid routing address | |
117 | - $prefix = str_replace('+', '\+', $prefix); | |
118 | - $mail_domain = quotemeta($setup['note_routing']['address_host']); | |
119 | - if (empty($prefix)) { | |
120 | + if (empty($setup['note_routing']['address_prefix'])) { | |
121 | return array(78, "Error: Please configure the email address prefix.\n"); | |
122 | } | |
123 | - if (empty($mail_domain)) { | |
124 | + if (empty($setup['note_routing']['address_host'])) { | |
125 | return array(78, "Error: Please configure the email address domain.\n"); | |
126 | } | |
127 | $structure = Mime_Helper::decode($full_message, true, true); | |
128 | ||
129 | // find which issue ID this email refers to | |
130 | - @preg_match("/$prefix(\d*)@$mail_domain/i", $structure->headers['to'], $matches); | |
131 | - @$issue_id = $matches[1]; | |
132 | + if (isset($structure->headers['to'])) { | |
133 | + $issue_id = Routing::getMatchingIssueIDs($structure->headers['to'], 'note'); | |
134 | + } | |
135 | // validation is always a good idea | |
136 | - if (empty($issue_id)) { | |
137 | + if (empty($issue_id) and isset($structure->headers['cc'])) { | |
138 | // we need to try the Cc header as well | |
139 | - @preg_match("/$prefix(\d*)@$mail_domain/i", $structure->headers['cc'], $matches); | |
140 | - if (!empty($matches[1])) { | |
141 | - $issue_id = $matches[1]; | |
142 | - } else { | |
143 | - return array(65, "Error: The routed note had no associated Eventum issue ID or had an invalid recipient address.\n"); | |
144 | - } | |
145 | + $issue_id = Routing::getMatchingIssueIDs($structure->headers['cc'], 'note'); | |
146 | + } | |
147 | + | |
148 | + if (empty($issue_id)) { | |
149 | + return array(65, "Error: The routed note had no associated Eventum issue ID or had an invalid recipient address.\n"); | |
150 | } | |
151 | ||
152 | $prj_id = Issue::getProjectID($issue_id); | |
153 | @@ -389,6 +379,7 @@ | |
154 | if ($res != -1) { | |
155 | Support::extractAttachments($issue_id, $full_message, true, $res); | |
156 | } | |
157 | + // FIXME! $res == -2 is not handled | |
158 | History::add($issue_id, Auth::getUserID(), History::getTypeID('note_routed'), "Note routed from " . $structure->headers['from']); | |
159 | ||
160 | return true; | |
161 | @@ -433,30 +424,27 @@ | |
162 | if (@$setup['draft_routing']['status'] != 'enabled') { | |
163 | return array(78, "Error: The email draft interface is disabled.\n"); | |
164 | } | |
165 | - $prefix = $setup['draft_routing']['address_prefix']; | |
166 | - // escape plus signs so 'draft+1@example.com' becomes a valid address | |
167 | - $prefix = str_replace('+', '\+', $prefix); | |
168 | - $mail_domain = quotemeta($setup['draft_routing']['address_host']); | |
169 | - if (empty($prefix)) { | |
170 | + if (empty($setup['draft_routing']['address_prefix'])) { | |
171 | return array(78, "Error: Please configure the email address prefix.\n"); | |
172 | } | |
173 | - if (empty($mail_domain)) { | |
174 | + if (empty($setup['draft_routing']['address_host'])) { | |
175 | return array(78, "Error: Please configure the email address domain.\n"); | |
176 | } | |
177 | + | |
178 | $structure = Mime_Helper::decode($full_message, true, false); | |
179 | ||
180 | // find which issue ID this email refers to | |
181 | - @preg_match("/$prefix(\d*)@$mail_domain/i", $structure->headers['to'], $matches); | |
182 | - @$issue_id = $matches[1]; | |
183 | + if (isset($structure->headers['to'])) { | |
184 | + $issue_id = Routing::getMatchingIssueIDs($structure->headers['to'], 'draft'); | |
185 | + } | |
186 | // validation is always a good idea | |
187 | - if (empty($issue_id)) { | |
188 | + if (empty($issue_id) and isset($structure->headers['cc'])) { | |
189 | // we need to try the Cc header as well | |
190 | - @preg_match("/$prefix(\d*)@$mail_domain/i", $structure->headers['cc'], $matches); | |
191 | - if (!empty($matches[1])) { | |
192 | - $issue_id = $matches[1]; | |
193 | - } else { | |
194 | - return array(65, "Error: The routed draft had no associated Eventum issue ID or had an invalid recipient address.\n"); | |
195 | - } | |
196 | + $issue_id = Routing::getMatchingIssueIDs($structure->headers['cc'], 'draft'); | |
197 | + } | |
198 | + | |
199 | + if (empty($issue_id)) { | |
200 | + return array(65, "Error: The routed email had no associated Eventum issue ID or had an invalid recipient address.\n"); | |
201 | } | |
202 | ||
203 | $prj_id = Issue::getProjectID($issue_id); | |
204 | @@ -477,5 +465,54 @@ | |
205 | History::add($issue_id, Auth::getUserID(), History::getTypeID('draft_routed'), "Draft routed from " . $structure->headers['from']); | |
206 | return true; | |
207 | } | |
208 | + | |
209 | + /** | |
210 | + * Check for $adresses for matches | |
211 | + * | |
212 | + * @param mixed $addresses to check | |
213 | + * @param string Type of address match to find (email, note, draft) | |
214 | + * @return mixed $issue_id in case of match otherwise false | |
215 | + */ | |
216 | + function getMatchingIssueIDs($addresses, $type) | |
217 | + { | |
218 | + $setup = Setup::load(); | |
219 | + $settings = $setup["${type}_routing"]; | |
220 | + if (!is_array($settings)) { | |
221 | + return false; | |
222 | + } | |
223 | + | |
224 | + if (empty($settings['address_prefix'])) { | |
225 | + return false; | |
226 | + } | |
227 | + // escape plus signs so 'issue+1@example.com' becomes a valid routing address | |
228 | + $prefix = quotemeta($settings['address_prefix']); | |
229 | + | |
230 | + if (empty($settings['address_host'])) { | |
231 | + return false; | |
232 | + } | |
233 | + $mail_domain = quotemeta($settings['address_host']); | |
234 | + | |
235 | + // it is not checked for type when host alias is asked. this leaves | |
236 | + // room foradding host_alias for other than email routing. | |
237 | + if (isset($settings['host_alias'])) { | |
238 | + // TODO: can't quotemeta() host alias as it can contain multiple hosts separated with pipe | |
239 | + $mail_domain = '(?:' . $mail_domain . '|' . $settings['host_alias'] . ')'; | |
240 | + } | |
241 | + | |
242 | + // if there are multiple CC or To headers Mail_Mime creates array. | |
243 | + // handle both cases (strings and arrays). | |
244 | + if (!is_array($addresses)) { | |
245 | + $addresses = array($addresses); | |
246 | + } | |
247 | + | |
248 | + // everything safely escaped and checked, try matching address | |
249 | + foreach ($addresses as $address) { | |
250 | + if (preg_match("/$prefix(\d*)@$mail_domain/i", $address, $matches)) { | |
251 | + return $matches[1]; | |
252 | + } | |
253 | + } | |
254 | + | |
255 | + return false; | |
256 | + } | |
257 | } | |
258 | ?> | |
259 | --- eventum-1.7.1/include/class.support.php 2006-04-12 00:48:18.619880756 +0300 | |
260 | +++ /home/glen/class.support.php 2006-04-12 00:52:33.395572521 +0300 | |
261 | @@ -504,22 +504,22 @@ | |
262 | if ($info['ema_use_routing'] == 1) { | |
263 | $setup = Setup::load(); | |
264 | ||
265 | - if (@$setup['email_routing']['status'] == 'enabled') { | |
266 | - $prefix = $setup['email_routing']['address_prefix']; | |
267 | - // escape plus signs so 'issue+1@example.com' becomes a valid routing address | |
268 | - $prefix = str_replace('+', '\+', $prefix); | |
269 | - $mail_domain = $setup['email_routing']['address_host']; | |
270 | - $mail_domain_alias = @$setup['email_routing']['host_alias']; | |
271 | - if (!empty($mail_domain_alias)) { | |
272 | - $mail_domain = "[" . $mail_domain . "|" . $mail_domain_alias . "]"; | |
273 | - } | |
274 | - if (empty($prefix)) { | |
275 | - return false; | |
276 | + // we create addresses array so it can be reused | |
277 | + $addresses = array(); | |
278 | + if (isset($email->to)) { | |
279 | + foreach ($email->to as $address) { | |
280 | + $addresses[] = $address->mailbox . '@' . $address->host; | |
281 | } | |
282 | - if (empty($mail_domain)) { | |
283 | - return false; | |
284 | + } | |
285 | + if (isset($email->cc)) { | |
286 | + foreach ($email->cc as $address) { | |
287 | + $addresses[] = $address->mailbox . '@' . $address->host; | |
288 | } | |
289 | - if (preg_match("/$prefix(\d*)@$mail_domain/i", $email->toaddress, $matches)) { | |
290 | + } | |
291 | + | |
292 | + if (@$setup['email_routing']['status'] == 'enabled') { | |
293 | + $res = Routing::getMatchingIssueIDs($addresses, 'email'); | |
294 | + if ($res != false) { | |
295 | $return = Routing::route_emails($message); | |
296 | if ($return == true) { | |
297 | Support::deleteMessage($info, $mbox, $num); | |
298 | @@ -528,18 +528,8 @@ | |
299 | } | |
300 | } | |
301 | if (@$setup['note_routing']['status'] == 'enabled') { | |
302 | - $prefix = $setup['note_routing']['address_prefix']; | |
303 | - // escape plus signs so 'note+1@example.com' becomes a valid routing address | |
304 | - $prefix = str_replace('+', '\+', $prefix); | |
305 | - $mail_domain = $setup['note_routing']['address_host']; | |
306 | - if (empty($prefix)) { | |
307 | - return false; | |
308 | - } | |
309 | - if (empty($mail_domain)) { | |
310 | - return false; | |
311 | - } | |
312 | - | |
313 | - if (preg_match("/$prefix(\d*)@$mail_domain/i", $email->toaddress, $matches)) { | |
314 | + $res = Routing::getMatchingIssueIDs($addresses, 'note'); | |
315 | + if ($res != false) { | |
316 | $return = Routing::route_notes($message); | |
317 | if ($return == true) { | |
318 | Support::deleteMessage($info, $mbox, $num); | |
319 | @@ -548,18 +538,8 @@ | |
320 | } | |
321 | } | |
322 | if (@$setup['draft_routing']['status'] == 'enabled') { | |
323 | - $prefix = $setup['draft_routing']['address_prefix']; | |
324 | - // escape plus signs so 'draft+1@example.com' becomes a valid routing address | |
325 | - $prefix = str_replace('+', '\+', $prefix); | |
326 | - $mail_domain = $setup['draft_routing']['address_host']; | |
327 | - if (empty($prefix)) { | |
328 | - return false; | |
329 | - } | |
330 | - if (empty($mail_domain)) { | |
331 | - return false; | |
332 | - } | |
333 | - | |
334 | - if (preg_match("/$prefix(\d*)@$mail_domain/i", $email->toaddress, $matches)) { | |
335 | + $res = Routing::getMatchingIssueIDs($addresses, 'draft'); | |
336 | + if ($res != false) { | |
337 | $return = Routing::route_drafts($message); | |
338 | if ($return == true) { | |
339 | Support::deleteMessage($info, $mbox, $num); | |
340 | ||
341 | ------------------------------------------------------------------------------------------------------- | |
342 | Fix possible Cc: headers composition of routed Notes where Eventum user email and email from headers differ with case. | |
343 | ||
344 | --- eventum-1.7.1/include/class.routing.php 2006-04-12 00:48:18.189871149 +0300 | |
345 | +++ /home/glen/class.routing.php 2006-04-12 00:52:33.295570287 +0300 | |
346 | @@ -356,12 +346,11 @@ | |
347 | $cc_users = array(); | |
348 | foreach ($addresses as $email) { | |
349 | if (in_array(strtolower($email), $user_emails)) { | |
350 | - $cc_users[] = $users[$email]; | |
351 | + $cc_users[] = $users[strtolower($email)]; | |
352 | } | |
353 | } | |
354 | ||
355 | $body = Mime_Helper::getMessageBody($structure); | |
356 | - | |
357 | $reference_msg_id = Mail_API::getReferenceMessageID($headers); | |
358 | if (!empty($reference_msg_id)) { | |
359 | $parent_id = Note::getIDByMessageID($reference_msg_id); | |
360 | ------------------------------------------------------------------------------------------------------- | |
361 | API cleanup: drop unneccessary $email_account_id in route_emails to be consistent with download_emails based routing. | |
362 | ||
363 | --- eventum-1.7.1/misc/route_emails.php 2006-04-12 00:54:57.398789518 +0300 | |
364 | +++ /home/glen/route_emails.php 2006-04-12 01:03:52.300737408 +0300 | |
365 | @@ -33,10 +33,9 @@ | |
366 | include_once(APP_INC_PATH . "db_access.php"); | |
367 | include_once(APP_INC_PATH . "class.routing.php"); | |
368 | ||
369 | -$email_account_id = $HTTP_SERVER_VARS['argv'][1]; | |
370 | $full_message = Misc::getInput(); | |
371 | ||
372 | -$return = Routing::route_emails($full_message, $email_account_id); | |
373 | +$return = Routing::route_emails($full_message); | |
374 | if (is_array($return)) { | |
375 | echo $return[1]; | |
376 | exit($return[0]); | |
377 | --- eventum-1.7.1/include/class.routing.php 2006-04-12 00:54:57.278786838 +0300 | |
378 | +++ /home/glen/class.routing.php 2006-04-12 01:03:45.370582745 +0300 | |
379 | @@ -52,9 +52,8 @@ | |
380 | * Routes an email to the correct issue. | |
381 | * | |
382 | * @param string $full_message The full email message, including headers | |
383 | - * @param integer $email_account_id The ID of the email account this email should be routed too. If empty this method will try to figure it out | |
384 | */ | |
385 | - function route_emails($full_message, $email_account_id = 0) | |
386 | + function route_emails($full_message) | |
387 | { | |
388 | GLOBAL $HTTP_POST_VARS; | |
389 |