- Fix handling of email addresses with quoted local part (#1487939)
| | |
| | | CHANGELOG Roundcube Webmail |
| | | =========================== |
| | | |
| | | - Fix handling of email addresses with quoted local part (#1487939) |
| | | - Fix EOL character in vCard exports (#1487873) |
| | | - Added optional "multithreading" autocomplete feature |
| | | - Plugin API: Added 'config_get' hook |
| | |
| | | $str = self::explode_header_string(',;', $str, true); |
| | | $result = array(); |
| | | |
| | | // simplified regexp, supporting quoted local part |
| | | $email_rx = '(\S+|("\s*(?:[^"\f\n\r\t\v\b\s]+\s*)+"))@\S+'; |
| | | |
| | | foreach ($str as $key => $val) { |
| | | $name = ''; |
| | | $address = ''; |
| | | $val = trim($val); |
| | | |
| | | if (preg_match('/(.*)<(\S+@\S+)>$/', $val, $m)) { |
| | | if (preg_match('/(.*)<('.$email_rx.')>$/', $val, $m)) { |
| | | $address = $m[2]; |
| | | $name = trim($m[1]); |
| | | } |
| | |
| | | |
| | | // dequote and/or decode name |
| | | if ($name) { |
| | | if ($name[0] == '"') { |
| | | if ($name[0] == '"' && $name[strlen($name)-1] == '"') { |
| | | $name = substr($name, 1, -1); |
| | | $name = stripslashes($name); |
| | | } |
| | |
| | | // if we're passed an array, assume addresses are valid and implode them before parsing. |
| | | if (is_array($recipients)) |
| | | $recipients = implode(', ', $recipients); |
| | | |
| | | |
| | | $addresses = array(); |
| | | $recipients = rcube_explode_quoted_string(',', $recipients); |
| | | |
| | | reset($recipients); |
| | | while (list($k, $recipient) = each($recipients)) |
| | | { |
| | | $a = explode(" ", $recipient); |
| | | $a = rcube_explode_quoted_string(' ', $recipient); |
| | | while (list($k2, $word) = each($a)) |
| | | { |
| | | if (strpos($word, "@") > 0 && $word[strlen($word)-1] != '"') |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | return $addresses; |
| | | } |
| | | |
| | |
| | | */ |
| | | var $_eol = "\r\n"; |
| | | |
| | | |
| | | /** |
| | | * Constructor. |
| | | * |
| | |
| | | |
| | | // Structured header (make sure addr-spec inside is not encoded) |
| | | if (!empty($separator)) { |
| | | // Simple e-mail address regexp |
| | | $email_regexp = '(\S+|("\s*(?:[^"\f\n\r\t\v\b\s]+\s*)+"))@\S+'; |
| | | |
| | | $parts = Mail_mimePart::_explodeQuotedString($separator, $value); |
| | | $value = ''; |
| | | |
| | |
| | | } |
| | | |
| | | // let's find phrase (name) and/or addr-spec |
| | | if (preg_match('/^<\S+@\S+>$/', $part)) { |
| | | if (preg_match('/^<' . $email_regexp . '>$/', $part)) { |
| | | $value .= $part; |
| | | } else if (preg_match('/^\S+@\S+$/', $part)) { |
| | | } else if (preg_match('/^' . $email_regexp . '$/', $part)) { |
| | | // address without brackets and without name |
| | | $value .= $part; |
| | | } else if (preg_match('/<*\S+@\S+>*$/', $part, $matches)) { |
| | | } else if (preg_match('/<*' . $email_regexp . '>*$/', $part, $matches)) { |
| | | // address with name (handle name) |
| | | $address = $matches[0]; |
| | | $word = str_replace($address, '', $part); |
| | |
| | | { |
| | | global $EMAIL_FORMAT_ERROR, $RECIPIENT_COUNT; |
| | | |
| | | $regexp = array('/[,;]\s*[\r\n]+/', '/[\r\n]+/', '/[,;]\s*$/m', '/;/', '/(\S{1})(<\S+@\S+>)/U'); |
| | | // simplified email regexp, supporting quoted local part |
| | | $email_regexp = '(\S+|("\s*(?:[^"\f\n\r\t\v\b\s]+\s*)+"))@\S+'; |
| | | |
| | | $regexp = array('/[,;]\s*[\r\n]+/', '/[\r\n]+/', '/[,;]\s*$/m', '/;/', '/(\S{1})(<'.$email_regexp.'>)/U'); |
| | | $replace = array(', ', ', ', '', ',', '\\1 \\2'); |
| | | |
| | | // replace new lines and strip ending ', ', make address input more valid |
| | |
| | | foreach($items as $item) { |
| | | $item = trim($item); |
| | | // address in brackets without name (do nothing) |
| | | if (preg_match('/^<\S+@\S+>$/', $item)) { |
| | | if (preg_match('/^<'.$email_regexp.'>$/', $item)) { |
| | | $item = rcube_idn_to_ascii($item); |
| | | $result[] = $item; |
| | | // address without brackets and without name (add brackets) |
| | | } else if (preg_match('/^\S+@\S+$/', $item)) { |
| | | } else if (preg_match('/^'.$email_regexp.'$/', $item)) { |
| | | $item = rcube_idn_to_ascii($item); |
| | | $result[] = '<'.$item.'>'; |
| | | // address with name (handle name) |
| | | } else if (preg_match('/\S+@\S+>*$/', $item, $matches)) { |
| | | } else if (preg_match('/'.$email_regexp.'>*$/', $item, $matches)) { |
| | | $address = $matches[0]; |
| | | $name = str_replace($address, '', $item); |
| | | $name = trim($name); |
| | |
| | | $name = '"'.addcslashes($name, '"').'"'; |
| | | } |
| | | $address = rcube_idn_to_ascii($address); |
| | | if (!preg_match('/^<\S+@\S+>$/', $address)) |
| | | if (!preg_match('/^<'.$email_regexp.'>$/', $address)) |
| | | $address = '<'.$address.'>'; |
| | | |
| | | $result[] = $name.' '.$address; |
| | |
| | | 16 => 'Test Test ((comment)) <test@domain.tld>', |
| | | 17 => 'test@domain.tld (comment)', |
| | | 18 => '"Test,Test" <test@domain.tld>', |
| | | // 1487939 |
| | | 19 => 'Test <"test test"@domain.tld>', |
| | | ); |
| | | |
| | | $results = array( |
| | |
| | | 16 => array(1, 'Test Test', 'test@domain.tld'), |
| | | 17 => array(1, '', 'test@domain.tld'), |
| | | 18 => array(1, 'Test,Test', 'test@domain.tld'), |
| | | 19 => array(1, 'Test', '"test test"@domain.tld'), |
| | | ); |
| | | |
| | | foreach ($headers as $idx => $header) { |
| | |
| | | |
| | | $this->assertEqual($results[$idx][0], count($res), "Rows number in result for header: " . $header); |
| | | $this->assertEqual($results[$idx][1], $res[1]['name'], "Name part decoding for header: " . $header); |
| | | $this->assertEqual($results[$idx][2], $res[1]['mailto'], "Name part decoding for header: " . $header); |
| | | $this->assertEqual($results[$idx][2], $res[1]['mailto'], "Email part decoding for header: " . $header); |
| | | } |
| | | } |
| | | |