Index: trunk/phase3/includes/UserMailer.php
@@ -72,6 +72,22 @@
73
73
74
74
75
75
76
+function send_mail($mailer, $dest, $headers, $body)
77
+{
78
+ $mailResult =& $mailer->send($dest, $headers, $body);
79
80
+ # Based on the result return an error string,
81
+ if ($mailResult === true) {
82
+ return '';
83
+ } elseif (is_object($mailResult)) {
84
+ wfDebug( "PEAR::Mail failed: " . $mailResult->getMessage() . "\n" );
85
+ return $mailResult->getMessage();
86
+ } else {
87
+ wfDebug( "PEAR::Mail failed, unknown error result\n" );
88
+ return 'Mail object return unknown error.';
89
+ }
90
+}
91
76
92
/**
77
93
* This function will perform a direct (authenticated) login to
78
94
* a SMTP Server to use for mail relaying if 'wgSMTP' specifies an
@@ -85,16 +101,28 @@
86
102
* @param $replyto String: optional reply-to email (default: null).
87
103
*/
88
104
function userMailer( $to, $from, $subject, $body, $replyto=null ) {
89
- global $wgUser, $wgSMTP, $wgOutputEncoding, $wgErrorString;
105
+ global $wgUser, $wgSMTP, $wgOutputEncoding, $wgErrorString, $wgEnotifImpersonal;
106
+ global $wgEnotifMaxRecips;
90
107
91
108
if (is_array( $wgSMTP )) {
92
109
require_once( 'Mail.php' );
93
110
94
111
$timestamp = time();
95
- $dest = $to->address;
96
112
113
+ if (is_array($to)) {
114
+ $dest = array();
115
+ foreach ($to as $u)
116
+ $dest[] = $u->address;
117
+ } else
118
+ $dest = $to->address;
119
97
120
$headers['From'] = $from->toString();
98
- $headers['To'] = $to->toString();
121
122
+ if ($wgEnotifImpersonal)
123
+ $headers['To'] = 'undisclosed-recipients:;';
124
+ else
125
+ $headers['To'] = $to->toString();
126
99
127
if ( $replyto ) {
100
128
$headers['Reply-To'] = $replyto->toString();
101
129
@@ -114,18 +142,16 @@
115
143
116
144
117
145
wfDebug( "Sending mail via PEAR::Mail to $dest\n" );
118
- $mailResult =& $mail_object->send($dest, $headers, $body);
146
+ if (is_array($dest)) {
147
+ $chunks = array_chunk($dest, $wgEnotifMaxRecips);
148
+ foreach ($chunks as $chunk) {
149
+ $e = send_mail($mail_object, $dest, $headers, $body);
150
+ if ($e != '')
151
+ return $e;
152
+ }
153
+ } else
154
+ return $mail_object->send($dest, $headers, $body);
119
155
120
- # Based on the result return an error string,
121
- if ($mailResult === true) {
122
- return '';
123
- } elseif (is_object($mailResult)) {
124
- wfDebug( "PEAR::Mail failed: " . $mailResult->getMessage() . "\n" );
125
- return $mailResult->getMessage();
126
- } else {
127
- wfDebug( "PEAR::Mail failed, unknown error result\n" );
128
- return 'Mail object return unknown error.';
129
- }
130
156
} else {
131
157
# In the following $headers = expression we removed "Reply-To: {$from}\r\n" , because it is treated differently
132
158
# (fifth parameter of the PHP mail function, see some lines below)
@@ -217,6 +243,7 @@
218
244
# we use $wgEmergencyContact as sender's address
219
245
global $wgUser, $wgEnotifWatchlist;
220
246
global $wgEnotifMinorEdits, $wgEnotifUserTalk, $wgShowUpdatedMarker;
247
+ global $wgEnotifImpersonal;
221
248
222
249
$fname = 'UserMailer::notifyOnPageChange';
223
250
wfProfileIn( $fname );
@@ -236,6 +263,8 @@
237
264
$this->oldid = $oldid;
238
265
$this->composeCommonMailtext();
239
266
267
+ $impersonals = array();
268
240
269
if ( (!$minorEdit || $wgEnotifMinorEdits) ) {
241
270
if( $wgEnotifWatchlist ) {
242
271
// Send updates to watchers other than the current editor
@@ -287,7 +316,10 @@
288
317
&& ($watchingUser->isEmailConfirmed() ) ) {
289
318
# ... adjust remaining text and page edit time placeholders
290
319
# which needs to be personalized for each user
291
- $this->composeAndSendPersonalisedMail( $watchingUser );
320
+ if ($wgEnotifImpersonal)
321
+ $impersonals[] = $watchingUser;
322
+ else
323
+ $this->composeAndSendPersonalisedMail( $watchingUser );
292
324
293
325
} # if the watching user has an email address in the preferences
294
326
@@ -298,9 +330,14 @@
299
331
global $wgUsersNotifedOnAllChanges;
300
332
foreach ( $wgUsersNotifedOnAllChanges as $name ) {
301
333
$user = User::newFromName( $name );
302
- $this->composeAndSendPersonalisedMail( $user );
334
+ if ($wgEnotifImpersonal)
335
+ $impersonals[] = $user;
336
+ else
337
+ $this->composeAndSendPersonalisedMail( $user );
303
338
304
339
340
+ $this->composeAndSendImpersonalMail($impersonals);
341
305
342
if ( $wgShowUpdatedMarker || $wgEnotifWatchlist ) {
306
343
# mark the changed watch-listed page with a timestamp, so that the page is
307
344
# listed with an "updated since your last visit" icon in the watch list, ...
@@ -324,6 +361,7 @@
325
362
function composeCommonMailtext() {
326
363
global $wgUser, $wgEmergencyContact, $wgNoReplyAddress;
327
364
global $wgEnotifFromEditor, $wgEnotifRevealEditorAddress;
365
+ global $wgEnotifImpersonal;
328
366
329
367
$summary = ($this->summary == '') ? ' - ' : $this->summary;
330
368
$medit = ($this->minorEdit) ? wfMsg( 'minoredit' ) : '';
@@ -353,6 +391,14 @@
354
392
$keys['$CHANGEDORCREATED'] = wfMsgForContent( 'created' );
355
393
356
394
395
+ if ($wgEnotifImpersonal && $this->oldid)
396
+ /*
397
+ * For impersonal mail, show a diff link to the last
398
+ * revision.
399
+ */
400
+ $keys['$NEWPAGE'] = wfMsgForContent('enotif_lastdiff',
401
+ $this->title->getFullURL("oldid={$this->oldid}&diff=prev"));
402
357
403
$body = strtr( $body, $keys );
358
404
$pagetitle = $this->title->getPrefixedText();
359
405
$keys['$PAGETITLE'] = $pagetitle;
@@ -406,8 +452,6 @@
407
453
$this->body = $body;
408
454
409
455
410
411
412
456
/**
413
457
* Does the per-user customizations to a notification e-mail (name,
414
458
* timestamp in proper timezone, etc) and sends it out.
@@ -439,5 +483,29 @@
440
484
return ($error == '');
441
485
442
486
487
+ /**
488
+ * Same as composeAndSendPersonalisedMail but does impersonal mail
489
+ * suitable for bulk mailing. Takes an array of users.
490
+ */
491
+ function composeAndSendImpersonalMail($users) {
492
+ global $wgLang;
493
494
+ if (empty($users))
495
+ return;
496
497
+ $to = array();
498
+ foreach ($users as $user)
499
+ $to[] = new MailAddress($user);
500
501
+ $body = str_replace(
502
+ array( '$WATCHINGUSERNAME',
503
+ '$PAGEEDITDATE'),
504
+ array( wfMsgForContent('enotif_impersonal_salutation'),
505
+ $wgLang->timeanddate($this->timestamp, true, false, false)),
506
+ $this->body);
507
+ $error = userMailer($to, $this->from, $this->subject, $body, $this->replyto);
508
+ return $error == '';
509
+ }
510
443
511
} # end of class EmailNotification
444
512
?>
Index: trunk/phase3/includes/DefaultSettings.php
@@ -1174,6 +1174,18 @@
1175
1175
$wgEnotifMinorEdits = true; # UPO; false: "minor edits" on pages do not trigger notification mails.
1176
1176
# # Attention: _every_ change on a user_talk page trigger a notification mail (if the user is not yet notified)
1177
1177
1178
+# Send a generic mail instead of a personalised mail for each user. This
1179
+# always uses UTC as the time zone, and doesn't include the username.
1180
+#
1181
+# For pages with many users watching, this can significantly reduce mail load.
1182
+# Has no effect when using sendmail rather than SMTP;
1183
1184
+$wgEnotifImpersonal = true;
1185
1186
+# Maximum number of users to mail at once when using impersonal mail. Should
1187
+# match the limit on your mail server.
1188
+$wgEnotifMaxRecips = 500;
1189
1178
1190
/**
1179
1191
* Array of usernames who will be sent a notification email for every change which occurs on a wiki
1180
1192
*/
Index: trunk/phase3/languages/messages/MessagesEn.php
@@ -1750,13 +1750,15 @@
1751
1751
'enotif_mailer' => '{{SITENAME}} Notification Mailer',
1752
1752
'enotif_reset' => 'Mark all pages visited',
1753
1753
'enotif_newpagetext'=> 'This is a new page.',
1754
+'enotif_impersonal_salutation' => '{{SITENAME}} user',
1754
1755
'changed' => 'changed',
1755
1756
'created' => 'created',
1756
1757
'enotif_subject' => '{{SITENAME}} page $PAGETITLE has been $CHANGEDORCREATED by $PAGEEDITOR',
1757
1758
'enotif_lastvisited' => 'See $1 for all changes since your last visit.',
1759
+'enotif_lastdiff' => 'See $1 to view this change.',
1758
1760
'enotif_body' => 'Dear $WATCHINGUSERNAME,
1759
1761
1760
-the {{SITENAME}} page $PAGETITLE has been $CHANGEDORCREATED on $PAGEEDITDATE by $PAGEEDITOR, see $PAGETITLE_URL for the current version.
1762
+The {{SITENAME}} page $PAGETITLE has been $CHANGEDORCREATED on $PAGEEDITDATE by $PAGEEDITOR, see $PAGETITLE_URL for the current version.
1761
1763
1762
1764
$NEWPAGE
1763
1765