<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><style type="text/css"><!--
#msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; }
#msg ul, pre { overflow: auto; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<title>[13456] trunk/wp-includes/pluggable.php: Allow multiple To:
  recipients in wp_mail().</title>
</head>
<body>

<div id="msg">
<dl>
<dt>Revision</dt> <dd><a href="http://trac.wordpress.org/changeset/13456">13456</a></dd>
<dt>Author</dt> <dd>nacin</dd>
<dt>Date</dt> <dd>2010-02-27 16:10:45 +0000 (Sat, 27 Feb 2010)</dd>
</dl>

<h3>Log Message</h3>
<pre>Allow multiple To: recipients in wp_mail(). Improve handling of \r\n in headers and multiple CC/BCC headers. fixes <a href="http://trac.wordpress.org/ticket/10420">#10420</a></pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkwpincludespluggablephp">trunk/wp-includes/pluggable.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkwpincludespluggablephp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/pluggable.php (13455 => 13456)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/pluggable.php        2010-02-27 15:53:06 UTC (rev 13455)
+++ trunk/wp-includes/pluggable.php        2010-02-27 16:10:45 UTC (rev 13456)
</span><span class="lines">@@ -244,7 +244,7 @@
</span><span class="cx">  * @uses PHPMailer
</span><span class="cx">  * @
</span><span class="cx">  *
</span><del>- * @param string $to Email address to send message
</del><ins>+ * @param string|array $to Array or comma-separated list of email addresses to send message.
</ins><span class="cx">  * @param string $subject Email subject
</span><span class="cx">  * @param string $message Message contents
</span><span class="cx">  * @param string|array $headers Optional. Additional headers.
</span><span class="lines">@@ -256,7 +256,7 @@
</span><span class="cx">         extract( apply_filters( 'wp_mail', compact( 'to', 'subject', 'message', 'headers', 'attachments' ) ) );
</span><span class="cx"> 
</span><span class="cx">         if ( !is_array($attachments) )
</span><del>-                $attachments = explode( &quot;\n&quot;, $attachments );
</del><ins>+                $attachments = explode( &quot;\n&quot;, str_replace( &quot;\r\n&quot;, &quot;\n&quot;, $attachments ) );
</ins><span class="cx"> 
</span><span class="cx">         global $phpmailer;
</span><span class="cx"> 
</span><span class="lines">@@ -274,7 +274,7 @@
</span><span class="cx">                 if ( !is_array( $headers ) ) {
</span><span class="cx">                         // Explode the headers out, so this function can take both
</span><span class="cx">                         // string headers and an array of headers.
</span><del>-                        $tempheaders = (array) explode( &quot;\n&quot;, $headers );
</del><ins>+                        $tempheaders = explode( &quot;\n&quot;, str_replace( &quot;\r\n&quot;, &quot;\n&quot;, $headers ) );
</ins><span class="cx">                 } else {
</span><span class="cx">                         $tempheaders = $headers;
</span><span class="cx">                 }
</span><span class="lines">@@ -295,43 +295,49 @@
</span><span class="cx">                                 list( $name, $content ) = explode( ':', trim( $header ), 2 );
</span><span class="cx"> 
</span><span class="cx">                                 // Cleanup crew
</span><del>-                                $name = trim( $name );
</del><ins>+                                $name    = trim( $name    );
</ins><span class="cx">                                 $content = trim( $content );
</span><span class="cx"> 
</span><del>-                                // Mainly for legacy -- process a From: header if it's there
-                                if ( 'from' == strtolower($name) ) {
-                                        if ( strpos($content, '&lt;' ) !== false ) {
-                                                // So... making my life hard again?
-                                                $from_name = substr( $content, 0, strpos( $content, '&lt;' ) - 1 );
-                                                $from_name = str_replace( '&quot;', '', $from_name );
-                                                $from_name = trim( $from_name );
</del><ins>+                                switch ( strtolower( $name ) ) {
+                                        // Mainly for legacy -- process a From: header if it's there
+                                        case 'from':
+                                                if ( strpos($content, '&lt;' ) !== false ) {
+                                                        // So... making my life hard again?
+                                                        $from_name = substr( $content, 0, strpos( $content, '&lt;' ) - 1 );
+                                                        $from_name = str_replace( '&quot;', '', $from_name );
+                                                        $from_name = trim( $from_name );
</ins><span class="cx"> 
</span><del>-                                                $from_email = substr( $content, strpos( $content, '&lt;' ) + 1 );
-                                                $from_email = str_replace( '&gt;', '', $from_email );
-                                                $from_email = trim( $from_email );
-                                        } else {
-                                                $from_email = trim( $content );
-                                        }
-                                } elseif ( 'content-type' == strtolower($name) ) {
-                                        if ( strpos( $content,';' ) !== false ) {
-                                                list( $type, $charset ) = explode( ';', $content );
-                                                $content_type = trim( $type );
-                                                if ( false !== stripos( $charset, 'charset=' ) ) {
-                                                        $charset = trim( str_replace( array( 'charset=', '&quot;' ), '', $charset ) );
-                                                } elseif ( false !== stripos( $charset, 'boundary=' ) ) {
-                                                        $boundary = trim( str_replace( array( 'BOUNDARY=', 'boundary=', '&quot;' ), '', $charset ) );
-                                                        $charset = '';
</del><ins>+                                                        $from_email = substr( $content, strpos( $content, '&lt;' ) + 1 );
+                                                        $from_email = str_replace( '&gt;', '', $from_email );
+                                                        $from_email = trim( $from_email );
+                                                } else {
+                                                        $from_email = trim( $content );
</ins><span class="cx">                                                 }
</span><del>-                                        } else {
-                                                $content_type = trim( $content );
-                                        }
-                                } elseif ( 'cc' == strtolower($name) ) {
-                                        $cc = explode(&quot;,&quot;, $content);
-                                } elseif ( 'bcc' == strtolower($name) ) {
-                                        $bcc = explode(&quot;,&quot;, $content);
-                                } else {
-                                        // Add it to our grand headers array
-                                        $headers[trim( $name )] = trim( $content );
</del><ins>+                                                break;
+                                        case 'content-type':
+                                                if ( strpos( $content, ';' ) !== false ) {
+                                                        list( $type, $charset ) = explode( ';', $content );
+                                                        $content_type = trim( $type );
+                                                        if ( false !== stripos( $charset, 'charset=' ) ) {
+                                                                $charset = trim( str_replace( array( 'charset=', '&quot;' ), '', $charset ) );
+                                                        } elseif ( false !== stripos( $charset, 'boundary=' ) ) {
+                                                                $boundary = trim( str_replace( array( 'BOUNDARY=', 'boundary=', '&quot;' ), '', $charset ) );
+                                                                $charset = '';
+                                                        }
+                                                } else {
+                                                        $content_type = trim( $content );
+                                                }
+                                                break;
+                                        case 'cc':
+                                                $cc = array_merge( (array) $cc, explode( ',', $content ) );
+                                                break;
+                                        case 'bcc':
+                                                $bcc = array_merge( (array) $bcc, explode( ',', $content ) );
+                                                break;
+                                        default:
+                                                // Add it to our grand headers array
+                                                $headers[trim( $name )] = trim( $content );
+                                                break;
</ins><span class="cx">                                 }
</span><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="lines">@@ -348,9 +354,8 @@
</span><span class="cx"> 
</span><span class="cx">         // From email and name
</span><span class="cx">         // If we don't have a name from the input headers
</span><del>-        if ( !isset( $from_name ) ) {
</del><ins>+        if ( !isset( $from_name ) )
</ins><span class="cx">                 $from_name = 'WordPress';
</span><del>-        }
</del><span class="cx"> 
</span><span class="cx">         /* If we don't have an email from the input headers default to wordpress@$sitename
</span><span class="cx">          * Some hosts will block outgoing mail from this address if it doesn't exist but
</span><span class="lines">@@ -370,23 +375,29 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // Plugin authors can override the potentially troublesome default
</span><del>-        $phpmailer-&gt;From = apply_filters( 'wp_mail_from', $from_email );
-        $phpmailer-&gt;FromName = apply_filters( 'wp_mail_from_name', $from_name );
</del><ins>+        $phpmailer-&gt;From     = apply_filters( 'wp_mail_from'     , $from_email );
+        $phpmailer-&gt;FromName = apply_filters( 'wp_mail_from_name', $from_name  );
</ins><span class="cx"> 
</span><del>-        // Set destination address
-        $phpmailer-&gt;AddAddress( $to );
</del><ins>+        // Set destination addresses
+        if ( !is_array( $to ) )
+                $to = explode( ',', $to );
</ins><span class="cx"> 
</span><ins>+        foreach ( (array) $to as $recipient ) {
+                $phpmailer-&gt;AddAddress( trim( $recipient ) );
+        }
+
</ins><span class="cx">         // Set mail's subject and body
</span><span class="cx">         $phpmailer-&gt;Subject = $subject;
</span><del>-        $phpmailer-&gt;Body = $message;
</del><ins>+        $phpmailer-&gt;Body    = $message;
</ins><span class="cx"> 
</span><span class="cx">         // Add any CC and BCC recipients
</span><del>-        if ( !empty($cc) ) {
</del><ins>+        if ( !empty( $cc ) ) {
</ins><span class="cx">                 foreach ( (array) $cc as $recipient ) {
</span><span class="cx">                         $phpmailer-&gt;AddCc( trim($recipient) );
</span><span class="cx">                 }
</span><span class="cx">         }
</span><del>-        if ( !empty($bcc) ) {
</del><ins>+
+        if ( !empty( $bcc ) ) {
</ins><span class="cx">                 foreach ( (array) $bcc as $recipient) {
</span><span class="cx">                         $phpmailer-&gt;AddBcc( trim($recipient) );
</span><span class="cx">                 }
</span><span class="lines">@@ -397,23 +408,20 @@
</span><span class="cx"> 
</span><span class="cx">         // Set Content-Type and charset
</span><span class="cx">         // If we don't have a content-type from the input headers
</span><del>-        if ( !isset( $content_type ) ) {
</del><ins>+        if ( !isset( $content_type ) )
</ins><span class="cx">                 $content_type = 'text/plain';
</span><del>-        }
</del><span class="cx"> 
</span><span class="cx">         $content_type = apply_filters( 'wp_mail_content_type', $content_type );
</span><span class="cx"> 
</span><span class="cx">         $phpmailer-&gt;ContentType = $content_type;
</span><span class="cx"> 
</span><span class="cx">         // Set whether it's plaintext, depending on $content_type
</span><del>-        if ( $content_type == 'text/html' ) {
</del><ins>+        if ( 'text/html' == $content_type )
</ins><span class="cx">                 $phpmailer-&gt;IsHTML( true );
</span><del>-        }
</del><span class="cx"> 
</span><span class="cx">         // If we don't have a charset from the input headers
</span><del>-        if ( !isset( $charset ) ) {
</del><ins>+        if ( !isset( $charset ) )
</ins><span class="cx">                 $charset = get_bloginfo( 'charset' );
</span><del>-        }
</del><span class="cx"> 
</span><span class="cx">         // Set the content-type and charset
</span><span class="cx">         $phpmailer-&gt;CharSet = apply_filters( 'wp_mail_charset', $charset );
</span><span class="lines">@@ -423,9 +431,9 @@
</span><span class="cx">                 foreach( (array) $headers as $name =&gt; $content ) {
</span><span class="cx">                         $phpmailer-&gt;AddCustomHeader( sprintf( '%1$s: %2$s', $name, $content ) );
</span><span class="cx">                 }
</span><del>-                if ( false !== stripos( $content_type, 'multipart' ) &amp;&amp; ! empty($boundary) ) {
</del><ins>+
+                if ( false !== stripos( $content_type, 'multipart' ) &amp;&amp; ! empty($boundary) )
</ins><span class="cx">                         $phpmailer-&gt;AddCustomHeader( sprintf( &quot;Content-Type: %s;\n\t boundary=\&quot;%s\&quot;&quot;, $content_type, $boundary ) );
</span><del>-                }
</del><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if ( !empty( $attachments ) ) {
</span></span></pre>
</div>
</div>

</body>
</html>