mail.php 29 KB

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