]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - lib/mail.php
Merge remote-tracking branch 'upstream/master' into social-master
[quix0rs-gnu-social.git] / lib / mail.php
1 <?php
2 /**
3  * StatusNet, the distributed open-source microblogging tool
4  *
5  * utilities for sending email
6  *
7  * PHP version 5
8  *
9  * LICENCE: This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU Affero General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU Affero General Public License for more details.
18  *
19  * You should have received a copy of the GNU Affero General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  * @category  Mail
23  * @package   StatusNet
24  * @author    Evan Prodromou <evan@status.net>
25  * @author    Zach Copley <zach@status.net>
26  * @author    Robin Millette <millette@status.net>
27  * @author    Sarven Capadisli <csarven@status.net>
28  * @copyright 2008 StatusNet, Inc.
29  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
30  * @link      http://status.net/
31  */
32
33 if (!defined('STATUSNET') && !defined('LACONICA')) {
34     exit(1);
35 }
36
37 require_once 'Mail.php';
38
39 /**
40  * return the configured mail backend
41  *
42  * Uses the $config array to make a mail backend. Cached so it is safe to call
43  * more than once.
44  *
45  * @return Mail backend
46  */
47 function mail_backend()
48 {
49     static $backend = null;
50     global $_PEAR;
51
52     if (!$backend) {
53         $mail = new Mail();
54         $backend = $mail->factory(common_config('mail', 'backend'),
55                                  common_config('mail', 'params') ?: array());
56         if ($_PEAR->isError($backend)) {
57             common_server_error($backend->getMessage(), 500);
58         }
59     }
60     return $backend;
61 }
62
63 /**
64  * send an email to one or more recipients
65  *
66  * @param array  $recipients array of strings with email addresses of recipients
67  * @param array  $headers    array mapping strings to strings for email headers
68  * @param string $body       body of the email
69  *
70  * @return boolean success flag
71  */
72 function mail_send($recipients, $headers, $body)
73 {
74     try {
75         // XXX: use Mail_Queue... maybe
76         $backend = mail_backend();
77
78         if (!isset($headers['Content-Type'])) {
79            $headers['Content-Type'] = 'text/plain; charset=UTF-8';
80         }
81
82         assert($backend); // throws an error if it's bad
83         $sent = $backend->send($recipients, $headers, $body);
84         return true;
85     } catch (PEAR_Exception $e) {
86         common_log(
87             LOG_ERR,
88             "Unable to send email - '{$e->getMessage()}'. "
89             . 'Is your mail subsystem set up correctly?'
90         );
91         return false;
92     }
93 }
94
95 /**
96  * returns the configured mail domain
97  *
98  * Defaults to the server name.
99  *
100  * @return string mail domain, suitable for making email addresses.
101  */
102 function mail_domain()
103 {
104     $maildomain = common_config('mail', 'domain');
105     if (!$maildomain) {
106         $maildomain = common_config('site', 'server');
107     }
108     return $maildomain;
109 }
110
111 /**
112  * returns a good address for sending email from this server
113  *
114  * Uses either the configured value or a faked-up value made
115  * from the mail domain.
116  *
117  * @return string notify from address
118  */
119 function mail_notify_from()
120 {
121     $notifyfrom = common_config('mail', 'notifyfrom');
122
123     if (!$notifyfrom) {
124
125         $domain = mail_domain();
126
127         $notifyfrom = '"'. str_replace('"', '\\"', common_config('site', 'name')) .'" <noreply@'.$domain.'>';
128     }
129
130     return $notifyfrom;
131 }
132
133 /**
134  * sends email to a user
135  *
136  * @param User   &$user   user to send email to
137  * @param string $subject subject of the email
138  * @param string $body    body of the email
139  * @param array  $headers optional list of email headers
140  * @param string $address optional specification of email address
141  *
142  * @return boolean success flag
143  */
144 function mail_to_user(&$user, $subject, $body, $headers=array(), $address=null)
145 {
146     if (!$address) {
147         $address = $user->email;
148     }
149
150     $recipients = $address;
151     $profile    = $user->getProfile();
152
153     $headers['Date']    = date("r", time());
154     $headers['From']    = mail_notify_from();
155     $headers['To']      = $profile->getBestName() . ' <' . $address . '>';
156     $headers['Subject'] = $subject;
157
158     return mail_send($recipients, $headers, $body);
159 }
160
161 /**
162  * Send an email to confirm a user's control of an email address
163  *
164  * @param User   $user     User claiming the email address
165  * @param string $code     Confirmation code
166  * @param string $nickname Nickname of user
167  * @param string $address  email address to confirm
168  *
169  * @see common_confirmation_code()
170  *
171  * @return success flag
172  */
173 function mail_confirm_address($user, $code, $nickname, $address, $url=null)
174 {
175     if (empty($url)) {
176         $url = common_local_url('confirmaddress', array('code' => $code));
177     }
178
179     // TRANS: Subject for address confirmation email.
180     $subject = _('Email address confirmation');
181
182     // TRANS: Body for address confirmation email.
183     // TRANS: %1$s is the addressed user's nickname, %2$s is the StatusNet sitename,
184     // TRANS: %3$s is the URL to confirm at.
185     $body = sprintf(_("Hey, %1\$s.\n\n".
186                       "Someone just entered this email address on %2\$s.\n\n" .
187                       "If it was you, and you want to confirm your entry, ".
188                       "use the URL below:\n\n\t%3\$s\n\n" .
189                       "If not, just ignore this message.\n\n".
190                       "Thanks for your time, \n%2\$s\n"),
191                     $nickname,
192                     common_config('site', 'name'),
193                     $url);
194
195     $headers = array();
196
197     return mail_to_user($user, $subject, $body, $headers, $address);
198 }
199
200 /**
201  * notify a user of subscription by another user
202  *
203  * This is just a wrapper around the profile-based version.
204  *
205  * @param User $listenee user who is being subscribed to
206  * @param User $listener user who is subscribing
207  *
208  * @see mail_subscribe_notify_profile()
209  *
210  * @return void
211  */
212 function mail_subscribe_notify($listenee, $listener)
213 {
214     $other = $listener->getProfile();
215     mail_subscribe_notify_profile($listenee, $other);
216 }
217
218 /**
219  * notify a user of subscription by a profile (remote or local)
220  *
221  * This function checks to see if the listenee has an email
222  * address and wants subscription notices.
223  *
224  * @param User    $listenee user who's being subscribed to
225  * @param Profile $other    profile of person who's listening
226  *
227  * @return void
228  */
229 function mail_subscribe_notify_profile($listenee, $other)
230 {
231     if ($other->hasRight(Right::EMAILONSUBSCRIBE) &&
232         $listenee->email && $listenee->emailnotifysub) {
233
234         $profile = $listenee->getProfile();
235
236         $name = $profile->getBestName();
237
238         $long_name = ($other->fullname) ?
239           ($other->fullname . ' (' . $other->nickname . ')') : $other->nickname;
240
241         $recipients = $listenee->email;
242
243         // use the recipient's localization
244         common_switch_locale($listenee->language);
245
246         $headers = _mail_prepare_headers('subscribe', $listenee->nickname, $other->nickname);
247         $headers['From']    = mail_notify_from();
248         $headers['To']      = $name . ' <' . $listenee->email . '>';
249         // TRANS: Subject of new-subscriber notification e-mail.
250         // TRANS: %1$s is the subscribing user's nickname, %2$s is the StatusNet sitename.
251         $headers['Subject'] = sprintf(_('%1$s is now following you on %2$s.'),
252                                       $other->getBestName(),
253                                       common_config('site', 'name'));
254
255         // TRANS: Main body of new-subscriber notification e-mail.
256         // TRANS: %1$s is the subscriber's long name, %2$s is the StatusNet sitename.
257         $body = sprintf(_('%1$s is now following you on %2$s.'),
258                         $long_name,
259                         common_config('site', 'name')) .
260                 mail_profile_block($other) .
261                 mail_footer_block();
262
263         // reset localization
264         common_switch_locale();
265         mail_send($recipients, $headers, $body);
266     }
267 }
268
269 function mail_subscribe_pending_notify_profile($listenee, $other)
270 {
271     if ($other->hasRight(Right::EMAILONSUBSCRIBE) &&
272         $listenee->email && $listenee->emailnotifysub) {
273
274         $profile = $listenee->getProfile();
275
276         $name = $profile->getBestName();
277
278         $long_name = ($other->fullname) ?
279           ($other->fullname . ' (' . $other->nickname . ')') : $other->nickname;
280
281         $recipients = $listenee->email;
282
283         // use the recipient's localization
284         common_switch_locale($listenee->language);
285
286         $headers = _mail_prepare_headers('subscribe', $listenee->nickname, $other->nickname);
287         $headers['From']    = mail_notify_from();
288         $headers['To']      = $name . ' <' . $listenee->email . '>';
289         // TRANS: Subject of pending new-subscriber notification e-mail.
290         // TRANS: %1$s is the subscribing user's nickname, %2$s is the StatusNet sitename.
291         $headers['Subject'] = sprintf(_('%1$s would like to listen to '.
292                                         'your notices on %2$s.'),
293                                       $other->getBestName(),
294                                       common_config('site', 'name'));
295
296         // TRANS: Main body of pending new-subscriber notification e-mail.
297         // TRANS: %1$s is the subscriber's long name, %2$s is the StatusNet sitename.
298         $body = sprintf(_('%1$s would like to listen to your notices on %2$s. ' .
299                           'You may approve or reject their subscription at %3$s'),
300                         $long_name,
301                         common_config('site', 'name'),
302                         common_local_url('subqueue', array('nickname' => $listenee->nickname))) .
303                 mail_profile_block($other) .
304                 mail_footer_block();
305
306         // reset localization
307         common_switch_locale();
308         mail_send($recipients, $headers, $body);
309     }
310 }
311
312 function mail_footer_block()
313 {
314     // TRANS: Common footer block for StatusNet notification emails.
315     // TRANS: %1$s is the StatusNet sitename,
316     // TRANS: %2$s is a link to the addressed user's e-mail settings.
317     return "\n\n" . sprintf(_('Faithfully yours,'.
318                               "\n".'%1$s.'."\n\n".
319                               "----\n".
320                               "Change your email address or ".
321                               "notification options at ".'%2$s'),
322                             common_config('site', 'name'),
323                             common_local_url('emailsettings')) . "\n";
324 }
325
326 /**
327  * Format a block of profile info for a plaintext notification email.
328  *
329  * @param Profile $profile
330  * @return string
331  */
332 function mail_profile_block($profile)
333 {
334     // TRANS: Layout for
335     // TRANS: %1$s is the subscriber's profile URL, %2$s is the subscriber's location (or empty)
336     // TRANS: %3$s is the subscriber's homepage URL (or empty), %4%s is the subscriber's bio (or empty)
337     $out = array();
338     $out[] = "";
339     $out[] = "";
340     // TRANS: Profile info line in notification e-mail.
341     // TRANS: %s is a URL.
342     $out[] = sprintf(_("Profile: %s"), $profile->profileurl);
343     if ($profile->location) {
344         // TRANS: Profile info line in notification e-mail.
345         // TRANS: %s is a location.
346         $out[] = sprintf(_("Location: %s"), $profile->location);
347     }
348     if ($profile->homepage) {
349         // TRANS: Profile info line in notification e-mail.
350         // TRANS: %s is a homepage.
351         $out[] = sprintf(_("Homepage: %s"), $profile->homepage);
352     }
353     if ($profile->bio) {
354         // TRANS: Profile info line in notification e-mail.
355         // TRANS: %s is biographical information.
356         $out[] = sprintf(_("Bio: %s"), $profile->bio);
357     }
358
359     $blocklink = common_local_url('block', array('profileid' => $profile->id));
360     // This'll let ModPlus add the remote profile info so it's possible
361     // to block remote users directly...
362     Event::handle('MailProfileInfoBlockLink', array($profile, &$blocklink));
363
364     // TRANS: This is a paragraph in a new-subscriber e-mail.
365     // TRANS: %s is a URL where the subscriber can be reported as abusive.
366     $out[] = sprintf(_('If you believe this account is being used abusively, ' .
367                        'you can block them from your subscribers list and ' .
368                        'report as spam to site administrators at %s.'),
369                      $blocklink);
370     $out[] = "";
371
372     return implode("\n", $out);
373 }
374
375 /**
376  * notify a user of their new incoming email address
377  *
378  * User's email and incoming fields should already be updated.
379  *
380  * @param User $user user with the new address
381  *
382  * @return void
383  */
384 function mail_new_incoming_notify($user)
385 {
386     $profile = $user->getProfile();
387
388     $name = $profile->getBestName();
389
390     $headers['From']    = $user->incomingemail;
391     $headers['To']      = $name . ' <' . $user->email . '>';
392     // TRANS: Subject of notification mail for new posting email address.
393     // TRANS: %s is the StatusNet sitename.
394     $headers['Subject'] = sprintf(_('New email address for posting to %s'),
395                                   common_config('site', 'name'));
396
397     // TRANS: Body of notification mail for new posting email address.
398     // TRANS: %1$s is the StatusNet sitename, %2$s is the e-mail address to send
399     // TRANS: to to post by e-mail, %3$s is a URL to more instructions.
400     $body = sprintf(_("You have a new posting address on %1\$s.\n\n".
401                       "Send email to %2\$s to post new messages.\n\n".
402                       "More email instructions at %3\$s."),
403                     common_config('site', 'name'),
404                     $user->incomingemail,
405                     common_local_url('doc', array('title' => 'email'))) .
406             mail_footer_block();
407
408     mail_send($user->email, $headers, $body);
409 }
410
411 /**
412  * generate a new address for incoming messages
413  *
414  * @todo check the database for uniqueness
415  *
416  * @return string new email address for incoming messages
417  */
418 function mail_new_incoming_address()
419 {
420     $prefix = common_confirmation_code(64);
421     $suffix = mail_domain();
422     return $prefix . '@' . $suffix;
423 }
424
425 /**
426  * broadcast a notice to all subscribers with SMS notification on
427  *
428  * This function sends SMS messages to all users who have sms addresses;
429  * have sms notification on; and have sms enabled for this particular
430  * subscription.
431  *
432  * @param Notice $notice The notice to broadcast
433  *
434  * @return success flag
435  */
436 function mail_broadcast_notice_sms($notice)
437 {
438     // Now, get users subscribed to this profile
439
440     $user = new User();
441
442     $UT = common_config('db','type')=='pgsql'?'"user"':'user';
443     $replies = $notice->getReplies();
444     $user->query('SELECT nickname, smsemail, incomingemail ' .
445                  "FROM $UT LEFT OUTER JOIN subscription " .
446                  "ON $UT.id = subscription.subscriber " .
447                  'AND subscription.subscribed = ' . $notice->profile_id . ' ' .
448                  'AND subscription.subscribed != subscription.subscriber ' .
449                  // Users (other than the sender) who `want SMS notices':
450                  "WHERE $UT.id != " . $notice->profile_id . ' ' .
451                  "AND $UT.smsemail IS NOT null " .
452                  "AND $UT.smsnotify = 1 " .
453                  // ... where either the user _is_ subscribed to the sender
454                  // (any of the "subscription" fields IS NOT null)
455                  // and wants to get SMS for all of this scribe's notices...
456                  'AND (subscription.sms = 1 ' .
457                  // ... or where the user was mentioned in
458                  // or replied-to with the notice:
459                  ($replies ? sprintf("OR $UT.id in (%s)",
460                                      implode(',', $replies))
461                            : '') .
462                  ')');
463
464     while ($user->fetch()) {
465         common_log(LOG_INFO,
466                    'Sending notice ' . $notice->id . ' to ' . $user->smsemail,
467                    __FILE__);
468         $success = mail_send_sms_notice_address($notice,
469                                                 $user->smsemail,
470                                                 $user->incomingemail,
471                                                 $user->nickname);
472         if (!$success) {
473             // XXX: Not sure, but I think that's the right thing to do
474             common_log(LOG_WARNING,
475                        'Sending notice ' . $notice->id . ' to ' .
476                        $user->smsemail . ' FAILED, cancelling.',
477                        __FILE__);
478             return false;
479         }
480     }
481
482     $user->free();
483     unset($user);
484
485     return true;
486 }
487
488 /**
489  * send a notice to a user via SMS
490  *
491  * A convenience wrapper around mail_send_sms_notice_address()
492  *
493  * @param Notice $notice notice to send
494  * @param User   $user   user to receive notice
495  *
496  * @see mail_send_sms_notice_address()
497  *
498  * @return boolean success flag
499  */
500 function mail_send_sms_notice($notice, $user)
501 {
502     return mail_send_sms_notice_address($notice,
503                                         $user->smsemail,
504                                         $user->incomingemail,
505                                         $user->nickname);
506 }
507
508 /**
509  * send a notice to an SMS email address from a given address
510  *
511  * We use the user's incoming email address as the "From" address to make
512  * replying to notices easier.
513  *
514  * @param Notice $notice        notice to send
515  * @param string $smsemail      email address to send to
516  * @param string $incomingemail email address to set as 'from'
517  * @param string $nickname      nickname to add to beginning
518  *
519  * @return boolean success flag
520  */
521 function mail_send_sms_notice_address($notice, $smsemail, $incomingemail, $nickname)
522 {
523     $to = $nickname . ' <' . $smsemail . '>';
524
525     $other = $notice->getProfile();
526
527     common_log(LOG_INFO, 'Sending notice ' . $notice->id .
528                ' to ' . $smsemail, __FILE__);
529
530     $headers = array();
531
532     $headers['From']    = ($incomingemail) ? $incomingemail : mail_notify_from();
533     $headers['To']      = $to;
534     // TRANS: Subject line for SMS-by-email notification messages.
535     // TRANS: %s is the posting user's nickname.
536     $headers['Subject'] = sprintf(_('%s status'),
537                                   $other->getBestName());
538
539     $body = $notice->content;
540
541     return mail_send($smsemail, $headers, $body);
542 }
543
544 /**
545  * send a message to confirm a claim for an SMS number
546  *
547  * @param string $code     confirmation code
548  * @param string $nickname nickname of user claiming number
549  * @param string $address  email address to send the confirmation to
550  *
551  * @see common_confirmation_code()
552  *
553  * @return void
554  */
555 function mail_confirm_sms($code, $nickname, $address)
556 {
557     $recipients = $address;
558
559     $headers['From']    = mail_notify_from();
560     $headers['To']      = $nickname . ' <' . $address . '>';
561     // TRANS: Subject line for SMS-by-email address confirmation message.
562     $headers['Subject'] = _('SMS confirmation');
563
564     // TRANS: Main body heading for SMS-by-email address confirmation message.
565     // TRANS: %s is the addressed user's nickname.
566     $body  = sprintf(_('%s: confirm you own this phone number with this code:'), $nickname);
567     $body .= "\n\n";
568     $body .= $code;
569     $body .= "\n\n";
570
571     mail_send($recipients, $headers, $body);
572 }
573
574 /**
575  * send a mail message to notify a user of a 'nudge'
576  *
577  * @param User $from user nudging
578  * @param User $to   user being nudged
579  *
580  * @return boolean success flag
581  */
582 function mail_notify_nudge($from, $to)
583 {
584     common_switch_locale($to->language);
585     // TRANS: Subject for 'nudge' notification email.
586     // TRANS: %s is the nudging user.
587     $subject = sprintf(_('You have been nudged by %s'), $from->nickname);
588
589     $from_profile = $from->getProfile();
590
591     // TRANS: Body for 'nudge' notification email.
592     // TRANS: %1$s is the nuding user's long name, $2$s is the nudging user's nickname,
593     // TRANS: %3$s is a URL to post notices at.
594     $body = sprintf(_("%1\$s (%2\$s) is wondering what you are up to ".
595                       "these days and is inviting you to post some news.\n\n".
596                       "So let's hear from you :)\n\n".
597                       "%3\$s\n\n".
598                       "Don't reply to this email; it won't get to them."),
599                     $from_profile->getBestName(),
600                     $from->nickname,
601                     common_local_url('all', array('nickname' => $to->nickname))) .
602             mail_footer_block();
603     common_switch_locale();
604
605     $headers = _mail_prepare_headers('nudge', $to->nickname, $from->nickname);
606
607     return mail_to_user($to, $subject, $body, $headers);
608 }
609
610 /**
611  * send a message to notify a user of a direct message (DM)
612  *
613  * This function checks to see if the recipient wants notification
614  * of DMs and has a configured email address.
615  *
616  * @param Message $message message to notify about
617  * @param User    $from    user sending message; default to sender
618  * @param User    $to      user receiving message; default to recipient
619  *
620  * @return boolean success code
621  */
622 function mail_notify_message($message, $from=null, $to=null)
623 {
624     if (is_null($from)) {
625         $from = User::getKV('id', $message->from_profile);
626     }
627
628     if (is_null($to)) {
629         $to = User::getKV('id', $message->to_profile);
630     }
631
632     if (is_null($to->email) || !$to->emailnotifymsg) {
633         return true;
634     }
635
636     common_switch_locale($to->language);
637     // TRANS: Subject for direct-message notification email.
638     // TRANS: %s is the sending user's nickname.
639     $subject = sprintf(_('New private message from %s'), $from->nickname);
640
641     $from_profile = $from->getProfile();
642
643     // TRANS: Body for direct-message notification email.
644     // TRANS: %1$s is the sending user's long name, %2$s is the sending user's nickname,
645     // TRANS: %3$s is the message content, %4$s a URL to the message,
646     $body = sprintf(_("%1\$s (%2\$s) sent you a private message:\n\n".
647                       "------------------------------------------------------\n".
648                       "%3\$s\n".
649                       "------------------------------------------------------\n\n".
650                       "You can reply to their message here:\n\n".
651                       "%4\$s\n\n".
652                       "Don't reply to this email; it won't get to them."),
653                     $from_profile->getBestName(),
654                     $from->nickname,
655                     $message->content,
656                     common_local_url('newmessage', array('to' => $from->id))) .
657             mail_footer_block();
658
659     $headers = _mail_prepare_headers('message', $to->nickname, $from->nickname);
660
661     common_switch_locale();
662     return mail_to_user($to, $subject, $body, $headers);
663 }
664
665 /**
666  * Notify a user that they have received an "attn:" message AKA "@-reply"
667  *
668  * @param User   $user   The user who recevied the notice
669  * @param Notice $notice The notice that was sent
670  *
671  * @return void
672  */
673 function mail_notify_attn($user, $notice)
674 {
675     if (!$user->receivesEmailNotifications()) {
676         return;
677     }
678
679     $sender = $notice->getProfile();
680
681     if ($sender->id == $user->id) {
682         return;
683     }
684
685     // See if the notice's author who mentions this user is sandboxed
686     if (!$sender->hasRight(Right::EMAILONREPLY)) {
687         return;
688     }
689
690     // If the author has blocked the author, don't spam them with a notification.
691     if ($user->hasBlocked($sender)) {
692         return;
693     }
694
695     $bestname = $sender->getBestName();
696
697     common_switch_locale($user->language);
698
699     if ($notice->hasConversation()) {
700         $conversationUrl = common_local_url('conversation',
701                          array('id' => $notice->conversation)).'#notice-'.$notice->id;
702         // TRANS: Line in @-reply notification e-mail. %s is conversation URL.
703         $conversationEmailText = sprintf(_("The full conversation can be read here:\n\n".
704                                            "\t%s"), $conversationUrl) . "\n\n";
705     } else {
706         $conversationEmailText = '';
707     }
708
709     // TRANS: E-mail subject for notice notification.
710     // TRANS: %1$s is the sending user's long name, %2$s is the adding user's nickname.
711     $subject = sprintf(_('%1$s (@%2$s) sent a notice to your attention'), $bestname, $sender->nickname);
712
713         // TRANS: Body of @-reply notification e-mail.
714         // TRANS: %1$s is the sending user's name, $2$s is the StatusNet sitename,
715         // TRANS: %3$s is a URL to the notice, %4$s is the notice text,
716         // TRANS: %5$s is the text "The full conversation can be read here:" and a URL to the full conversion if it exists (otherwise empty),
717         // TRANS: %6$s is a URL to reply to the notice, %7$s is a URL to all @-replies for the addressed user,
718         $body = sprintf(_("%1\$s just sent a notice to your attention (an '@-reply') on %2\$s.\n\n".
719                       "The notice is here:\n\n".
720                       "\t%3\$s\n\n" .
721                       "It reads:\n\n".
722                       "\t%4\$s\n\n" .
723                       "%5\$s" .
724                       "You can reply back here:\n\n".
725                       "\t%6\$s\n\n" .
726                       "The list of all @-replies for you here:\n\n" .
727                       "%7\$s"),
728                     $sender->getFancyName(),//%1
729                     common_config('site', 'name'),//%2
730                     common_local_url('shownotice',
731                                      array('notice' => $notice->id)),//%3
732                     $notice->content,//%4
733                     $conversationEmailText,//%5
734                     common_local_url('newnotice',
735                                      array('replyto' => $sender->nickname, 'inreplyto' => $notice->id)),//%6
736                     common_local_url('replies',
737                                      array('nickname' => $user->nickname))) . //%7
738                 mail_footer_block();
739     $headers = _mail_prepare_headers('mention', $user->nickname, $sender->nickname);
740
741     common_switch_locale();
742     mail_to_user($user, $subject, $body, $headers);
743 }
744
745 /**
746  * Prepare the common mail headers used in notification emails
747  *
748  * @param string $msg_type type of message being sent to the user
749  * @param string $to       nickname of the receipient
750  * @param string $from     nickname of the user triggering the notification
751  *
752  * @return array list of mail headers to include in the message
753  */
754 function _mail_prepare_headers($msg_type, $to, $from)
755 {
756     $headers = array(
757         'X-StatusNet-MessageType' => $msg_type,
758         'X-StatusNet-TargetUser'  => $to,
759         'X-StatusNet-SourceUser'  => $from,
760         'X-StatusNet-Domain'      => common_config('site', 'server')
761     );
762
763     return $headers;
764 }
765
766 /**
767  * Send notification emails to group administrator.
768  *
769  * @param User_group $group
770  * @param Profile $joiner
771  */
772 function mail_notify_group_join($group, $joiner)
773 {
774     // This returns a Profile query...
775     $admin = $group->getAdmins();
776     while ($admin->fetch()) {
777         // We need a local user for email notifications...
778         $adminUser = User::getKV('id', $admin->id);
779         // @fixme check for email preference?
780         if ($adminUser && $adminUser->email) {
781             // use the recipient's localization
782             common_switch_locale($adminUser->language);
783
784             $headers = _mail_prepare_headers('join', $admin->nickname, $joiner->nickname);
785             $headers['From']    = mail_notify_from();
786             $headers['To']      = $admin->getBestName() . ' <' . $adminUser->email . '>';
787             // TRANS: Subject of group join notification e-mail.
788             // TRANS: %1$s is the joining user's nickname, %2$s is the group name, and %3$s is the StatusNet sitename.
789             $headers['Subject'] = sprintf(_('%1$s has joined '.
790                                             'your group %2$s on %3$s'),
791                                           $joiner->getBestName(),
792                                           $group->getBestName(),
793                                           common_config('site', 'name'));
794
795             // TRANS: Main body of group join notification e-mail.
796             // TRANS: %1$s is the subscriber's long name, %2$s is the group name, and %3$s is the StatusNet sitename,
797             // TRANS: %4$s is a block of profile info about the subscriber.
798             // TRANS: %5$s is a link to the addressed user's e-mail settings.
799             $body = sprintf(_('%1$s has joined your group %2$s on %3$s.'),
800                             $joiner->getFancyName(),
801                             $group->getFancyName(),
802                             common_config('site', 'name')) .
803                     mail_profile_block($joiner) .
804                     mail_footer_block();
805
806             // reset localization
807             common_switch_locale();
808             mail_send($adminUser->email, $headers, $body);
809         }
810     }
811 }
812
813
814 /**
815  * Send notification emails to group administrator.
816  *
817  * @param User_group $group
818  * @param Profile $joiner
819  */
820 function mail_notify_group_join_pending($group, $joiner)
821 {
822     $admin = $group->getAdmins();
823     while ($admin->fetch()) {
824         // We need a local user for email notifications...
825         $adminUser = User::getKV('id', $admin->id);
826         // @fixme check for email preference?
827         if ($adminUser && $adminUser->email) {
828             // use the recipient's localization
829             common_switch_locale($adminUser->language);
830
831             $headers = _mail_prepare_headers('join', $admin->nickname, $joiner->nickname);
832             $headers['From']    = mail_notify_from();
833             $headers['To']      = $admin->getBestName() . ' <' . $adminUser->email . '>';
834             // TRANS: Subject of pending group join request notification e-mail.
835             // TRANS: %1$s is the joining user's nickname, %2$s is the group name, and %3$s is the StatusNet sitename.
836             $headers['Subject'] = sprintf(_('%1$s wants to join your group %2$s on %3$s.'),
837                                           $joiner->getBestName(),
838                                           $group->getBestName(),
839                                           common_config('site', 'name'));
840
841             // TRANS: Main body of pending group join request notification e-mail.
842             // TRANS: %1$s is the subscriber's long name, %2$s is the group name, and %3$s is the StatusNet sitename,
843             // TRANS: %4$s is the URL to the moderation queue page.
844             $body = sprintf(_('%1$s would like to join your group %2$s on %3$s. ' .
845                               'You may approve or reject their group membership at %4$s'),
846                             $joiner->getFancyName(),
847                             $group->getFancyName(),
848                             common_config('site', 'name'),
849                             common_local_url('groupqueue', array('nickname' => $group->nickname))) .
850                     mail_profile_block($joiner) .
851                     mail_footer_block();
852
853             // reset localization
854             common_switch_locale();
855             mail_send($adminUser->email, $headers, $body);
856         }
857     }
858 }