Email.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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 = [];
  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 = isset($secureArr[$this->options['mail_verify_type']]) ? $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. * @param string $name 收件人名称
  86. * @return $this
  87. */
  88. public function to($email, $name = '')
  89. {
  90. $emailArr = $this->buildAddress($email);
  91. foreach ($emailArr as $address => $name) {
  92. $this->mail->addTo($name, $address);
  93. }
  94. return $this;
  95. }
  96. /**
  97. * 设置抄送
  98. * @param mixed $email 收件人,多个收件人以,进行分隔
  99. * @param string $name 收件人名称
  100. * @return Email
  101. */
  102. public function cc($email, $name = '')
  103. {
  104. $emailArr = $this->buildAddress($email);
  105. if (count($emailArr) == 1 && $name) {
  106. $emailArr[key($emailArr)] = $name;
  107. }
  108. foreach ($emailArr as $address => $name) {
  109. $this->mail->addCC($address, $name);
  110. }
  111. return $this;
  112. }
  113. /**
  114. * 设置密送
  115. * @param mixed $email 收件人,多个收件人以,进行分隔
  116. * @param string $name 收件人名称
  117. * @return Email
  118. */
  119. public function bcc($email, $name = '')
  120. {
  121. $emailArr = $this->buildAddress($email);
  122. if (count($emailArr) == 1 && $name) {
  123. $emailArr[key($emailArr)] = $name;
  124. }
  125. foreach ($emailArr as $address => $name) {
  126. $this->mail->addBCC($name, $address);
  127. }
  128. return $this;
  129. }
  130. /**
  131. * 设置邮件正文
  132. * @param string $body 邮件下方
  133. * @param boolean $ishtml 是否HTML格式
  134. * @return $this
  135. */
  136. public function message($body, $ishtml = true)
  137. {
  138. $this->mail->setBody($body);
  139. return $this;
  140. }
  141. /**
  142. * 添加附件
  143. * @param string $path 附件路径
  144. * @param string $name 附件名称
  145. * @return Email
  146. */
  147. public function attachment($path, $name = '')
  148. {
  149. $this->mail->addAttachment($name, $path);
  150. return $this;
  151. }
  152. /**
  153. * 构建Email地址
  154. * @param mixed $emails Email数据
  155. * @return array
  156. */
  157. protected function buildAddress($emails)
  158. {
  159. $emails = is_array($emails) ? $emails : array_flip(explode(',', str_replace(";", ",", $emails)));
  160. return $emails;
  161. }
  162. /**
  163. * 获取最后产生的错误
  164. * @return string
  165. */
  166. public function getError()
  167. {
  168. return $this->error;
  169. }
  170. /**
  171. * 设置错误
  172. * @param string $error 信息信息
  173. */
  174. protected function setError($error)
  175. {
  176. $this->error = $error;
  177. }
  178. /**
  179. * 发送邮件
  180. * @return boolean
  181. */
  182. public function send()
  183. {
  184. $result = false;
  185. if (in_array($this->options['mail_type'], [1, 2])) {
  186. try {
  187. $result = $this->mail->send();
  188. } catch (SendException $e) {
  189. $this->setError($e->getCode() . $e->getMessage());
  190. } catch (CodeException $e) {
  191. preg_match_all("/Expected: (\d+)\, Got: (\d+)( \| (.*))?\$/i", $e->getMessage(), $matches);
  192. $code = isset($matches[2][3]) ? $matches[2][3] : 0;
  193. $message = isset($matches[2][0]) ? $matches[4][0] : $e->getMessage();
  194. $this->setError($message);
  195. } catch (\Exception $e) {
  196. $this->setError($e->getMessage());
  197. }
  198. $this->setError($result ? '' : $this->getError());
  199. } else {
  200. //邮件功能已关闭
  201. $this->setError(__('Mail already closed'));
  202. }
  203. return $result;
  204. }
  205. }