r21897 - Code Review

From MediaWiki.org

Jump to: navigation, search
Repository:MediaWiki
Revision:r21896 | r21897 (on ViewVC) | r21898 >
Date:12:08, 5 May 2007
Author:river
Status:new
Tags:
Comment:enotif should have a way to send bulk mail without customisations, for large sites
Modified paths:

Diff [purge]

Index: trunk/phase3/includes/UserMailer.php
===================================================================
--- trunk/phase3/includes/UserMailer.php	(revision 21896)
+++ trunk/phase3/includes/UserMailer.php	(revision 21897)
@@ -72,6 +72,22 @@
 	}
 }
 
+function send_mail($mailer, $dest, $headers, $body)
+{
+	$mailResult =& $mailer->send($dest, $headers, $body);
+
+	# Based on the result return an error string,
+	if ($mailResult === true) {
+		return '';
+	} elseif (is_object($mailResult)) {
+		wfDebug( "PEAR::Mail failed: " . $mailResult->getMessage() . "\n" );
+		return $mailResult->getMessage();
+	} else {
+		wfDebug( "PEAR::Mail failed, unknown error result\n" );
+		return 'Mail object return unknown error.';
+	}
+}
+
 /**
  * This function will perform a direct (authenticated) login to
  * a SMTP Server to use for mail relaying if 'wgSMTP' specifies an
@@ -85,16 +101,28 @@
  * @param $replyto String: optional reply-to email (default: null).
  */
 function userMailer( $to, $from, $subject, $body, $replyto=null ) {
-	global $wgUser, $wgSMTP, $wgOutputEncoding, $wgErrorString;
+	global $wgUser, $wgSMTP, $wgOutputEncoding, $wgErrorString, $wgEnotifImpersonal;
+	global $wgEnotifMaxRecips;
 
 	if (is_array( $wgSMTP )) {
 		require_once( 'Mail.php' );
 
 		$timestamp = time();
-		$dest = $to->address;
 
+		if (is_array($to)) {
+			$dest = array();
+			foreach ($to as $u)
+				$dest[] = $u->address;
+		} else
+			$dest = $to->address;
+
 		$headers['From'] = $from->toString();
-		$headers['To'] = $to->toString();
+
+		if ($wgEnotifImpersonal)
+			$headers['To'] = 'undisclosed-recipients:;';
+		else
+			$headers['To'] = $to->toString();
+
 		if ( $replyto ) {
 			$headers['Reply-To'] = $replyto->toString();
 		}
@@ -114,18 +142,16 @@
 		}
 
 		wfDebug( "Sending mail via PEAR::Mail to $dest\n" );
-		$mailResult =& $mail_object->send($dest, $headers, $body);
+		if (is_array($dest)) {
+			$chunks = array_chunk($dest, $wgEnotifMaxRecips);
+			foreach ($chunks as $chunk) {
+				$e = send_mail($mail_object, $dest, $headers, $body);
+				if ($e != '')
+					return $e;
+			}
+		} else
+			return $mail_object->send($dest, $headers, $body);
 
-		# Based on the result return an error string,
-		if ($mailResult === true) {
-			return '';
-		} elseif (is_object($mailResult)) {
-			wfDebug( "PEAR::Mail failed: " . $mailResult->getMessage() . "\n" );
-			return $mailResult->getMessage();
-		} else {
-			wfDebug( "PEAR::Mail failed, unknown error result\n" );
-			return 'Mail object return unknown error.';
-		}
 	} 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)
@@ -217,6 +243,7 @@
 		# we use $wgEmergencyContact as sender's address
 		global $wgUser, $wgEnotifWatchlist;
 		global $wgEnotifMinorEdits, $wgEnotifUserTalk, $wgShowUpdatedMarker;
+		global $wgEnotifImpersonal;
 
 		$fname = 'UserMailer::notifyOnPageChange';
 		wfProfileIn( $fname );
@@ -236,6 +263,8 @@
 		$this->oldid = $oldid;
 		$this->composeCommonMailtext();
 
+		$impersonals = array();
+
 		if ( (!$minorEdit || $wgEnotifMinorEdits) ) {
 			if( $wgEnotifWatchlist ) {
 				// Send updates to watchers other than the current editor
@@ -287,7 +316,10 @@
 						&& ($watchingUser->isEmailConfirmed() ) ) {
 							# ... adjust remaining text and page edit time placeholders
 							# which needs to be personalized for each user
-							$this->composeAndSendPersonalisedMail( $watchingUser );
+							if ($wgEnotifImpersonal)
+								$impersonals[] = $watchingUser;
+							else
+								$this->composeAndSendPersonalisedMail( $watchingUser );
 
 						} # if the watching user has an email address in the preferences
 					}
@@ -298,9 +330,14 @@
 		global $wgUsersNotifedOnAllChanges;
 		foreach ( $wgUsersNotifedOnAllChanges as $name ) {
 			$user = User::newFromName( $name );
-			$this->composeAndSendPersonalisedMail( $user );
+			if ($wgEnotifImpersonal)
+				$impersonals[] = $user;
+			else
+				$this->composeAndSendPersonalisedMail( $user );
 		}
 
+		$this->composeAndSendImpersonalMail($impersonals);
+
 		if ( $wgShowUpdatedMarker || $wgEnotifWatchlist ) {
 			# mark the changed watch-listed page with a timestamp, so that the page is
 			# listed with an "updated since your last visit" icon in the watch list, ...
@@ -324,6 +361,7 @@
 	function composeCommonMailtext() {
 		global $wgUser, $wgEmergencyContact, $wgNoReplyAddress;
 		global $wgEnotifFromEditor, $wgEnotifRevealEditorAddress;
+		global $wgEnotifImpersonal;
 
 		$summary = ($this->summary == '') ? ' - ' : $this->summary;
 		$medit   = ($this->minorEdit) ? wfMsg( 'minoredit' ) : '';
@@ -353,6 +391,14 @@
 			$keys['$CHANGEDORCREATED'] = wfMsgForContent( 'created' );
 		}
 
+		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=prev"));
+
 		$body = strtr( $body, $keys );
 		$pagetitle = $this->title->getPrefixedText();
 		$keys['$PAGETITLE']          = $pagetitle;
@@ -406,8 +452,6 @@
 		$this->body    = $body;
 	}
 
-
-
 	/**
 	 * Does the per-user customizations to a notification e-mail (name,
 	 * timestamp in proper timezone, etc) and sends it out.
@@ -439,5 +483,29 @@
 		return ($error == '');
 	}
 
+	/**
+	 * Same as composeAndSendPersonalisedMail but does impersonal mail 
+	 * suitable for bulk mailing.  Takes an array of users.
+	 */
+	function composeAndSendImpersonalMail($users) {
+		global $wgLang;
+
+		if (empty($users))
+			return;
+
+		$to = array();
+		foreach ($users as $user)
+			$to[] = new MailAddress($user);
+
+		$body = str_replace(
+				array(	'$WATCHINGUSERNAME',
+					'$PAGEEDITDATE'),
+				array(	wfMsgForContent('enotif_impersonal_salutation'),
+					$wgLang->timeanddate($this->timestamp, true, false, false)),
+				$this->body);
+		$error = userMailer($to, $this->from, $this->subject, $body, $this->replyto);
+		return $error == '';
+	}
+
 } # end of class EmailNotification
 ?>
Index: trunk/phase3/includes/DefaultSettings.php
===================================================================
--- trunk/phase3/includes/DefaultSettings.php	(revision 21896)
+++ trunk/phase3/includes/DefaultSettings.php	(revision 21897)
@@ -1174,6 +1174,18 @@
 $wgEnotifMinorEdits		= true;	# UPO; false: "minor edits" on pages do not trigger notification mails.
 #							# Attention: _every_ change on a user_talk page trigger a notification mail (if the user is not yet notified)
 
+# Send a generic mail instead of a personalised mail for each user.  This
+# always uses UTC as the time zone, and doesn't include the username.
+#
+# For pages with many users watching, this can significantly reduce mail load.
+# Has no effect when using sendmail rather than SMTP;
+
+$wgEnotifImpersonal = true;
+
+# Maximum number of users to mail at once when using impersonal mail.  Should 
+# match the limit on your mail server.
+$wgEnotifMaxRecips = 500;
+
 /** 
  * Array of usernames who will be sent a notification email for every change which occurs on a wiki
  */
Index: trunk/phase3/languages/messages/MessagesEn.php
===================================================================
--- trunk/phase3/languages/messages/MessagesEn.php	(revision 21896)
+++ trunk/phase3/languages/messages/MessagesEn.php	(revision 21897)
@@ -1750,13 +1750,15 @@
 'enotif_mailer' 		=> '{{SITENAME}} Notification Mailer',
 'enotif_reset'			=> 'Mark all pages visited',
 'enotif_newpagetext'=> 'This is a new page.',
+'enotif_impersonal_salutation'	=> '{{SITENAME}} user',
 'changed'			=> 'changed',
 'created'			=> 'created',
 'enotif_subject' 	=> '{{SITENAME}} page $PAGETITLE has been $CHANGEDORCREATED by $PAGEEDITOR',
 'enotif_lastvisited' => 'See $1 for all changes since your last visit.',
+'enotif_lastdiff' => 'See $1 to view this change.',
 'enotif_body' => 'Dear $WATCHINGUSERNAME,
 
-the {{SITENAME}} page $PAGETITLE has been $CHANGEDORCREATED on $PAGEEDITDATE by $PAGEEDITOR, see $PAGETITLE_URL for the current version.
+The {{SITENAME}} page $PAGETITLE has been $CHANGEDORCREATED on $PAGEEDITDATE by $PAGEEDITOR, see $PAGETITLE_URL for the current version.
 
 $NEWPAGE
 
Views
Toolbox