-
如果是基于 API 的驱动,需要安装 Guzzle HTTP 库
composer require guzzlehttp/guzzle
,不过遗憾的是,好像 Mailgun 驱动、SparkPost 驱动、SES 驱动在国内都不可用,所以我们用 SMTP 服务器形式 -
一些配置,ENV里面配置,也可以在
config.mail
里面设置
# Laravel自带的SMTP发送邮件
MAIL_DRIVER=smtp # 驱动
MAIL_HOST=smtp.qq.com # 邮箱SMTP地址,这个不同厂商地址不同
MAIL_PORT=465 # 端口
MAIL_USERNAME=673996019@qq.com # 用于发送邮件的邮箱
MAIL_PASSWORD=xxxxxxxxxxx # 密码,如果是QQ邮箱,就要填写授权密码,163邮箱好像也是授权密码
MAIL_FROM_NAME=舒孝元邮件测试 # 发件人名称
MAIL_FROM_ADDRESS=673996019@qq.com # 默认发送地址,这个还必须和 MAIL_USERNAME 一样,不然会报错
MAIL_ENCRYPTION=ssl # SSL 协议
直接在控制器里面开撸,在控制器里面引入:use Illuminate\Support\Facades\Mail;
,具体可以查看这个类 \vendor\laravel\framework\src\Illuminate\Support\Testing\Fakes\MailFake.php
简单粗暴的演示,直接在控制器里面开撸
发送纯文本邮件、视图模板、上传附件等
<?php
/**
* Created by PhpStorm.
* User: xiaoyuan.shu
* Date: 2019/11/27
* Time: 13:50
*/
namespace App\Http\Controllers\Test;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Mail;
class EmailController extends Controller {
/**
* 发送纯文本邮件
*/
public function text() {
$content = '这个是用 Laravel 的邮件类发送的纯文本邮件,试试看html标签会不会解析:<html><body><h1>舒孝元</h1></body></html>';
// 接收一个文本消息和一个回调函数
$data = Mail::raw($content, function ($message) {
$to = env('Admin_EMAIL');
$message->to($to)->subject('邮件主题:纯文本邮件测试');
});
// 返回值:null,应该不是这么获取的
// dd($data);// null
// 这个返回也是个空数组
dd(Mail::failures());
}
/**
* 通过视图模板发送
* 注意,第一个参数为你的视图模板,第二个参数为一个回调函数,里面可以配置一些东西
* 如果是视图模板的话,{{ $data }} 会转义html实体标签
*/
public function view() {
$image_url = 'https://i.vgy.me/U3qzgx.png';
$content = '这个是用 Laravel 的邮件类发送的,主要测试图片+内容';
$data = Mail::send('emails.shu', [
'image' => $image_url,
'data' => $content
], function ($message) {
$to = env('Admin_EMAIL');
$message->to($to)->subject('邮件主题:测试图片');
});
//返回值,null
// dd($data);// null
// 这个返回也是个空数组
dd(Mail::failures());
}
/**
* 测试上传附件
*/
public function enclosure() {
$image_url = 'https://i.vgy.me/U3qzgx.png';
$content = '这个是用 Laravel 的邮件类发送的,主要测试附件+图片+内容';
Mail::send('emails.shu', [
'image' => $image_url,
'data' => $content
], function ($message) {
$to = env('Admin_EMAIL');
$message->to($to)->subject('邮件测试:附件');
$attachment = '/usr/share/nginx/html/laravel_dev/public/git-webhook_log.txt';
// 在邮件中上传附件
// 已经实践证明了,这个中文会乱码。
// $message->attach($attachment, ['as' => 'git拉取日志.txt']);
// 解决乱码
$message->attach($attachment,['as'=>"=?UTF-8?B?".base64_encode('git拉取日志')."?=.txt"]);
});
// 这个返回也是个空数组
dd(Mail::failures());
}
}
视图模板
<html>
<head>
<title>测试邮件</title>
</head>
<body>
<h1>这个是H1标签,下面是div里面的信息</h1>
<div>
{{ $data }}
</div>
<img src="{{ $image }}" alt="test">
</body>
</html>
来点优雅的搞法
生成邮件类
执行 php artisan make:mail WarningMail
,在需要的地方调用就行,类路径 app/Mail
<?php
namespace App\Mail;
use App\Models\Wx\WxConfig;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;
class WarningMail extends Mailable {
use Queueable, SerializesModels;
/**
* 可以通过这个公共属性完成数据传递,在视图中可以直接用这个字段
* 另外一种就可以直接通过 with 来完成数据传递
* @var string
*/
public $data;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct(WxConfig $config) {
$this->data = $config;
}
/**
* Build the message.
* 更多的还是参考我写的那个简单粗暴的类,很多共通之处
*
* @return $this
*/
public function build() {
return $this
// 发件人,如果没这个就采用全局默认的发送地址
->from(env('MAIL_FROM_ADDRESS'))
// 视图路径
->view('view.emails.warning')
// 附件上传
// 解决中文乱码问题
// ->attach($attachment,['as'=>"=?UTF-8?B?".base64_encode('git拉取日志')."?=.txt"]);
->attach('/www/error.log',[
'as' => 'error.log',
// 指定 MIME 类型,其实没必要设置
'mime' => 'application/pdf',
]);
// text 方法接收一个用于渲染邮件内容的模板名,你既可以定义纯文本消息也可以定义 HTML 消息
// ->text('emails.orders.shipped_plain');
}
}
发送邮件
在需要发送邮件的地方 Mail::to($request->user())->send(new WarningMail($config));
在浏览器中先预览邮件
// 预览邮件
Route::any('/mailable', function () {
$config = App\Models\Wx\WxConfig::find(1);
// 直接在浏览器预览邮件样式
return new App\Mail\WarningMail($config);
// 在不发送可邮寄类的情况下捕获其 HTML 内容,内容以字符串方式返回
return (new App\Mail\WarningMail($config))->render();
});
邮件队列
其实没什么好说的,就是在发送邮件的时候入队列,需要提前准备好队列
Mail::to($request->user())
->cc($moreUsers) // 抄送
->bcc($evenMoreUsers)// 暗抄送
->queue(new WarningMail($config));
事件
Laravel 会在发送邮件消息前触发两个事件
- MessageSending 事件在消息发送前触发
- MessageSent 事件在消息发送后触发
需要注意的是这两个事件是在邮件被发送前后触发,而不是推送到队列时,你可以在 EventServiceProvider 中注册对应的事件监听器:
protected $listen = [
'Illuminate\Mail\Events\MessageSending' => [
'App\Listeners\LogSendingMessage',
],
'Illuminate\Mail\Events\MessageSent' => [
'App\Listeners\LogSentMessage',
],
];