1.安装composer
2.设置composer为全局变量
3.进入项目目录
4.在命令行执行:composer require phpmailer/phpmailer
5.创建Test.controller控制器文件,代码如下:
<?php
/**
* Created by PhpStorm.
* User: dyane
* Date: 2019/3/29
* Time: 16:38
*/
namespace app\system_admin\controller;
use think\Request;
class Test
{
/**
* 邮件发送页面
* @return mixed
*/
public function index()
{
return view('email/index');
}
/**
* 发送邮件
*/
public function send()
{
if($this->request->isPost()) {
$param = $this->request->param();
//判断收件人
if (empty($param['addressee'])) {
return json(['code' => 400, 'msg' => '收件人地址不能为空!']);
die;
}
//判断邮件主题和内容必须存在一个
if (empty($param['title']) && empty($param['content'])) {
return json(['code' => 400, 'msg' => '主题和内容必须填写一个!']);
die;
}
//获取收件人地址
$addressee = $param['addressee'];
//验证邮箱
$addressee = $this->checkEmailStr($addressee);
//获取主题或内容
if (!empty($param['title'])) {
$title = htmlspecialchars($param['title']);
} else {
$title = ' ';
}//空格不能去,否则发送失败
if (!empty($param['content'])) {
$content = $param['content'];
} else {
$content = ' ';
}//空格不能去,否则发送失败
//获取抄送人地址
if (!empty($param['copyperson'])) {
$copyerArray = $this->checkEmailStr($param['copyperson']);
} else {
$copyerArray = '';
}
//获取密送人地址
if (!empty($param['secretagent'])) {
$sercreterArray = $this->checkEmailStr($param['secretagent']);
} else {
$sercreterArray = '';
}
//获取附件
if (!empty($param['files_list'])) {
$filesArray = $this->checkFiles($param['files_list']);
} else {
$filesArray = '';
}
$res = $this->sendEmail($addressee,$copyerArray,$sercreterArray,$filesArray,$title,$content);
//反馈发送结果
if($res){
if (!empty($filesArray)) {
$this->deleteOldEmaileFiles($filesArray);
}
echo json_encode(['code' => 200, 'msg' => '发送成功!']);die;
}else{
echo json_encode(['code' => 400, 'msg' => '发送失败!']);die;
}
}
}
/**
* 发送邮件
* @param $addressee
* @param $copyerArray
* @param $sercreterArray
* @param $filesArray
* @param $title
* @param $content
*/
protected function sendEmail($addressee,$copyerArray,$sercreterArray,$filesArray,$title,$content)
{
//使用发送邮件类
$mail = new EmailYX();
//设置收件人
$mail->setManyAddressee($addressee);
if(!empty($copyerArray)){$mail->setManyCC($copyerArray);}
if(!empty($sercreterArray)){$mail->setManyBCC($sercreterArray);}
if(!empty($filesArray)){$mail->setManyAttachment($filesArray);}
//设置主题和内容
$mail->setContent($title,$content);
//发送邮件
$res = $mail->send();
return $res;
}
/**
* 发送成功之后删除附件文件
* @param $filesArray
*/
protected function deleteOldEmaileFiles($filesArray)
{
foreach ($filesArray as $key => $value){
$path = ROOT_PATH . 'public'.$value;
if(file_exists($path)){
unlink($path);
}
}
}
/**
* 验证邮箱是否正确
* @param $str
*/
protected function checkEmailStr($emailStr)
{
$toArray = explode(',',$emailStr);
$res = $this->checkManyEmail($toArray);
return $res;
}
/**
* 判断多组字符窜邮箱是否有不正确的邮箱存在
* @param $toArray
* @return bool
*/
protected function checkManyEmail($toArray)
{
foreach ($toArray as $key => $value){
$check = $this->checkEmail($value);
if(!$check){unset($toArray[$key]);}
}
return $toArray;
}
/**
* 正则验证邮箱是否合法
* @param $email
* @return false|int
*/
protected function checkEmail($email)
{
// $pregEmail='/^[a-zA-Z0-9]+([-_.][a-zA-Z0-9]+)*@([a-zA-Z0-9]+[-.])+([a-z]{2,5})$/ims';
$pregEmail = '/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/';
$res = preg_match($pregEmail,$email);
return $res;
}
/**
* 处理邮件附件字符串
* @param $filesStr
* @return array
*/
protected function checkFiles($filesStr)
{
$filesStr = trim($filesStr);
$filesStr = rtrim($filesStr,',');
$res = explode(',',$filesStr);
return $res;
}
}
6.封装设置邮件发送参数类Email.controller文件,代码如下:
<?php
/**
* Created by PhpStorm.
* User: dyane
* Date: 2019-03-21
* Time: 10:10
*/
namespace app\system_admin\controller;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
vendor('autoload.php');
class Email
{
const SMTPDebug = 0;
const HOST = 'smtp.qq.com';
const USERNAME = '你的QQ号@qq.com';
const PASSOWRD = 'SMTP授权码,非QQ邮箱密码';
const CHARSET = 'UTF-8';
const SMTPAUTH = true;
const ISHTML = true;
const SMTPSECURE = 'ssl';
const PORT = 465;
static $addressee = array();
static $sender = array('a'=>'你的QQ号@qq.com','n'=>'测试系统邮件');
static $cc = array();
static $bcc = array();
static $attachment= array();
static $title = '';
static $body = '';
static $altBody = '';
private $mail = null;
function __construct()
{
$this->mail = new PHPMailer();
}
//初始化参数
public function start()
{
$this->mail->SMTPDebug = self::SMTPDebug;
$this->mail->Host = self::HOST;
$this->mail->CharSet = self::CHARSET;
$this->mail->SMTPAuth = self::SMTPAUTH;
$this->mail->Username = self::USERNAME;
$this->mail->Password = self::PASSOWRD;
$this->mail->SMTPSecure = self::SMTPSECURE;
$this->mail->Port = self::PORT;
if(self::SMTPSECURE == 'ssl'){
$this->mail->SMTPOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
}
$this->mail->isHTML(self::ISHTML);
}
//发送人
public function setSender($address,$senderName = '')
{
self::$sender['a'] = $address;
self::$sender['n'] = $senderName;
}
//收件人回复的地址
public function setReplyAddress($address = '', $replayName = '')
{
self::$sender['a'] = $address;
self::$sender['n'] = $replayName;
}
//单个接收人
public function setAddressee($address,$recName = '')
{
call_user_func_array([$this, 'setAddress'],['addressee',$address, $recName]);
}
//多个接收人
public function setManyAddressee($array)
{
array_walk($array,function($v, $k){
$this->setAddressee($v);
});
}
//抄送单个
public function setCC($address = '', $name = '')
{
call_user_func_array([$this, 'setAddress'],['cc',$address, $name]);
}
//抄送多个
public function setManyCC($array)
{
array_walk($array,function($v, $k){
$this->setCC($v);
});
}
//暗抄送单个
public function setBCC($address = '', $name = '')
{
call_user_func_array([$this, 'setAddress'],['bcc',$address, $name]);
}
//暗抄送单个
public function setManyBCC($array)
{
array_walk($array,function($v, $k){
$this->setBCC($v);
});
}
//附件单个
public function setAttachment($address, $newName = '')
{
call_user_func_array([$this, 'setAddress'],['attachment',$address, $newName]);
}
//附件多个
public function setManyAttachment($array)
{
array_walk($array,function($v, $k){
$this->setAttachment($v);
});
}
public function setAddress($param, $address, $name)
{
array_push(self::${$param}, [
'a'=>$address,'n'=>$name
]
);
}
public function setContent($title = '', $body='', $table = '', $altBody='')
{
self::$title = $title;
if($table) $body = $body.'<br/>'.$table;
self::$body = $body;
self::$altBody = $altBody;
}
//发送邮件
public function send()
{
$res = false;
try {
$this->mail->isSMTP();
$this->start();
$this->mail->setFrom(self::$sender['a'], self::$sender['n']);
$this->mail->addReplyTo(self::$sender['a'], self::$sender['n']);
$this->addAddress(self::$addressee,'addAddress');
$this->addAddress(self::$bcc,'addBCC');
$this->addAddress(self::$cc,'addCC');
$this->addAddress(self::$attachment,'addAttachment');
$this->mail->Subject = self::$title;
$this->mail->Body = self::$body;
$this->mail->AltBody = self::$altBody;
$result = $this->mail->send();
$this->mail->isSMTP();
$result && $res = true;
}catch (Exception $e){
// YXLog::error('Mailer Error: ' . $this->mail->ErrorInfo);
}
return $res;
}
public function addAddress($address,$func)
{
foreach ($address as $item){
$item['a'] && $this->mail->{$func}($item['a'], $item['n']);
}
}
public function setTable($th = array(), $data = array(), $title = '')
{
$table_data = '<table cellpadding="2" cellspacing="0" style="font-size: 12px;">';
$title && $table_data .= '<caption>'.$title.'</caption>';
$table_data .= $this->setTh($th);
$table_data .= $this->setTd($data);
$table_data .= '</table>';
return $table_data;
}
public function setTd($td = array())
{
$data = '';
foreach ($td as $item){
$data .= '<tr>';
foreach ($item as $value){
$data .= '<td>'.$value.'</td>';
}
$data .= '</tr>';
}
return $data;
}
public function setTh($th = array())
{
$data = '<tr>';
foreach ($th as $item){
$data .='<th>'.$item.'</th>';
}
$data .= '</tr>';
return $data;
}
}
7.前段页面代码,前端本人使用的是layui框架:
{include file='common/head'}
<div style="overflow-x: hidden;width: 96%;margin: auto;padding-top: 1rem;">
<blockquote class="layui-elem-quote"><span>测试模块 邮件发送 (<span style="color: red;margin-right: 0.2rem;font-size: 20px;">*</span>为必填 | 多个邮箱之间用","号隔开)</span></blockquote>
<div class="demoTable layui-form" action="" method="post" style="margin-top: 3rem">
<div class="layui-form-item">
<label class="layui-form-label"><span style="color: red;margin-right: 0.2rem;font-size: 20px">*</span>收件人</label>
<div class="layui-input-block">
<input type="text" lay-verify="required" name="addressee" placeholder="请输入收件人邮箱" autocomplete="off" class="layui-input">
<button class="layui-btn layui-btn-radius chao" style="margin-top:0.5rem">抄送</button>
<button class="layui-btn layui-btn-radius layui-btn-normal mi" style="margin-top:0.5rem">密送</button>
</div>
</div>
<div class="layui-form-item input-chao" style="display: none">
<label class="layui-form-label">抄送人</label>
<div class="layui-input-block">
<input type="text" name="copyperson" placeholder="请输入抄送人邮箱" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item input-mi" style="display: none;">
<label class="layui-form-label">密送人</label>
<div class="layui-input-block">
<input type="text" name="secretagent" placeholder="请输入密送人邮箱" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">主题</label>
<div class="layui-input-block">
<input type="text" name="title" placeholder="请输入邮件主题" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">附件</label>
<div class="layui-input-block">
<blockquote class="layui-elem-quote layui-quote-nm" style="margin-top: 10px;">
<div id="uploadImg" class="layui-upload">
<button type="button" class="layui-btn" id="upload">选择文件</button>
<div class="layui-upload-list">
<table class="layui-table" style="text-align: center;">
<thead>
<tr>
<th style="text-align: center;">文件名</th>
<th style="text-align: center;">大小</th>
<th style="text-align: center;">状态</th>
<th style="text-align: center;">操作</th>
</tr>
</thead>
<tbody id="imgList"></tbody>
</table>
</div>
<button type="button" class="layui-btn" id="startUpload">开始上传</button>
</div>
<input type="text" name="files_list" id="imgInput" style="display: none;">
</blockquote>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">邮件内容</label>
<div class="layui-input-block" style="width: 1220px;height: 300px">
<textarea id="demo" name="content" lay-verify="content" lay-verify="required"></textarea>
</div>
</div>
<div class="layui-form-item" style="margin-top: 2rem">
<div class="layui-input-block">
<button class="layui-btn" lay-submit="" lay-filter="demo1">发送</button>
</div>
</div>
</div>
</div>
{include file='common/footer'}
<script>
layui.use(['table', 'form', 'element', 'upload', 'layedit'], function () {
var table = layui.table;
var form = layui.form;
var element = layui.element;
var $ = layui.jquery;
var upload = layui.upload;
var layedit = layui.layedit;
// //创建一个编辑器
layedit.set({
uploadImage:{
url:'{:url("Upload/editUpload")}',
type:'post'
}
});
var editIndex = layedit.build('demo', {
tool: [
'strong' //加粗
,'italic' //斜体
,'underline' //下划线
,'del' //删除线
,'|' //分割线
,'left' //左对齐
,'center' //居中对齐
,'right' //右对齐
,'image'
],
});
//
//自定义验证规则
form.verify({
content: function(value){
layedit.sync(editIndex);
}
});
//多文件列表示例
var demoListView = $('#imgList');
var totalArray = new Array();
var uploadInst = upload.render({
elem: '#upload' //绑定元素
, url: '{:url("Upload/file_images")}' //上传接口
, accept: 'file' // 允许上传的文件类型
// , acceptMime: 'image/jpg,image/png' // (只支持jpg和png格式,多个用逗号隔开),
, size: 5120 // 最大允许上传的文件大小 单位 KB
, auto: false //选择文件后不自动上传
, bindAction: '#startUpload' //指向一个按钮触发上传
, multiple: true // 开启多文件上传
, number: 6 // 同时上传文件的最大个数
, choose: function (obj) {
console.log(obj)
var files = this.files = obj.pushFile(); //将每次选择的文件追加到文件队列
var arr = Object.keys(files);
totalArray = totalArray.concat(arr);
// 检查上传文件的个数
if (totalArray.length <= 6) {
//读取本地文件
obj.preview(function (index, file, result) {
var tr = $(['<tr id="upload-' + index + '">'
, '<td>'+file.name+'</td>'
, '<td>' + (file.size / 1014).toFixed(1) + 'kb</td>'
, '<td>等待上传</td>'
, '<td>'
, '<button class="layui-btn demo-reload layui-hide">重传</button>'
, '<button class="layui-btn layui-btn-danger demo-delete">删除</button>'
, '</td>'
, '</tr>'].join(''));
//单个重传
tr.find('.demo-reload').on('click', function () {
obj.upload(index, file);
});
//删除
tr.find('.demo-delete').on('click', function () {
delete files[index]; //删除对应的文件
tr.remove();
uploadListIns.config.elem.next()[0].value = ''; //清空 input file 值,以免删除后出现同名文件不可选
});
demoListView.append(tr);
});
} else {
// 超出上传最大文件
layer.msg("上传文件最大不超过6个")
}
}
, done: function (res, index, upload) {
if (res.code == 0) { //上传成功
// 上传成功后将图片路径拼接到input中,多个路径用","分割
var inputVal = document.getElementById("imgInput").value;
var valData = "";
if (inputVal) {
valData = inputVal + "," + res.data.src;
} else {
valData = res.data.src;
}
document.getElementById("imgInput").value = valData;
var tr = demoListView.find('tr#upload-' + index)
, tds = tr.children();
tds.eq(2).html('<span style="color: #5FB878;">上传成功</span>');
tds.eq(3).html(''); //清空操作
return delete this.files[index]; //删除文件队列已经上传成功的文件
}
this.error(index, upload);
}
, error: function (index, upload) {
var tr = demoListView.find('tr#upload-' + index)
, tds = tr.children();
tds.eq(2).html('<span style="color: #FF5722;">上传失败</span>');
tds.eq(3).find('.demo-reload').removeClass('layui-hide'); //显示重传
}
});
var url='{:url("EmailSend/send")}';
form.on('submit(demo1)', function(data){
layer.msg('邮件正在发送中,请稍后.....',{time:2000},function(){
$.post(url,data.field,function (obj) {
if(obj.code==200){
parent.layer.msg(obj.msg, {icon: 6,time: 1000});
window.location.reload();
}
if(obj.code==400){
parent.layer.msg(obj.msg, {icon: 5,time: 1000});
}
},"JSON");
})
});
//抄送人、密送人input框显示
$('.chao').click(function(){
$('.input-chao').css('display','block');
$('.chao').css('display','none');
})
//抄送人、密送人input框显示
$('.mi').click(function(){
$('.input-mi').css('display','block');
$('.mi').css('display','none');
})
});
</script>
</body>
</html>