暫無描述

PHPMail.php 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. <?php
  2. namespace MailPoet\Mailer\Methods;
  3. if (!defined('ABSPATH')) exit;
  4. use MailPoet\Mailer\Mailer;
  5. use MailPoet\Mailer\Methods\Common\BlacklistCheck;
  6. use MailPoet\Mailer\Methods\ErrorMappers\PHPMailMapper;
  7. use MailPoet\Mailer\WordPress\PHPMailerLoader;
  8. PHPMailerLoader::load();
  9. class PHPMail {
  10. public $sender;
  11. public $replyTo;
  12. public $returnPath;
  13. public $mailer;
  14. /** @var PHPMailMapper */
  15. private $errorMapper;
  16. /** @var BlacklistCheck */
  17. private $blacklist;
  18. public function __construct(
  19. $sender,
  20. $replyTo,
  21. $returnPath,
  22. PHPMailMapper $errorMapper
  23. ) {
  24. $this->sender = $sender;
  25. $this->replyTo = $replyTo;
  26. $this->returnPath = ($returnPath) ?
  27. $returnPath :
  28. $this->sender['from_email'];
  29. $this->mailer = $this->buildMailer();
  30. $this->errorMapper = $errorMapper;
  31. $this->blacklist = new BlacklistCheck();
  32. }
  33. public function send($newsletter, $subscriber, $extraParams = []) {
  34. if ($this->blacklist->isBlacklisted($subscriber)) {
  35. $error = $this->errorMapper->getBlacklistError($subscriber);
  36. return Mailer::formatMailerErrorResult($error);
  37. }
  38. try {
  39. $mailer = $this->configureMailerWithMessage($newsletter, $subscriber, $extraParams);
  40. $result = $mailer->send();
  41. } catch (\Exception $e) {
  42. return Mailer::formatMailerErrorResult($this->errorMapper->getErrorFromException($e, $subscriber));
  43. }
  44. if ($result === true) {
  45. return Mailer::formatMailerSendSuccessResult();
  46. } else {
  47. $error = $this->errorMapper->getErrorForSubscriber($subscriber);
  48. return Mailer::formatMailerErrorResult($error);
  49. }
  50. }
  51. public function buildMailer() {
  52. $mailer = new \PHPMailer(true);
  53. // send using PHP's mail() function
  54. $mailer->isMail();
  55. return $mailer;
  56. }
  57. public function configureMailerWithMessage($newsletter, $subscriber, $extraParams = []) {
  58. $mailer = $this->mailer;
  59. $mailer->clearAddresses();
  60. $mailer->clearCustomHeaders();
  61. $mailer->isHTML(!empty($newsletter['body']['html']));
  62. $mailer->CharSet = 'UTF-8'; // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
  63. $mailer->setFrom($this->sender['from_email'], $this->sender['from_name'], false);
  64. $mailer->addReplyTo($this->replyTo['reply_to_email'], $this->replyTo['reply_to_name']);
  65. $subscriber = $this->processSubscriber($subscriber);
  66. $mailer->addAddress($subscriber['email'], $subscriber['name']);
  67. $mailer->Subject = (!empty($newsletter['subject'])) ? $newsletter['subject'] : ''; // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
  68. $mailer->Body = (!empty($newsletter['body']['html'])) ? $newsletter['body']['html'] : $newsletter['body']['text']; // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
  69. if ($mailer->ContentType !== 'text/plain') { // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
  70. $mailer->AltBody = (!empty($newsletter['body']['text'])) ? $newsletter['body']['text'] : ''; // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
  71. }
  72. $mailer->Sender = $this->returnPath; // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
  73. if (!empty($extraParams['unsubscribe_url'])) {
  74. $this->mailer->addCustomHeader('List-Unsubscribe', $extraParams['unsubscribe_url']);
  75. }
  76. // Enforce base64 encoding when lines are too long, otherwise quoted-printable encoding
  77. // is automatically used which can occasionally break the email body.
  78. // Explanation:
  79. // The bug occurs on Unix systems where mail() function passes email to a variation of
  80. // sendmail command which expects only NL as line endings (POSIX). Since quoted-printable
  81. // requires CRLF some of those commands convert LF to CRLF which can break the email body
  82. // because it already (correctly) uses CRLF. Such CRLF then (wrongly) becomes CRCRLF.
  83. if (\PHPMailer::hasLineLongerThanMax($mailer->Body)) { // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
  84. $mailer->Encoding = 'base64'; // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
  85. }
  86. return $mailer;
  87. }
  88. public function processSubscriber($subscriber) {
  89. preg_match('!(?P<name>.*?)\s<(?P<email>.*?)>!', $subscriber, $subscriberData);
  90. if (!isset($subscriberData['email'])) {
  91. $subscriberData = [
  92. 'email' => $subscriber,
  93. ];
  94. }
  95. return [
  96. 'email' => $subscriberData['email'],
  97. 'name' => (isset($subscriberData['name'])) ? $subscriberData['name'] : '',
  98. ];
  99. }
  100. }