Index: phpmailer.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/phpmailer/phpmailer.module,v
retrieving revision 1.11.2.1
diff -u -p -r1.11.2.1 phpmailer.module
--- phpmailer.module	16 Nov 2009 12:57:25 -0000	1.11.2.1
+++ phpmailer.module	20 Nov 2009 09:35:07 -0000
@@ -97,7 +97,7 @@ function phpmailer_mailengine($op, $mess
 /**
  * Extract address and optional display name of an e-mail address.
  *
- * @param $address
+ * @param $string
  *   A string containing one or more valid e-mail address(es) separated with
  *   commas.
  *
@@ -106,24 +106,56 @@ function phpmailer_mailengine($op, $mess
  *
  * @see http://tools.ietf.org/html/rfc5322#section-3.4
  */
-function phpmailer_parse_address($address) {
+function phpmailer_parse_address($string) {
   $parsed = array();
-  $regexp = "/^(.*) <([a-z0-9]+(?:[_\\.-][a-z0-9]+)*@(?:[a-z0-9]+(?:[\.-][a-z0-9]+)*)+\\.[a-z]{2,})>$/i";
 
-  // Split multiple addresses and process each.
-  foreach (explode(',', $address) as $email) {
-    $email = trim($email);
-    if (preg_match($regexp, $email, $matches)) {
-      $parsed[] = array('mail' => $matches[2], 'name' => trim($matches[1], '"'));
+  // The display name may contain commas (3.4). Extract all quoted strings
+  // (3.2.4) to a stack and replace them with a placeholder to prevent
+  // splitting at wrong places.
+  $string = preg_replace('/(".*?(?<!\\\\)")/e', '_phpmailer_stack("$1")', $string);
+
+  // Build a regex that matches a name-addr (3.4).
+  // @see valid_email_address()
+  $user = '[a-zA-Z0-9_\-\.\+\^!#\$%&*+\/\=\?\`\|\{\}~\']+';
+  $domain = '(?:(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.?)+';
+  $ipv4 = '[0-9]{1,3}(?:\.[0-9]{1,3}){3}';
+  $ipv6 = '[0-9a-fA-F]{1,4}(?:\:[0-9a-fA-F]{1,4}){7}';
+  $address = "$user@(?:$domain|(?:\[(?:$ipv4|$ipv6)\]))";
+  $adr_rx = "/^(?<name>.*)\s<(?<address>$address)>$/";
+
+  // Split string into multiple parts and process each.
+  foreach (explode(',', $string) as $email) {
+    // Re-inject stripped placeholders.
+    $email = preg_replace('/\x01/e', '_phpmailer_stack()', trim($email));
+    // Check if it's a name-addr or a plain address (3.4).
+    if (preg_match($adr_rx, $email, $matches)) {
+      $parsed[] = array('mail' => $matches['address'], 'name' => $matches['name']);
     }
     else {
-      $parsed[] = array('mail' => $email, 'name' => '');
+      $parsed[] = array('mail' => trim($email, '<>'), 'name' => '');
     }
   }
   return $parsed;
 }
 
 /**
+ * Implements a FIFO stack to store extracted quoted strings.
+ */
+function _phpmailer_stack($string = NULL) {
+  static $stack = array();
+
+  if (!isset($string)) {
+    // Unescape quoted characters (3.2.4) to prevent double escaping.
+    return str_replace(array('\"', '\\\\'), array('"', '\\'), array_shift($stack));
+  }
+  // Remove surrounding quotes and push on stack.
+  array_push($stack, substr($string, 1, -1));
+  // Return placeholder substitution. 0x01 may never appear outside a quoted
+  // string (3.2.3).
+  return "\x01";
+}
+
+/**
  * Menu access callback; Block access to settings page if Mime Mail module is enabled.
  */
 function phpmailer_settings_access() {
