diff options
Diffstat (limited to 'includes/UserMailer.php')
-rw-r--r-- | includes/UserMailer.php | 183 |
1 files changed, 106 insertions, 77 deletions
diff --git a/includes/UserMailer.php b/includes/UserMailer.php index c15843d9..5976c6fd 100644 --- a/includes/UserMailer.php +++ b/includes/UserMailer.php @@ -31,7 +31,7 @@ */ class MailAddress { /** - * @param $address Mixed: string with an email address, or a User object + * @param $address string|User string with an email address, or a User object * @param $name String: human-readable name if a string address is given * @param $realName String: human-readable real name if a string address is given */ @@ -55,16 +55,18 @@ class MailAddress { # PHP's mail() implementation under Windows is somewhat shite, and # can't handle "Joe Bloggs <joe@bloggs.com>" format email addresses, # so don't bother generating them - if ( $this->name != '' && !wfIsWindows() ) { - global $wgEnotifUseRealName; - $name = ( $wgEnotifUseRealName && $this->realName ) ? $this->realName : $this->name; - $quoted = wfQuotedPrintable( $name ); - if ( strpos( $quoted, '.' ) !== false || strpos( $quoted, ',' ) !== false ) { - $quoted = '"' . $quoted . '"'; + if ( $this->address ) { + if ( $this->name != '' && !wfIsWindows() ) { + global $wgEnotifUseRealName; + $name = ( $wgEnotifUseRealName && $this->realName ) ? $this->realName : $this->name; + $quoted = UserMailer::quotedPrintable( $name ); + if ( strpos( $quoted, '.' ) !== false || strpos( $quoted, ',' ) !== false ) { + $quoted = '"' . $quoted . '"'; + } + return "$quoted <{$this->address}>"; + } else { + return $this->address; } - return "$quoted <{$this->address}>"; - } else { - return $this->address; } } @@ -82,6 +84,13 @@ class UserMailer { /** * Send mail using a PEAR mailer + * + * @param $mailer + * @param $dest + * @param $headers + * @param $body + * + * @return Status */ protected static function sendWithPear( $mailer, $dest, $headers, $body ) { $mailResult = $mailer->send( $dest, $headers, $body ); @@ -106,14 +115,15 @@ class UserMailer { * @param $subject String: email's subject. * @param $body String: email's text. * @param $replyto MailAddress: optional reply-to email (default: null). - * @param $contentType String: optional custom Content-Type + * @param $contentType String: optional custom Content-Type (default: text/plain; charset=UTF-8) * @return Status object */ - public static function send( $to, $from, $subject, $body, $replyto = null, $contentType = null ) { - global $wgSMTP, $wgOutputEncoding, $wgEnotifImpersonal; + public static function send( $to, $from, $subject, $body, $replyto = null, $contentType = 'text/plain; charset=UTF-8') { + global $wgSMTP, $wgEnotifImpersonal; global $wgEnotifMaxRecips, $wgAdditionalMailParams; if ( is_array( $to ) ) { + $emails = ''; // This wouldn't be necessary if implode() worked on arrays of // objects using __toString(). http://bugs.php.net/bug.php?id=36612 foreach ( $to as $t ) { @@ -126,13 +136,10 @@ class UserMailer { } if ( is_array( $wgSMTP ) ) { - $found = false; - $pathArray = explode( PATH_SEPARATOR, get_include_path() ); - foreach ( $pathArray as $path ) { - if ( file_exists( $path . DIRECTORY_SEPARATOR . 'Mail.php' ) ) { - $found = true; - break; - } + if ( function_exists( 'stream_resolve_include_path' ) ) { + $found = stream_resolve_include_path( 'Mail.php' ); + } else { + $found = Fallback::stream_resolve_include_path( 'Mail.php' ); } if ( !$found ) { throw new MWException( 'PEAR mail package is not installed' ); @@ -140,17 +147,21 @@ class UserMailer { require_once( 'Mail.php' ); $msgid = str_replace( " ", "_", microtime() ); - if ( function_exists( 'posix_getpid' ) ) + if ( function_exists( 'posix_getpid' ) ) { $msgid .= '.' . posix_getpid(); + } if ( is_array( $to ) ) { $dest = array(); - foreach ( $to as $u ) + foreach ( $to as $u ) { $dest[] = $u->address; - } else + } + } else { $dest = $to->address; + } $headers['From'] = $from->toString(); + $headers['Return-Path'] = $from->toString(); if ( $wgEnotifImpersonal ) { $headers['To'] = 'undisclosed-recipients:;'; @@ -162,13 +173,14 @@ class UserMailer { if ( $replyto ) { $headers['Reply-To'] = $replyto->toString(); } - $headers['Subject'] = wfQuotedPrintable( $subject ); + $headers['Subject'] = self::quotedPrintable( $subject ); $headers['Date'] = date( 'r' ); $headers['MIME-Version'] = '1.0'; $headers['Content-type'] = ( is_null( $contentType ) ? - 'text/plain; charset=' . $wgOutputEncoding : $contentType ); + 'text/plain; charset=UTF-8' : $contentType ); $headers['Content-transfer-encoding'] = '8bit'; - $headers['Message-ID'] = "<$msgid@" . $wgSMTP['IDHost'] . '>'; // FIXME + // @todo FIXME + $headers['Message-ID'] = "<$msgid@" . $wgSMTP['IDHost'] . '>'; $headers['X-Mailer'] = 'MediaWiki mailer'; wfSuppressWarnings(); @@ -193,9 +205,6 @@ class UserMailer { wfRestoreWarnings(); return Status::newGood(); } else { - # In the following $headers = expression we removed "Reply-To: {$from}\r\n" , because it is treated differently - # (fifth parameter of the PHP mail function, see some lines below) - # Line endings need to be different on Unix and Windows due to # the bug described at http://trac.wordpress.org/ticket/2603 if ( wfIsWindows() ) { @@ -204,31 +213,32 @@ class UserMailer { } else { $endl = "\n"; } - $ctype = ( is_null( $contentType ) ? - 'text/plain; charset=' . $wgOutputEncoding : $contentType ); - $headers = - "MIME-Version: 1.0$endl" . - "Content-type: $ctype$endl" . - "Content-Transfer-Encoding: 8bit$endl" . - "X-Mailer: MediaWiki mailer$endl" . - 'From: ' . $from->toString(); + + $headers = array( + "MIME-Version: 1.0", + "Content-type: $contentType", + "Content-Transfer-Encoding: 8bit", + "X-Mailer: MediaWiki mailer", + "From: " . $from->toString(), + ); if ( $replyto ) { - $headers .= "{$endl}Reply-To: " . $replyto->toString(); + $headers[] = "Reply-To: " . $replyto->toString(); } + $headers = implode( $endl, $headers ); + wfDebug( "Sending mail via internal mail() function\n" ); self::$mErrorString = ''; $html_errors = ini_get( 'html_errors' ); ini_set( 'html_errors', '0' ); - set_error_handler( array( 'UserMailer', 'errorHandler' ) ); + set_error_handler( 'UserMailer::errorHandler' ); - if ( is_array( $to ) ) { - foreach ( $to as $recip ) { - $sent = mail( $recip->toString(), wfQuotedPrintable( $subject ), $body, $headers, $wgAdditionalMailParams ); - } - } else { - $sent = mail( $to->toString(), wfQuotedPrintable( $subject ), $body, $headers, $wgAdditionalMailParams ); + if ( !is_array( $to ) ) { + $to = array( $to ); + } + foreach ( $to as $recip ) { + $sent = mail( $recip->toString(), self::quotedPrintable( $subject ), $body, $headers, $wgAdditionalMailParams ); } restore_error_handler(); @@ -259,11 +269,41 @@ class UserMailer { /** * Converts a string into a valid RFC 822 "phrase", such as is used for the sender name + * @param $phrase string + * @return string */ public static function rfc822Phrase( $phrase ) { $phrase = strtr( $phrase, array( "\r" => '', "\n" => '', '"' => '' ) ); return '"' . $phrase . '"'; } + + /** + * Converts a string into quoted-printable format + * @since 1.17 + */ + public static function quotedPrintable( $string, $charset = '' ) { + # Probably incomplete; see RFC 2045 + if( empty( $charset ) ) { + $charset = 'UTF-8'; + } + $charset = strtoupper( $charset ); + $charset = str_replace( 'ISO-8859', 'ISO8859', $charset ); // ? + + $illegal = '\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\xff='; + $replace = $illegal . '\t ?_'; + if( !preg_match( "/[$illegal]/", $string ) ) { + return $string; + } + $out = "=?$charset?Q?"; + $out .= preg_replace_callback( "/([$replace])/", + array( __CLASS__, 'quotedPrintableCallback' ), $string ); + $out .= '?='; + return $out; + } + + protected static function quotedPrintableCallback( $matches ) { + return sprintf( "=%02X", ord( $matches[1] ) ); + } } /** @@ -307,8 +347,9 @@ class EmailNotification { public function notifyOnPageChange( $editor, $title, $timestamp, $summary, $minorEdit, $oldid = false ) { global $wgEnotifUseJobQ, $wgEnotifWatchlist, $wgShowUpdatedMarker; - if ( $title->getNamespace() < 0 ) + if ( $title->getNamespace() < 0 ) { return; + } // Build a list of users to notfiy $watchers = array(); @@ -360,7 +401,7 @@ class EmailNotification { } - /* + /** * Immediate version of notifyOnPageChange(). * * Send emails corresponding to the user $editor editing the page $title. @@ -404,7 +445,9 @@ class EmailNotification { wfDebug( __METHOD__ . ": user talk page edited, but user does not exist\n" ); } elseif ( $targetUser->getId() == $editor->getId() ) { wfDebug( __METHOD__ . ": user edited their own talk page, no notification sent\n" ); - } elseif ( $targetUser->getOption( 'enotifusertalkpages' ) ) { + } elseif ( $targetUser->getOption( 'enotifusertalkpages' ) && + ( !$minorEdit || $targetUser->getOption( 'enotifminoredits' ) ) ) + { if ( $targetUser->isEmailConfirmed() ) { wfDebug( __METHOD__ . ": sending talk page update notification\n" ); $this->compose( $targetUser ); @@ -466,7 +509,7 @@ class EmailNotification { $keys = array(); if ( $this->oldid ) { - $difflink = $this->title->getFullUrl( 'diff=0&oldid=' . $this->oldid ); + $difflink = $this->title->getCanonicalUrl( 'diff=0&oldid=' . $this->oldid ); $keys['$NEWPAGE'] = wfMsgForContent( 'enotif_lastvisited', $difflink ); $keys['$OLDID'] = $this->oldid; $keys['$CHANGEDORCREATED'] = wfMsgForContent( 'changed' ); @@ -478,22 +521,22 @@ class EmailNotification { } if ( $wgEnotifImpersonal && $this->oldid ) { - /* + /** * For impersonal mail, show a diff link to the last * revision. */ $keys['$NEWPAGE'] = wfMsgForContent( 'enotif_lastdiff', - $this->title->getFullURL( "oldid={$this->oldid}&diff=next" ) ); - } + $this->title->getCanonicalUrl( "oldid={$this->oldid}&diff=next" ) ); + } $body = strtr( $body, $keys ); $pagetitle = $this->title->getPrefixedText(); $keys['$PAGETITLE'] = $pagetitle; - $keys['$PAGETITLE_URL'] = $this->title->getFullUrl(); + $keys['$PAGETITLE_URL'] = $this->title->getCanonicalUrl(); $keys['$PAGEMINOREDIT'] = $medit; $keys['$PAGESUMMARY'] = $summary; - $keys['$UNWATCHURL'] = $this->title->getFullUrl( 'action=unwatch' ); + $keys['$UNWATCHURL'] = $this->title->getCanonicalUrl( 'action=unwatch' ); $subject = strtr( $subject, $keys ); @@ -505,8 +548,8 @@ class EmailNotification { $adminAddress = new MailAddress( $wgPasswordSender, $wgPasswordSenderName ); $editorAddress = new MailAddress( $editor ); if ( $wgEnotifRevealEditorAddress - && ( $editor->getEmail() != '' ) - && $editor->getOption( 'enotifrevealaddr' ) ) { + && ( $editor->getEmail() != '' ) + && $editor->getOption( 'enotifrevealaddr' ) ) { if ( $wgEnotifFromEditor ) { $from = $editorAddress; } else { @@ -518,7 +561,7 @@ class EmailNotification { $replyto = new MailAddress( $wgNoReplyAddress ); } - if ( $editor->isIP( $name ) ) { + if ( $editor->isAnon() ) { # real anon (user:xxx.xxx.xxx.xxx) $utext = wfMsgForContent( 'enotif_anon_editor', $name ); $subject = str_replace( '$PAGEEDITOR', $utext, $subject ); @@ -528,10 +571,10 @@ class EmailNotification { $subject = str_replace( '$PAGEEDITOR', $name, $subject ); $keys['$PAGEEDITOR'] = $name; $emailPage = SpecialPage::getSafeTitleFor( 'Emailuser', $name ); - $keys['$PAGEEDITOR_EMAIL'] = $emailPage->getFullUrl(); + $keys['$PAGEEDITOR_EMAIL'] = $emailPage->getCanonicalUrl(); } $userPage = $editor->getUserPage(); - $keys['$PAGEEDITOR_WIKI'] = $userPage->getFullUrl(); + $keys['$PAGEEDITOR_WIKI'] = $userPage->getCanonicalUrl(); $body = strtr( $body, $keys ); $body = wordwrap( $body, 72 ); @@ -618,28 +661,14 @@ class EmailNotification { $body = str_replace( array( '$WATCHINGUSERNAME', - '$PAGEEDITDATE' ), + '$PAGEEDITDATE', + '$PAGEEDITTIME' ), array( wfMsgForContent( 'enotif_impersonal_salutation' ), - $wgContLang->timeanddate( $this->timestamp, true, false, false ) ), + $wgContLang->date( $this->timestamp, true, false, false ), + $wgContLang->time( $this->timestamp, true, false, false ) ), $this->body ); return UserMailer::send( $addresses, $this->from, $this->subject, $body, $this->replyto ); } } # end of class EmailNotification - -/**@{ - * Backwards compatibility functions - * - * @deprecated Use UserMailer methods; will be removed in 1.19 - */ -function wfRFC822Phrase( $s ) { - wfDeprecated( __FUNCTION__ ); - return UserMailer::rfc822Phrase( $s ); -} - -function userMailer( $to, $from, $subject, $body, $replyto = null ) { - wfDeprecated( __FUNCTION__ ); - return UserMailer::send( $to, $from, $subject, $body, $replyto ); -} -/**@}*/
\ No newline at end of file |