Mailer.php
190 lines
| 1 | <?php |
| 2 | namespace MailPoet\Mailer; |
| 3 | |
| 4 | use MailPoet\Models\Setting; |
| 5 | |
| 6 | if(!defined('ABSPATH')) exit; |
| 7 | require_once(ABSPATH . 'wp-includes/pluggable.php'); |
| 8 | |
| 9 | class Mailer { |
| 10 | public $mailer_config; |
| 11 | public $sender; |
| 12 | public $reply_to; |
| 13 | public $return_path; |
| 14 | public $mailer_instance; |
| 15 | const MAILER_CONFIG_SETTING_NAME = 'mta'; |
| 16 | const SENDING_LIMIT_INTERVAL_MULTIPLIER = 60; |
| 17 | const METHOD_MAILPOET = 'MailPoet'; |
| 18 | const METHOD_AMAZONSES = 'AmazonSES'; |
| 19 | const METHOD_SENDGRID = 'SendGrid'; |
| 20 | const METHOD_PHPMAIL = 'PHPMail'; |
| 21 | const METHOD_SMTP = 'SMTP'; |
| 22 | |
| 23 | function __construct($mailer = false, $sender = false, $reply_to = false, $return_path = false) { |
| 24 | $this->mailer_config = self::getMailerConfig($mailer); |
| 25 | $this->sender = $this->getSenderNameAndAddress($sender); |
| 26 | $this->reply_to = $this->getReplyToNameAndAddress($reply_to); |
| 27 | $this->return_path = $this->getReturnPathAddress($return_path); |
| 28 | $this->mailer_instance = $this->buildMailer(); |
| 29 | } |
| 30 | |
| 31 | function send($newsletter, $subscriber) { |
| 32 | $subscriber = $this->formatSubscriberNameAndEmailAddress($subscriber); |
| 33 | return $this->mailer_instance->send($newsletter, $subscriber); |
| 34 | } |
| 35 | |
| 36 | function buildMailer() { |
| 37 | switch($this->mailer_config['method']) { |
| 38 | case self::METHOD_AMAZONSES: |
| 39 | $mailer_instance = new $this->mailer_config['class']( |
| 40 | $this->mailer_config['region'], |
| 41 | $this->mailer_config['access_key'], |
| 42 | $this->mailer_config['secret_key'], |
| 43 | $this->sender, |
| 44 | $this->reply_to, |
| 45 | $this->return_path |
| 46 | ); |
| 47 | break; |
| 48 | case self::METHOD_MAILPOET: |
| 49 | $mailer_instance = new $this->mailer_config['class']( |
| 50 | $this->mailer_config['mailpoet_api_key'], |
| 51 | $this->sender, |
| 52 | $this->reply_to |
| 53 | ); |
| 54 | break; |
| 55 | case self::METHOD_SENDGRID: |
| 56 | $mailer_instance = new $this->mailer_config['class']( |
| 57 | $this->mailer_config['api_key'], |
| 58 | $this->sender, |
| 59 | $this->reply_to |
| 60 | ); |
| 61 | break; |
| 62 | case self::METHOD_PHPMAIL: |
| 63 | $mailer_instance = new $this->mailer_config['class']( |
| 64 | $this->sender, |
| 65 | $this->reply_to, |
| 66 | $this->return_path |
| 67 | ); |
| 68 | break; |
| 69 | case self::METHOD_SMTP: |
| 70 | $mailer_instance = new $this->mailer_config['class']( |
| 71 | $this->mailer_config['host'], |
| 72 | $this->mailer_config['port'], |
| 73 | $this->mailer_config['authentication'], |
| 74 | $this->mailer_config['login'], |
| 75 | $this->mailer_config['password'], |
| 76 | $this->mailer_config['encryption'], |
| 77 | $this->sender, |
| 78 | $this->reply_to, |
| 79 | $this->return_path |
| 80 | ); |
| 81 | break; |
| 82 | default: |
| 83 | throw new \Exception(__('Mailing method does not exist', 'mailpoet')); |
| 84 | } |
| 85 | return $mailer_instance; |
| 86 | } |
| 87 | |
| 88 | static function getMailerConfig($mailer = false) { |
| 89 | if(!$mailer) { |
| 90 | $mailer = Setting::getValue(self::MAILER_CONFIG_SETTING_NAME); |
| 91 | if(!$mailer || !isset($mailer['method'])) throw new \Exception(__('Mailer is not configured', 'mailpoet')); |
| 92 | } |
| 93 | if(empty($mailer['frequency'])) { |
| 94 | $default_settings = Setting::getDefaults(); |
| 95 | $mailer['frequency'] = $default_settings['mta']['frequency']; |
| 96 | } |
| 97 | // add additional variables to the mailer object |
| 98 | $mailer['class'] = 'MailPoet\\Mailer\\Methods\\' . $mailer['method']; |
| 99 | $mailer['frequency_interval'] = |
| 100 | (int)$mailer['frequency']['interval'] * self::SENDING_LIMIT_INTERVAL_MULTIPLIER; |
| 101 | $mailer['frequency_limit'] = (int)$mailer['frequency']['emails']; |
| 102 | return $mailer; |
| 103 | } |
| 104 | |
| 105 | function getSenderNameAndAddress($sender = false) { |
| 106 | if(empty($sender)) { |
| 107 | $sender = Setting::getValue('sender', array()); |
| 108 | if(empty($sender['address'])) throw new \Exception(__('Sender name and email are not configured', 'mailpoet')); |
| 109 | } |
| 110 | $from_name = $this->encodeAddressNamePart($sender['name']); |
| 111 | return array( |
| 112 | 'from_name' => $from_name, |
| 113 | 'from_email' => $sender['address'], |
| 114 | 'from_name_email' => sprintf('%s <%s>', $from_name, $sender['address']) |
| 115 | ); |
| 116 | } |
| 117 | |
| 118 | function getReplyToNameAndAddress($reply_to = array()) { |
| 119 | if(!$reply_to) { |
| 120 | $reply_to = Setting::getValue('reply_to'); |
| 121 | $reply_to['name'] = (!empty($reply_to['name'])) ? |
| 122 | $reply_to['name'] : |
| 123 | $this->sender['from_name']; |
| 124 | $reply_to['address'] = (!empty($reply_to['address'])) ? |
| 125 | $reply_to['address'] : |
| 126 | $this->sender['from_email']; |
| 127 | } |
| 128 | if(empty($reply_to['address'])) { |
| 129 | $reply_to['address'] = $this->sender['from_email']; |
| 130 | } |
| 131 | $reply_to_name = $this->encodeAddressNamePart($reply_to['name']); |
| 132 | return array( |
| 133 | 'reply_to_name' => $reply_to_name, |
| 134 | 'reply_to_email' => $reply_to['address'], |
| 135 | 'reply_to_name_email' => sprintf('%s <%s>', $reply_to_name, $reply_to['address']) |
| 136 | ); |
| 137 | } |
| 138 | |
| 139 | function getReturnPathAddress($return_path) { |
| 140 | return ($return_path) ? |
| 141 | $return_path : |
| 142 | Setting::getValue('bounce.address'); |
| 143 | } |
| 144 | |
| 145 | function formatSubscriberNameAndEmailAddress($subscriber) { |
| 146 | $subscriber = (is_object($subscriber)) ? $subscriber->asArray() : $subscriber; |
| 147 | if(!is_array($subscriber)) return $subscriber; |
| 148 | if(isset($subscriber['address'])) $subscriber['email'] = $subscriber['address']; |
| 149 | $first_name = (isset($subscriber['first_name'])) ? $subscriber['first_name'] : ''; |
| 150 | $last_name = (isset($subscriber['last_name'])) ? $subscriber['last_name'] : ''; |
| 151 | if(!$first_name && !$last_name) return $subscriber['email']; |
| 152 | $full_name = sprintf('%s %s', $first_name, $last_name); |
| 153 | $full_name = trim(preg_replace('!\s\s+!', ' ', $full_name)); |
| 154 | $full_name = $this->encodeAddressNamePart($full_name); |
| 155 | $subscriber = sprintf( |
| 156 | '%s <%s>', |
| 157 | $full_name, |
| 158 | $subscriber['email'] |
| 159 | ); |
| 160 | return $subscriber; |
| 161 | } |
| 162 | |
| 163 | function encodeAddressNamePart($name) { |
| 164 | if(mb_detect_encoding($name) === 'ASCII') return $name; |
| 165 | // encode non-ASCII string as per RFC 2047 (https://www.ietf.org/rfc/rfc2047.txt) |
| 166 | return sprintf('=?utf-8?B?%s?=', base64_encode($name)); |
| 167 | } |
| 168 | |
| 169 | static function formatMailerConnectionErrorResult($error_message) { |
| 170 | return array( |
| 171 | 'response' => false, |
| 172 | 'operation' => 'connect', |
| 173 | 'error_message' => $error_message |
| 174 | ); |
| 175 | } |
| 176 | |
| 177 | static function formatMailerSendErrorResult($error_message) { |
| 178 | return array( |
| 179 | 'response' => false, |
| 180 | 'operation' => 'send', |
| 181 | 'error_message' => $error_message |
| 182 | ); |
| 183 | } |
| 184 | |
| 185 | static function formatMailerSendSuccessResult() { |
| 186 | return array( |
| 187 | 'response' => true |
| 188 | ); |
| 189 | } |
| 190 | } |