| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- <?php
- /**
- * 邮件
- *
- * @author mybsdc <[email protected]>
- * @date 2019/5/12
- * @time 16:38
- */
- namespace Luolongfei\Libs\MessageServices;
- use Luolongfei\App\Exceptions\LlfException;
- use Luolongfei\Libs\Log;
- use PHPMailer\PHPMailer\PHPMailer;
- use PHPMailer\PHPMailer\Exception as MailException;
- use Luolongfei\Libs\Connector\MessageGateway;
- class Mail extends MessageGateway
- {
- /**
- * @var PHPMailer
- */
- private $phpMailerInstance;
- /**
- * @throws MailException
- */
- public function __construct()
- {
- $this->phpMailerInstance = new PHPMailer(true);
- $this->init();
- }
- /**
- * 初始化邮箱配置
- *
- * @throws MailException
- */
- protected function init()
- {
- $username = config('message.mail.username');
- $password = config('message.mail.password');
- list($host, $secure, $port) = $this->getBasicMailConf($username);
- $this->phpMailerInstance->SMTPDebug = config('debug') ? 2 : 0; // Debug 0:关闭 1:客户端信息 2:客户端和服务端信息
- $this->phpMailerInstance->isSMTP(); // 告诉 PHPMailer 使用 SMTP
- $this->phpMailerInstance->Host = $host; // SMTP 服务器
- $this->phpMailerInstance->SMTPAuth = true; // 启用 SMTP 身份验证
- $this->phpMailerInstance->Username = $username; // 账号
- $this->phpMailerInstance->Password = $password; // 密码或授权码
- $this->phpMailerInstance->SMTPSecure = $secure; // 将加密系统设置为使用 - ssl(不建议使用)或 tls
- $this->phpMailerInstance->Port = $port; // 设置 SMTP 端口号 - tsl 使用 587 端口,ssl 使用 465 端口
- $this->phpMailerInstance->CharSet = 'UTF-8'; // 防止中文邮件乱码
- $this->phpMailerInstance->setLanguage('zh_cn', VENDOR_PATH . '/phpmailer/phpmailer/language/'); // 设置语言
- $this->phpMailerInstance->setFrom($username, 'Im robot'); // 发件人
- }
- /**
- * 获取邮箱基本配置
- *
- * @param string $username
- *
- * @return array
- * @throws MailException
- */
- public function getBasicMailConf(string $username)
- {
- if (stripos($username, '@gmail.com') !== false) {
- $host = 'smtp.gmail.com';
- $secure = 'tls';
- $port = 587;
- } else if (stripos($username, '@qq.com') !== false) {
- $host = 'smtp.qq.com';
- $secure = 'tls';
- $port = 587;
- } else if (stripos($username, '@163.com') !== false) {
- $host = 'smtp.163.com';
- $secure = 'ssl';
- $port = 465;
- } else if (stripos($username, '@vip.163.com') !== false) {
- $host = 'smtp.vip.163.com';
- $secure = 'ssl';
- $port = 465;
- } else if (stripos($username, '@outlook.com') !== false) {
- $host = 'smtp.office365.com';
- $secure = 'starttls';
- $port = 587;
- } else {
- $host = config('message.mail.host');
- $secure = config('message.mail.encryption');
- $port = (int)config('message.mail.port');
- if (!($host && $secure && $port)) {
- throw new MailException('目前支持Gmail、QQ邮箱、163邮箱以及Outlook邮箱自动识别配置,其它类型的邮箱或者自建邮箱,'
- . '请在 .env 文件中追加“自定义邮箱配置”的所有相关项,否则无法使用邮件服务。');
- }
- }
- return [$host, $secure, $port];
- }
- /**
- * 生成域名 html
- *
- * @param array $domains
- *
- * @return string
- */
- public function genDomainsHtml(array $domains)
- {
- $domainsHtml = '';
- foreach ($domains as $domain) {
- $domainsHtml .= sprintf('<a href="http://%s" rel="noopener" target="_blank">%s</a>', $domain, $domain);
- }
- return $domainsHtml;
- }
- /**
- * 生成域名状态 html
- *
- * @param array $domainStatus
- *
- * @return string
- */
- public function genDomainStatusHtml(array $domainStatus)
- {
- $domainStatusHtml = '';
- foreach ($domainStatus as $domain => $daysLeft) {
- $domainStatusHtml .= sprintf('<a href="http://%s" rel="noopener" target="_blank">%s</a>还有 <span style="font-weight: bold; font-size: 16px;">%d</span> 天到期,', $domain, $domain, $daysLeft);
- }
- $domainStatusHtml = rtrim($domainStatusHtml, ',') . "。";
- return $domainStatusHtml;
- }
- /**
- * 送信
- *
- * @param string $content
- * @param string $subject
- * @param integer $type
- * @param array $data
- * @param string|null $recipient
- * @param mixed ...$params
- *
- * @return bool
- * @throws LlfException
- * @throws MailException
- */
- public function send(string $content, string $subject = '', int $type = 1, array $data = [], ?string $recipient = null, ...$params)
- {
- $recipient = $recipient ?: config('message.mail.to');
- if (!$recipient) {
- throw new LlfException(34520012);
- }
- if ($content === '' && empty($data)) {
- throw new \Exception(lang('error_msg.100002'));
- }
- if ($content !== '' && $data) {
- throw new \Exception(lang('error_msg.100004'));
- }
- $this->phpMailerInstance->addAddress($recipient, config('message.mail.recipient_name', '主人')); // 添加收件人,参数2选填
- $this->phpMailerInstance->addReplyTo(config('message.mail.reply_to', '[email protected]'), config('message.mail.reply_to_name', '作者')); // 备用回复地址,收到的回复的邮件将被发到此地址
- /**
- * 抄送和密送都是添加收件人,抄送方式下,被抄送者知道除被密送者外的所有的收件人,密送方式下,
- * 被密送者知道所有的被抄送者,但不知道其它的被密送者。
- * 抄送好比@,密送好比私信。
- */
- // $this->phpMailerInstance->addCC('[email protected]'); // 抄送
- // $this->phpMailerInstance->addBCC('[email protected]'); // 密送
- // 添加附件,参数2选填
- // $this->phpMailerInstance->addAttachment('README.md', '说明.txt');
- // 标题
- $subject = $subject === '' ? mb_substr($content, 0, 12) . '...' : $subject;
- $this->phpMailerInstance->Subject = $subject;
- /**
- * 正文
- * 使用 html 文件内容作为正文,其中的图片将被 base64 编码,另确保 html 样式为内联形式,且某些样式可能需要 !important 方能正常显示,
- * msgHTML 方法的第二个参数指定 html 内容中图片的路径,在转换时会拼接 html 中图片的相对路径得到完整的路径,最右侧无需“/”,PHPMailer
- * 源码里有加。 css 中的背景图片不会被转换,这是 PHPMailer 已知问题,建议外链
- * 此处也可替换为:
- * $this->phpMailerInstance->isHTML(true); // 设为html格式
- * $this->phpMailerInstance->Body = '正文'; // 支持html
- * $this->phpMailerInstance->AltBody = 'This is an HTML-only message. To view it, activate HTML in your email application.'; // 纯文本消息正文。不支持html预览的邮件客户端将显示此预览消息,其它情况将显示正常的body
- */
- if ($type === 1) {
- $template = file_get_contents(RESOURCES_PATH . '/mail/notice.html');
- $message = sprintf($template, $content);
- } else if ($type === 2) {
- $template = file_get_contents(RESOURCES_PATH . '/mail/successful_renewal.html');
- $realData = [
- $data['username'],
- $data['renewalSuccessArr'] ? sprintf('续期成功:%s<br>', $this->genDomainsHtml($data['renewalSuccessArr'])) : '',
- $data['renewalFailuresArr'] ? sprintf('续期出错:%s<br>', $this->genDomainsHtml($data['renewalFailuresArr'])) : '',
- $this->genDomainStatusHtml($data['domainStatusArr'])
- ];
- $message = $this->genMessageContent($realData, $template);
- } else if ($type === 3) {
- $template = file_get_contents(RESOURCES_PATH . '/mail/no_renewal_required.html');
- $realData = [
- $data['username'],
- $this->genDomainStatusHtml($data['domainStatusArr'])
- ];
- $message = $this->genMessageContent($realData, $template);
- } else {
- throw new \Exception(lang('error_msg.100003'));
- }
- $this->phpMailerInstance->msgHTML($message, APP_PATH . '/mail');
- try {
- if (!$this->phpMailerInstance->send()) {
- throw new MailException($this->phpMailerInstance->ErrorInfo);
- }
- return true;
- } catch (\Exception $e) {
- system_log('邮件发送失败:' . $e->getMessage());
- return false;
- }
- }
- }
|