* (bug 3407) Fix encoding of subject and from/to headers on notification
authorBrion Vibber <brion@users.mediawiki.org>
Mon, 12 Dec 2005 06:04:45 +0000 (06:04 +0000)
committerBrion Vibber <brion@users.mediawiki.org>
Mon, 12 Dec 2005 06:04:45 +0000 (06:04 +0000)
  mails; userMailer() now takes a MailAddress wrapper object instead of
  a raw string to abstract things a level.

RELEASE-NOTES
includes/SpecialEmailuser.php
includes/User.php
includes/UserMailer.php

index 9b6e16a..37253c3 100644 (file)
@@ -314,6 +314,9 @@ fully support the editing toolbar, but was found to be too confusing.
 * Fix regression: old version missing from edit links on CSS/JS pages
 * (bug 3073) Keep search parameter on paging in Special:Newimages
 * (bug 3211) Include Date, To mail headers when using PEAR::Mail
+* (bug 3407) Fix encoding of subject and from/to headers on notification
+  mails; userMailer() now takes a MailAddress wrapper object instead of
+  a raw string to abstract things a level.
 
 
 === Caveats ===
index 2c6e139..83d02b8 100644 (file)
@@ -46,8 +46,7 @@ function wfSpecialEmailuser( $par ) {
                return;
        }
 
-       $address = $nu->getEmail();
-       $f = new EmailUserForm( $nu->getName() . " <{$address}>", $target );
+       $f = new EmailUserForm( $nu );
 
        if ( "success" == $action ) {
                $f->showSuccess();
@@ -66,13 +65,14 @@ function wfSpecialEmailuser( $par ) {
  */
 class EmailUserForm {
 
-       var $mAddress;
        var $target;
        var $text, $subject;
 
-       function EmailUserForm( $addr, $target ) {
+       /**
+        * @param User $target
+        */
+       function EmailUserForm( $target ) {
                global $wgRequest;
-               $this->mAddress = $addr;
                $this->target = $target;
                $this->text = $wgRequest->getText( 'wpText' );
                $this->subject = $wgRequest->getText( 'wpSubject' );
@@ -91,7 +91,7 @@ class EmailUserForm {
                $emf = wfMsg( "emailfrom" );
                $sender = $wgUser->getName();
                $emt = wfMsg( "emailto" );
-               $rcpt = str_replace( "_", " ", $this->target );
+               $rcpt = $this->target->getName();
                $emr = wfMsg( "emailsubject" );
                $emm = wfMsg( "emailmessage" );
                $ems = wfMsg( "emailsend" );
@@ -99,7 +99,7 @@ class EmailUserForm {
                
                $titleObj = Title::makeTitle( NS_SPECIAL, "Emailuser" );
                $action = $titleObj->escapeLocalURL( "target=" .
-                       urlencode( $this->target ) . "&action=submit" );
+                       urlencode( $this->target->getName() ) . "&action=submit" );
                $token = $wgUser->editToken();
 
                $wgOut->addHTML( "
@@ -129,20 +129,21 @@ class EmailUserForm {
        function doSubmit() {
                global $wgOut, $wgUser;
            
-               $from = wfQuotedPrintable( $wgUser->getName() ) . " <" . $wgUser->getEmail() . ">";
-               $subject = wfQuotedPrintable( $this->subject );
+               $to = new MailAddress( $this->target );
+               $from = new MailAddress( $wgUser );
+               $subject = $this->subject;
                
-               if (wfRunHooks('EmailUser', array(&$this->mAddress, &$from, &$subject, &$this->text))) {
+               if( wfRunHooks( 'EmailUser', array( &$to, &$from, &$subject, &$this->text ) ) ) {
                        
-                       $mailResult = userMailer( $this->mAddress, $from, $subject, $this->text );
+                       $mailResult = userMailer( $to, $from, $subject, $this->text );
                        
                        if( WikiError::isError( $mailResult ) ) {
                                $wgOut->addHTML( wfMsg( "usermailererror" ) . $mailResult);
                        } else {
                                $titleObj = Title::makeTitle( NS_SPECIAL, "Emailuser" );
-                               $encTarget = wfUrlencode( $this->target );
+                               $encTarget = wfUrlencode( $this->target->getName() );
                                $wgOut->redirect( $titleObj->getFullURL( "target={$encTarget}&action=success" ) );
-                               wfRunHooks('EmailUserComplete', array($this->mAddress, $from, $subject, $this->text));
+                               wfRunHooks( 'EmailUserComplete', array( $to, $from, $subject, $this->text ) );
                        }
                }
        }
index f3c3245..1c59a64 100644 (file)
@@ -1701,7 +1701,9 @@ class User {
                }
 
                require_once( 'UserMailer.php' );
-               $error = userMailer( $this->getEmail(), $from, $subject, $body );
+               $to = new MailAddress( $this );
+               $sender = new MailAddress( $from );
+               $error = userMailer( $to, $sender, $subject, $body );
 
                if( $error == '' ) {
                        return true;
index 67c7176..b887b1e 100644 (file)
@@ -35,14 +35,42 @@ function wfRFC822Phrase( $phrase ) {
        return '"' . $phrase . '"';
 }
 
+class MailAddress {
+       /**
+        * @param mixed $address String with an email address, or a User object
+        * @param string $name Human-readable name if a string address is given
+        */
+       function MailAddress( $address, $name=null ) {
+               if( is_object( $address ) && is_a( $address, 'User' ) ) {
+                       $this->address = $address->getEmail();
+                       $this->name = $address->getName();
+               } else {
+                       $this->address = strval( $address );
+                       $this->name = strval( $name );
+               }
+       }
+       
+       /**
+        * Return formatted and quoted address to insert into SMTP headers
+        * @return string
+        */
+       function toString() {
+               if( $this->name != '' ) {
+                       return wfQuotedPrintable( $this->name ) . " <" . $this->address . ">";
+               } else {
+                       return $this->address;
+               }
+       }
+}
+
 /**
  * This function will perform a direct (authenticated) login to
  * a SMTP Server to use for mail relaying if 'wgSMTP' specifies an
  * array of parameters. It requires PEAR:Mail to do that.
  * Otherwise it just uses the standard PHP 'mail' function.
  *
- * @param string $to recipient's email
- * @param string $from sender's email
+ * @param MailAddress $to recipient's email
+ * @param MailAddress $from sender's email
  * @param string $subject email's subject
  * @param string $body email's text
  * @param string $replyto optional reply-to email (default : false)
@@ -54,24 +82,25 @@ function userMailer( $to, $from, $subject, $body, $replyto=false ) {
                require_once( 'Mail.php' );
 
                $timestamp = time();
-
-               $headers['From'] = $from;
-               $headers['To'] = $to;
+               $dest = $to->toString();
+               
+               $headers['From'] = $from->toString();
+               $headers['To'] = $dest;
                if ( $replyto ) {
                        $headers['Reply-To'] = $replyto;
                }
-               $headers['Subject'] = $subject;
+               $headers['Subject'] = wfQuotedPrintable( $subject );
                $headers['Date'] = date( 'r' );
                $headers['MIME-Version'] = '1.0';
                $headers['Content-type'] = 'text/plain; charset='.$wgOutputEncoding;
                $headers['Content-transfer-encoding'] = '8bit';
-               $headers['Message-ID'] = "<{$timestamp}" . $wgUser->getName() . '@' . $wgSMTP['IDHost'] . '>';
+               $headers['Message-ID'] = "<{$timestamp}" . $wgUser->getName() . '@' . $wgSMTP['IDHost'] . '>'; // FIXME
                $headers['X-Mailer'] = 'MediaWiki mailer';
 
                // Create the mail object using the Mail::factory method
                $mail_object =& Mail::factory('smtp', $wgSMTP);
-               wfDebug( "Sending mail via PEAR::Mail to $to\n" );
-               $mailResult =& $mail_object->send($to, $headers, $body);
+               wfDebug( "Sending mail via PEAR::Mail to $dest" );
+               $mailResult =& $mail_object->send($dest, $headers, $body);
 
                # Based on the result return an error string,
                if ($mailResult === true) {
@@ -91,15 +120,17 @@ function userMailer( $to, $from, $subject, $body, $replyto=false ) {
                        "Content-type: text/plain; charset={$wgOutputEncoding}\n" .
                        "Content-Transfer-Encoding: 8bit\n" .
                        "X-Mailer: MediaWiki mailer\n".
-                       'From: ' . $from . "\n";
+                       'From: ' . $from->toString() . "\n";
                if ($replyto) {
                        $headers .= "Reply-To: $replyto\n";
                }
 
+               $dest = $to->toString();
+               
                $wgErrorString = '';
                set_error_handler( 'mailErrorHandler' );
-               wfDebug( "Sending mail via internal mail() function to $to\n" );
-               mail( $to, $subject, $body, $headers );
+               wfDebug( "Sending mail via internal mail() function to $dest\n" );
+               mail( $dest, wfQuotedPrintable( $subject ), $body, $headers );
                restore_error_handler();
 
                if ( $wgErrorString ) {
@@ -306,8 +337,8 @@ class EmailNotification {
                # the user has not opted-out and the option is enabled at the
                # global configuration level.
                $name    = $wgUser->getName();
-               $adminAddress = 'WikiAdmin <' . $wgEmergencyContact . '>';
-               $editorAddress = wfRFC822Phrase( $name ) . ' <' . $wgUser->getEmail() . '>';
+               $adminAddress = new MailAddress( $wgEmergencyContact, 'WikiAdmin' );
+               $editorAddress = new MailAddress( $wgUser );
                if( $wgEnotifRevealEditorAddress
                    && ( $wgUser->getEmail() != '' )
                    && $wgUser->getOption( 'enotifrevealaddr' ) ) {
@@ -362,7 +393,7 @@ class EmailNotification {
                // From the PHP manual:
                //     Note:  The to parameter cannot be an address in the form of "Something <someone@example.com>".
                //     The mail command will not parse this properly while talking with the MTA.
-               $to = $watchingUser->getEmail();
+               $to = new MailAddress( $watchingUser );
                $body = str_replace( '$WATCHINGUSERNAME', $watchingUser->getName() , $this->body );
 
                $timecorrection = $watchingUser->getOption( 'timecorrection' );