Laravel5.* 使用Smtp发送邮件以及常见报错解决(腾讯企业邮箱、163、QQ、Gmail 等)

Song5052 次浏览0个评论2017年07月20日

一、快速解决邮件发送

Laravel 提供了非常简单的邮件发送 API,但是文档却不是太清晰,再加上它采用传递闭包(回调函数)的方式调用,导致邮件发送的使用门槛偏高。看文档也是云里雾里,那我们来简单的来讲一下发送邮件,只需要3步即可,

1、有一个发送邮箱账号和密码:

无论是什么邮箱,要发送邮件,必须要开启IMAP/SMTP服务和POP/SMTP服务,企业邮箱是默认开启的,直接使用即可

2、修改.env文件的配置,我们这里以腾讯企业邮箱为例:
MAIL_DRIVER=smtp
MAIL_HOST=smtp.exmail.qq.com
MAIL_PORT=465
MAIL_USERNAME=user@company.com
MAIL_PASSWORD=password
MAIL_ENCRYPTION=ssl

driver用于配置默认的邮件发送驱动,MAIL_HOST是邮箱所在主机,MAIL_PORT为发送端口,MAIL_USERNAME为发送邮箱,MAIL_PASSWORD为邮箱密码

3、发送测试邮件
Mail::raw('test mail', function ($m) {
            $m->from('1@earnp.com', 'User');
            $m->to('71@qq.com')->subject('test email');
});

好的,到这里邮件就发送成功了,注意使用前要use Mail一下,接下来深入解读

二、深入解读

1、配置文件

Laravel集成了SwiftMailer库进行邮件发送,邮件配置文件位于config/mail.php:

return [
    // port用于配置邮箱发送服务端口号,比如一般默认值是25,但如果设置SMTP使用SSL加密,该值为465。
    'driver' => env('MAIL_DRIVER', 'smtp'),
    // host是邮箱所在主机,比如我们使用163邮箱,对应值是smtp.163.com,使用QQ邮箱的话,对应值是smtp.qq.com。
    'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
    // port用于配置邮箱发送服务端口号,比如一般默认值是25,但如果设置SMTP使用SSL加密,该值为465。
    'port' => env('MAIL_PORT', 587),
    // from配置项包含address和name,前者表示发送邮箱,后者表示发送邮件使用的用户名。
    'from' => ['address' => null, 'name' => null],
    // encryption表示加密类型,可以设置为null表示不使用任何加密,也可以设置为tls/ssl。
    'encryption' => env('MAIL_ENCRYPTION', 'tls'),
    // username表示邮箱账号,比如yaojinbu@163.com
    'username' => env('MAIL_USERNAME'),
    // password表示上述邮箱登录对应登录密码。
    'password' => env('MAIL_PASSWORD'),
    // sendmail是在设置driver为sendmail时使用,用于指定sendmail命令路径。
    'sendmail' => '/usr/sbin/sendmail -bs',
    // pretend用于配置是否将邮件发送记录到日志中,默认为false则发送邮件不记录日志,如果为true的话只记录日志不发送邮件,这一配置在本地开发中调试时很有用。
    'pretend' => false,
]
2、简单邮件发送实现

在该控制器中添加邮件发送动作send(),我们使用Mail门面的send方法发送邮件,我们先发送一个最简单的邮件:

<?php

namespace App\Http\Controllers;
use Mail;

class MailController extends Controller
{
    public function send()
    {
        $flag = Mail::send('emails.test',['name'=>'Laravel学习网'],function($message){
            $to = '123@qq.com';
            $message ->to($to)->subject('测试邮件');
        });
        if($flag){
            echo '发送邮件成功,请查收!';
        }else{
            echo '发送邮件失败,请重试!';
        }
    }
}

Mail::send需要传递三个参数,第一个是邮件视图,第二个是传入视图的数据,第三个是一个闭包,该闭包中定义了收件人、抄送人(如果有的话)、邮件主题、附件等信息。邮件的主体内容位于局部视图中,下面我们就来定义这个局部视图,在resources/views/emails目录下新建test.blade.php,编辑其内容如下:

{{$name}},这是一封测试邮件

运用上面的路由调用控制器即可收到邮件了

3、更简单的纯文本邮件发送

上面的示例仅仅是发送一个字符串,对于纯文本字符串邮件发送,还有更简单的方法:

Mail::raw('这是一封测试邮件', function ($message) {
    $to = '123@qq.com';
    $message ->to($to)->subject('测试邮件');
});

这样的话无需创建视图即可完成邮件发送。

4、发送带附件的邮件(中文乱码解决)

当然,邮件内容往往不仅仅是纯文本这么简单,有时候我们会在邮件中加上附件,那么这该如何实现呢?

$flag = Mail::send('emails.test',['name'=>$name],function($message){
    $to = '123@qq.com';
    $message->to($to)->subject('测试邮件');

    $attachment = storage_path('app/files/test.doc');
    //在邮件中上传附件
    $message->attach($attachment,['as'=>'测试文档.doc']);
});

从代码可知我们使用闭包中$message实例上的attach方法上传附件,该方法第一个参数是附件地址,第二个参数是一些额外参数,这里我们通过as指定附件在邮件中的显示名称。

注:需要注意的是$message实际上是Illuminate\Mail\Message的实例,我们可以在$message上调用Message类的所有方法。 运行陆游,这样在收件箱中可以看到附件,但附件名称出现中文乱码,解决办法如下:

$message->attach($attachment,['as'=>"=?UTF-8?B?".base64_encode('测试文档')."?=.doc"]);
5、发送带图片的邮件

除了附件之外,有时候为了让邮件内容更丰富,还会在邮件内容中插入图片,我们固然可以在邮件视图中硬编码写入图片路径,但是这显然很笨重,灵活性很差,Laravel为我们提供了便捷方法——在视图中使用$message上的embed方法:

{{$name}},这是一封测试邮件
<br>
<img src="{{$message->embed($imgPath)}}">

这里的$message就是上述邮件发送闭包中的$message,Laravel内部自动将该变量传递到邮件视图。当然我们还需要在控制器动作中传入$imgPath变量;同时,我们也可以直接使用<img src="1.png">这种类型发送邮件哦:

$name = 'Laravel学习网';
$imgPath = 'http://host.com/1.jpg';
$flag = Mail::send('emails.test',['name'=>$name,'imgPath'=>$imgPath],function($message){
    $to = '123@qq.com';
    $message->to($to)->subject('测试邮件');

    $attachment = storage_path('app/files/test.doc');
    //在邮件中上传附件
    $message->attach($attachment,['as'=>"=?UTF-8?B?".base64_encode('测试文档')."?=.doc"]);
});

在浏览器中访问http://laravel.app:8000/mail/send发送邮件,邮件发送成功后去收件箱查看,图片已经插入到邮件内容中。

embedData

此外还支持发送原生的图片数据到邮件中,即将本地图片读取到内存然后渲染到邮件视图,这可以通过$message上的embedData实现。

首先我们修改控制器动作如下:

$name = 'Laravel学习网';
//$imgPath = 'http://host.com/1.jpg';
$image = Storage::get('images/test.jpg');
$flag = Mail::send('emails.test',['name'=>$name,'image'=>$image],function($message){
    $to = '123@qq.com';
    $message->to($to)->subject('测试邮件');

    $attachment = storage_path('app/files/test.doc');
    //在邮件中上传附件
    $message->attach($attachment,['as'=>"=?UTF-8?B?".base64_encode('测试文档')."?=.doc"]);
});

记得在MailController顶部加上use Storage,然后修改邮件视图test.blade.php如下:

{{$name}},这是一封测试邮件
<br>
<img src="{{$message->embedData($image,'LaravelAcademy.jpg')}}">

最后去浏览器中访问http://laravel.app:8000/mail/send发送邮件,邮件发送成功去收件箱查看邮件内容

如果你是Laravel 6.*+可以参考:laravel 6. 7.发送邮件

提交评论

请登录后评论

用户评论

    当前暂无评价,快来发表您的观点吧...

更多相关好文

    当前暂无更多相关好文推荐...