r111832 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r111831‎ | r111832 | r111833 >
Date:15:34, 18 February 2012
Author:hashar
Status:ok (Comments)
Tags:
Comment:
(bug 34421) duplicate Subject / wrong To: headers in mail

This fixup our mail sending system which duplicated the Subject and To: header.
In some conditions it used only the email address for the From: field skipping
the username ($dest in old code only contains the email address).

Mails sent to a single recipients will look alike with mail() or PEAR Mail.
For multiple recipients:
- php mail() will show the recipient email and 'undisclosed-recipients:'
- PEAR Mail will only show 'undisclosed-recipients:'


Reverts r111820
Follow r111819
Fixup r93397
Modified paths:
  • /trunk/phase3/includes/UserMailer.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/UserMailer.php
@@ -163,29 +163,52 @@
164164
165165 wfDebug( __METHOD__ . ': sending mail to ' . implode( ', ', $to ) . "\n" );
166166
167 - $dest = array();
 167+ # Make sure we have at least one address
 168+ $has_address = false;
168169 foreach ( $to as $u ) {
169170 if ( $u->address ) {
170 - $dest[] = $u->address;
 171+ $has_address = true;
 172+ break;
171173 }
172174 }
173 - if ( count( $dest ) == 0 ) {
 175+ if ( !$has_address ) {
174176 return Status::newFatal( 'user-mail-no-addy' );
175177 }
176178
 179+ # Forge email headers
 180+ # -------------------
 181+ #
 182+ # WARNING
 183+ #
 184+ # DO NOT add To: or Subject: headers at this step. They need to be
 185+ # handled differently depending upon the mailer we are going to use.
 186+ #
 187+ # To:
 188+ # PHP mail() first argument is the mail receiver. The argument is
 189+ # used as a recipient destination and as a To header.
 190+ #
 191+ # PEAR mailer has a recipient argument which is only used to
 192+ # send the mail. If no To header is given, PEAR will set it to
 193+ # to 'undisclosed-recipients:'.
 194+ #
 195+ # NOTE: To: is for presentation, the actual recipient is specified
 196+ # by the mailer using the Rcpt-To: header.
 197+ #
 198+ # Subject:
 199+ # PHP mail() second argument to pass the subject, passing a Subject
 200+ # as an additional header will result in a duplicate header.
 201+ #
 202+ # PEAR mailer should be passed a Subject header.
 203+ #
 204+ # -- hashar 20120218
 205+
177206 $headers['From'] = $from->toString();
178207 $headers['Return-Path'] = $from->address;
179 - if ( count( $to ) == 1 ) {
180 - $headers['To'] = $to[0]->toString();
181 - } else {
182 - $headers['To'] = 'undisclosed-recipients:;';
183 - }
184208
185209 if ( $replyto ) {
186210 $headers['Reply-To'] = $replyto->toString();
187211 }
188212
189 - $headers['Subject'] = self::quotedPrintable( $subject );
190213 $headers['Date'] = date( 'r' );
191214 $headers['MIME-Version'] = '1.0';
192215 $headers['Content-type'] = ( is_null( $contentType ) ?
@@ -203,6 +226,10 @@
204227 }
205228
206229 if ( is_array( $wgSMTP ) ) {
 230+ #
 231+ # PEAR MAILER
 232+ #
 233+
207234 if ( function_exists( 'stream_resolve_include_path' ) ) {
208235 $found = stream_resolve_include_path( 'Mail.php' );
209236 } else {
@@ -224,9 +251,20 @@
225252 }
226253
227254 wfDebug( "Sending mail via PEAR::Mail\n" );
228 - $chunks = array_chunk( $dest, $wgEnotifMaxRecips );
 255+
 256+ $headers['Subject'] = self::quotedPrintable( $subject );
 257+
 258+ # When sending only to one recipient, shows it its email using To:
 259+ if ( count( $to ) == 1 ) {
 260+ $headers['To'] = $to[0]->toString();
 261+ }
 262+
 263+ # Split jobs since SMTP servers tends to limit the maximum
 264+ # number of possible recipients.
 265+ $chunks = array_chunk( $to, $wgEnotifMaxRecips );
229266 foreach ( $chunks as $chunk ) {
230267 $status = self::sendWithPear( $mail_object, $chunk, $headers, $body );
 268+ # FIXME : some chunks might be sent while others are not!
231269 if ( !$status->isOK() ) {
232270 wfRestoreWarnings();
233271 return $status;
@@ -235,6 +273,10 @@
236274 wfRestoreWarnings();
237275 return Status::newGood();
238276 } else {
 277+ #
 278+ # PHP mail()
 279+ #
 280+
239281 # Line endings need to be different on Unix and Windows due to
240282 # the bug described at http://trac.wordpress.org/ticket/2603
241283 if ( wfIsWindows() ) {
@@ -244,8 +286,9 @@
245287 $endl = "\n";
246288 }
247289
248 - # Subject header is unneeded since it an argument of mail()
249 - unset( $headers['Subject'] );
 290+ if( count($to) > 1 ) {
 291+ $headers['To'] = 'undisclosed-recipients:;';
 292+ }
250293 $headers = self::arrayToHeaderString( $headers, $endl );
251294
252295 wfDebug( "Sending mail via internal mail() function\n" );
@@ -256,7 +299,7 @@
257300 set_error_handler( 'UserMailer::errorHandler' );
258301
259302 $safeMode = wfIniGetBool( 'safe_mode' );
260 - foreach ( $dest as $recip ) {
 303+ foreach ( $to as $recip ) {
261304 if ( $safeMode ) {
262305 $sent = mail( $recip, self::quotedPrintable( $subject ), $body, $headers );
263306 } else {

Follow-up revisions

RevisionCommit summaryAuthorDate
r111925MFT to 1.19wmf1 r111832...hashar13:32, 20 February 2012
r112027MFT r111580, r111695, r111697, r111832, r112021reedy17:29, 21 February 2012

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r93397Reduce mail header differences by moving all the header creation code...mah16:56, 28 July 2011
r111765(bug 34421) avoid duplicate Subject headers...hashar17:02, 17 February 2012
r111819revert r111765 bug 34421 avoid duplicate Subject headers...hashar10:37, 18 February 2012
r111820(bug 34421) avoid duplicate Subject headers in mail...hashar10:57, 18 February 2012

Comments

#Comment by Aaron Schulz (talk | contribs)   20:45, 19 February 2012

The PEAR and mail() functionality badly needs to be split into separate functions.

There are some interesting other changes here. With the removal of $dest, MailAddress::_toString() is now relied on, which uses "name <addr>" type destinations sometimes instead of just "<addr>". Also $dest was a filtered version of $to, having only addresses corresponding to MailAddress items that had $u->address set. Are you assuming that the filtering was not needed and can be removed? MailAddress::_toString() may give "" in cases that where previously filtered out. Is that OK?

Otherwise looks OK.

#Comment by Hashar (talk | contribs)   12:42, 20 February 2012

> With the removal of $dest, MailAddress::_toString() is now relied on, which uses "name <addr>" type destinations sometimes instead of just "<addr>".

That part is intended, previously PEAR (or maybe it was mail()) did not use the user name as a from.

#Comment by Hashar (talk | contribs)   13:37, 20 February 2012

The $dest filtering was introduced by hexmode. Probably could have left it, but it has no side effect in my testing mail() and PEAR seems to just skip them.

#Comment by Hashar (talk | contribs)   13:36, 20 February 2012

Deployed with r111925

Status & tagging log