Email.php 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. <?php
  2. namespace app\common\library;
  3. use think\Config;
  4. use Tx\Mailer;
  5. use Tx\Mailer\Exceptions\CodeException;
  6. use Tx\Mailer\Exceptions\SendException;
  7. class Email
  8. {
  9. /**
  10. * 单例对象
  11. */
  12. protected static $instance;
  13. /**
  14. * phpmailer对象
  15. */
  16. protected $mail = null;
  17. /**
  18. * 错误内容
  19. */
  20. protected $error = '';
  21. /**
  22. * 默认配置
  23. */
  24. public $options = [
  25. 'charset' => 'utf-8', //编码格式
  26. 'debug' => false, //调式模式
  27. 'mail_type' => 0, //状态
  28. ];
  29. /**
  30. * 初始化
  31. * @access public
  32. * @param array $options 参数
  33. * @return Email
  34. */
  35. public static function instance($options = [])
  36. {
  37. if (is_null(self::$instance)) {
  38. self::$instance = new static($options);
  39. }
  40. return self::$instance;
  41. }
  42. /**
  43. * 构造函数
  44. * @param array $options
  45. */
  46. public function __construct($options = [])
  47. {
  48. if ($config = Config::get('site')) {
  49. $this->options = array_merge($this->options, $config);
  50. }
  51. $this->options = array_merge($this->options, $options);
  52. $secureArr = [0 => '', 1 => 'tls', 2 => 'ssl'];
  53. $secure = $secureArr[$this->options['mail_verify_type']] ?? '';
  54. $logger = isset($this->options['debug']) && $this->options['debug'] ? new Log : null;
  55. $this->mail = new Mailer($logger);
  56. $this->mail->setServer($this->options['mail_smtp_host'], $this->options['mail_smtp_port'], $secure);
  57. $this->mail->setAuth($this->options['mail_from'], $this->options['mail_smtp_pass']);
  58. //设置发件人
  59. $this->from($this->options['mail_from'], $this->options['mail_smtp_user']);
  60. }
  61. /**
  62. * 设置邮件主题
  63. * @param string $subject 邮件主题
  64. * @return $this
  65. */
  66. public function subject($subject)
  67. {
  68. $this->mail->setSubject($subject);
  69. return $this;
  70. }
  71. /**
  72. * 设置发件人
  73. * @param string $email 发件人邮箱
  74. * @param string $name 发件人名称
  75. * @return $this
  76. */
  77. public function from($email, $name = '')
  78. {
  79. $this->mail->setFrom($name, $email);
  80. return $this;
  81. }
  82. /**
  83. * 设置收件人
  84. * @param mixed $email 收件人,多个收件人以,进行分隔
  85. * @return $this
  86. */
  87. public function to($email)
  88. {
  89. $emailArr = $this->buildAddress($email);
  90. foreach ($emailArr as $address => $name) {
  91. $this->mail->addTo($name, $address);
  92. }
  93. return $this;
  94. }
  95. /**
  96. * 设置抄送
  97. * @param mixed $email 收件人,多个收件人以,进行分隔
  98. * @param string $name 收件人名称
  99. * @return Email
  100. */
  101. public function cc($email, $name = '')
  102. {
  103. $emailArr = $this->buildAddress($email);
  104. if (count($emailArr) == 1 && $name) {
  105. $emailArr[key($emailArr)] = $name;
  106. }
  107. foreach ($emailArr as $address => $name) {
  108. $this->mail->addCC($name, $address);
  109. }
  110. return $this;
  111. }
  112. /**
  113. * 设置密送
  114. * @param mixed $email 收件人,多个收件人以,进行分隔
  115. * @param string $name 收件人名称
  116. * @return Email
  117. */
  118. public function bcc($email, $name = '')
  119. {
  120. $emailArr = $this->buildAddress($email);
  121. if (count($emailArr) == 1 && $name) {
  122. $emailArr[key($emailArr)] = $name;
  123. }
  124. foreach ($emailArr as $address => $name) {
  125. $this->mail->addBCC($name, $address);
  126. }
  127. return $this;
  128. }
  129. /**
  130. * 设置邮件正文
  131. * @param string $body 邮件下方
  132. * @param boolean $ishtml 是否HTML格式
  133. * @return $this
  134. */
  135. public function message($body, $ishtml = true)
  136. {
  137. $this->mail->setBody($body);
  138. return $this;
  139. }
  140. /**
  141. * 添加附件
  142. * @param string $path 附件路径
  143. * @param string $name 附件名称
  144. * @return Email
  145. */
  146. public function attachment($path, $name = '')
  147. {
  148. $this->mail->addAttachment($name, $path);
  149. return $this;
  150. }
  151. /**
  152. * 构建Email地址
  153. * @param mixed $emails Email数据
  154. * @return array
  155. */
  156. protected function buildAddress($emails)
  157. {
  158. if (!is_array($emails)) {
  159. $emails = array_flip(explode(',', str_replace(";", ",", $emails)));
  160. foreach ($emails as $key => $value) {
  161. $emails[$key] = strstr($key, '@', true);
  162. }
  163. }
  164. return $emails;
  165. }
  166. /**
  167. * 获取最后产生的错误
  168. * @return string
  169. */
  170. public function getError()
  171. {
  172. return $this->error;
  173. }
  174. /**
  175. * 设置错误
  176. * @param string $error 信息信息
  177. */
  178. protected function setError($error)
  179. {
  180. $this->error = $error;
  181. }
  182. /**
  183. * 发送邮件
  184. * @return boolean
  185. */
  186. public function send()
  187. {
  188. $result = false;
  189. if (in_array($this->options['mail_type'], [1, 2])) {
  190. try {
  191. $result = $this->mail->send();
  192. } catch (SendException $e) {
  193. $this->setError($e->getCode() . $e->getMessage());
  194. } catch (CodeException $e) {
  195. preg_match_all("/Expected: (\d+)\, Got: (\d+)( \| (.*))?\$/i", $e->getMessage(), $matches);
  196. $code = $matches[2][0] ?? 0;
  197. $message = isset($matches[2][0]) && isset($matches[4][0]) ? $matches[4][0] : $e->getMessage();
  198. $message = mb_convert_encoding($message, 'UTF-8', 'GBK,GB2312,BIG5');
  199. $this->setError($message);
  200. } catch (\Exception $e) {
  201. $this->setError($e->getMessage());
  202. }
  203. $this->setError($result ? '' : $this->getError());
  204. } else {
  205. //邮件功能已关闭
  206. $this->setError(__('Mail already closed'));
  207. }
  208. return $result;
  209. }
  210. }