前言

最近还是比较忙的,上大学第一个学期的下半学期,事情都比较忙,想写很多技术文章和做一些自己的项目开源到github,但是我自己都没有什么时间。我的大部分时间都是拿去学校基础课程的学习啊,还有一些比赛,例如什么《中国大学生服务外包创新创业大赛》之类的,然后我自己目前还在快速学习Java,加入了我们学校的计算机协会,开发的要寄出要求就是用Java进行程序开发,所以我还得在暑假结束之前结束Java基础学习、JavaSE,Spring和SpringBoot等等,所以相对来说比较忙的。

这一篇博文是我打算为了简化我后续的开发,自己构建一个自己的通用框架,这样也可以方便我自己的开发,后续如果框架完善不错,也可能直接将框架以MIT LICENSE开源出来。

在这里,我大概讲述基于PHPMailer构建的一个邮件发送框架和我自己的API标准接口输出框架。

前置知识

因为用到了框架进行开发,为了方便代码的调用,所以在PHP中,需要用到类进行开发操作。所以如果没有学习相对应的面对对象语言的操作,在看这一篇博文可能有一定的难度。

  • 所需内容:
    • PHP
    • 方法
    • 成员变量
    • 限制修饰符
    • PHPMailer
    • PHP与Json相关方面
    • HTML等

邮件发送通用框架开发

前置准备

为了展示方便,我在这里处理操作不包括 namespace 如有需要会根据 protected 有相关知识

创建一个 SendMail.php 文件,随后创建类的内容

1
2
3
class SnedMail {

}

需要进行引用PHPMailer类内部内容,所以需要进行导入,由于不在同一个 namespace 所以不能够直接进行引用

1
2
3
4
5
require_once dirname(__FILE__, 3) . "/class/Mailer/PHPMailer/PHPMailer.php";
require_once dirname(__FILE__, 3) . "/class/Mailer/PHPMailer/Exception.php";
require_once dirname(__FILE__, 3) . "/class/Mailer/PHPMailer/SMTP.php";
// 这是我的发件模板
require_once dirname(__FILE__, 3) . "/class/Mailer/MailTemplate.php";

由于根据我的目录结构,所以获取 dirname(__FILE__,3) 的文件路径,获取当前文件的前三级目录。
由于我只需要实现发件模块,所以只需要引入SMTP以及基础PHPMailer和抛出错误的Exception即可

架构设计

实现系统自动根据SSL证书是否启用安全发送或基础发送(ssl模式与TLS模式),基于此设计函数名 SSLCheck() ,由于这个函数只需要执行主函数时候进行执行,不需要进行外部调用,故进行内部封装,使用 private 。

发送邮件,实现最终邮件的发送,设计函数名 PostMail() ,由于设计时候外部可以直接调用,所以直接使用 public 进行权限设计。

以及设计初始化内容需要进行构造函数。

分布实现

实现最简单的根据SSL设计发件模式。

根据PHPMailer提供的框架,发件需要提供接口以及发件模式,其中TLS对应25,ssl对应465。(不同邮件服务商对应不同的服务,等一会我再说如何处理不同邮件服务商如何修改,不然只对应一个,几乎没有可迁移能力以及客制化操作)

基于此设计,需要设计传入形参类型 string 的 $SmtpType ,用于判断需要监测是返回端口还是返回安全模式;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 检查通信协议是 HTTP 还是 HTTPS
* @param string $Smtp_Type [Port]获取端口值,[Secure]连接模式
* @return mixed|string|null
*/
private function SSLCheck(string $SmtpType)
{
if ($SmtpType == 'Port')
return $_SERVER['SERVER_PORT'] != '443' ? 25 : 465;
elseif ($SmtpType == 'Secure')
return $_SERVER['SERVER_PORT'] != '443' ? "TLS" : "ssl";
else
return null;
}

总实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/*
* Copyright © 2016 - 2023 筱锋xiao_lfeng. All Rights Reserved.
* 开发开源遵循 MIT 许可,若需商用请联系开发者
* https://www.x-lf.com/
*/


namespace Mailer;

require_once dirname(__FILE__, 3) . "/class/Mailer/PHPMailer/PHPMailer.php";
require_once dirname(__FILE__, 3) . "/class/Mailer/PHPMailer/Exception.php";
require_once dirname(__FILE__, 3) . "/class/Mailer/PHPMailer/SMTP.php";
require_once dirname(__FILE__, 3) . "/class/Mailer/MailTemplate.php";

class SendMail
{
public static int $EmailType;
public static string $EmailReceiver;

protected static array $ConfigData;
public static int $ExpTime;
public static string $WebTitle;
protected static ?string $GCode;
protected PHPMailer $Mail;
public static string $SendMailError;
public static string $getDomain;

/**
* @return void 导入文件,无具体返回值
*/
public function __construct()
{
// 文件导入
$Array_ConfigData = null;
$FileData = fopen(dirname(__FILE__, 3) . "/setting.inc.json", 'r');
while (!feof($FileData))
$Array_ConfigData .= fgetc($FileData);
$Array_ConfigData = json_decode($Array_ConfigData, JSON_UNESCAPED_UNICODE);
self::$ConfigData = $Array_ConfigData["Smtp"];
fclose($FileData);
// 参数赋予
self::$ExpTime = $Array_ConfigData["Mail"]['ExpDate'];
self::$WebTitle = $Array_ConfigData["Web"]['Title'];
self::$getDomain = $Array_ConfigData["Web"]['Domain'];

// 导入类
$this->Mail = new PHPMailer(true);
}

/**
* 发件基础内容(调用)
* 说明:
*
* 1. [EmailType(int)] 邮件发送类型
* - [1] 站点注册邮件
* - [2] 站点邮件登录
* @param string $EmailReceiver 邮件接收方(邮箱地址)
* @param int $EmailType 发送邮件类型
* @param string $OtherPush 其他备注内容,例如激活码
* @return bool 邮件发送成功返回 true 否则返回 false
*/
public function PostMail(string $EmailReceiver, int $EmailType, string $OtherPush = null): bool
{
self::$EmailType = $EmailType;
self::$EmailReceiver = $EmailReceiver;
self::$GCode = $OtherPush;

// 尝试邮件发送
try {
// 服务器配置
$this->Mail->CharSet = "UTF-8";
$this->Mail->SMTPDebug = 0;
$this->Mail->isSMTP();
$this->Mail->Host = self::$ConfigData['Host'];
$this->Mail->SMTPAuth = self::$ConfigData['SmtpAuth'];
$this->Mail->Username = self::$ConfigData['Username'];
$this->Mail->Password = self::$ConfigData['Password'];
$this->Mail->SMTPSecure = $this->SSLCheck('Secure');
$this->Mail->Port = $this->SSLCheck('Port');
$this->Mail->setFrom(self::$ConfigData['User'], self::$ConfigData['Name']);
$this->Mail->addAddress($EmailReceiver);
$this->Mail->isHTML(true);

// 发件编写
if ($EmailType == 1) $this->EmailRegister();
else if ($EmailType == 2) $this->EmailLogin();

$this->Mail->send();
return true;
} catch (\Exception $e) {
self::$SendMailError = $this->Mail->ErrorInfo;
return false;
}
}

protected function EmailRegister(): void
{
$this->Mail->Subject = self::$ConfigData['Name'] . ' - 站点注册'; // 邮箱标题
$this->Mail->Body = MailTemplate::Templates(self::$GCode);
}

protected function EmailLogin(): void
{
$this->Mail->Subject = self::$ConfigData['Name'] . ' - 邮箱登录验证码'; // 邮箱标题
$this->Mail->Body = MailTemplate::Templates();
}
}