构建自己的PHP框架(邮件发送)

 

完整项目地址:https://github.com/Evai/Aier

 

 

我们采用 'nette/mail' 包作为我们的邮件发送基础模块,在它的基础上封装一个 'Mail' 类,暴露出简洁的 API 给控制器使用,下面我们正式开始。

引入 'nette/mail' 包,修改 'composer.json':

"require": {

  "codingbean/macaw": "dev-master",

  "illuminate/database": "*",

  "filp/whoops": "*",

  "nette/mail": "*"

}

 

运行 'composer update',等待安装完成。'nette/mail' 的文档位于:http://doc.nette.org/en/2.2/mailing 让我们阅读它,然后设计 Mail 类:

新建 'services/Mail.php' 文件,内容如下:

<?php

use Nette\Mail\Message;

date_default_timezone_set('PRC');

/**
 * Mail
 */

class Mail

{

    public $config;

    // [String] e-mail

    protected $from;

    // [Array] e-mail list

    protected $to;

    protected $title;

    protected $body;

    protected $mail;

    /**
     * Mail constructor.
     * @param $to
     */
    function __construct($values)

    {
        $this->mail = new Message;

        $this->config = require_once BASE_PATH . '/config/mail.php';

        $this->mail->setFrom($this->config['username']);

        if ( !is_array($values) ) {

            $values = [$values];

        }

        foreach ($values as $email) {

            $this->mail->addTo($email);

        }

    }

    /**
     * 发件人
     * @param null $from
     * @return $this
     */
    public function from($from=null)

    {

        if ( !$from ) {

            throw new InvalidArgumentException("邮件发送地址不能为空!");

        }

        $this->mail->setFrom($from);

        return $this;

    }

    /**
     * 收件人
     * @param null $to
     * @return Mail
     */
    public static function to($values=null)

    {

        if ( !$values ) {

            throw new InvalidArgumentException("邮件接收地址不能为空!");

        }

        return new Mail($values);

    }

    /**
     * 邮件标题
     * @param null $title
     * @return $this
     */
    public function title($title=null)

    {

        if ( !$title ) {

            throw new InvalidArgumentException("邮件标题不能为空!");

        }

        $this->mail->setSubject($title);

        return $this;

    }

    /**
     * 邮件内容
     * @param null $content
     * @return $this
     */
    public function content($content=null)

    {

        if ( !$content ) {

            throw new InvalidArgumentException("邮件内容不能为空!");

        }

        $this->mail->setHTMLBody($content);

        return $this;

    }

    function __destruct()
    {

        $mailer = new Nette\Mail\SmtpMailer($this->config);

        $mailer->send($this->mail);

    }

}

 

Mail 类和 View 类工作的方式基本一致,在homecontroller.php中添加:

function mail()
    {
        Mail::to(['xxxxx@qq.com'])
            ->from('Evai <xxx@163.com>')
            ->title('Hello World')
            ->content('<h1>Hello World !</h1>');
        echo '发送邮件成功';
    }

 

新建 'MFFC/config/mail.php',请自行替换邮件地址和密码:

<?php

return [

    'host' => 'smtp.163.com',

    'username' => 'Evai <xxx@163.com>',

    'password' => 'password',

    'secure' => '',

    'context' =>  [
        'ssl' => [
           
        ],
    ],

];

 

routs.php中添加一条路由:
Route::get('mail', 'HomeController@mail');
 

OK,准备的差不多了,运行 'composer dump-autoload' 把 Mail 类加入自动加载,刷新页面!

 

如果你看到以上页面,恭喜你!邮件发送成功了!

赶快去检查一下收件箱有木有邮件!这次页面加载可能会稍慢,因为邮件是同步发送的。异步的队列系统我们会在以后讲到。

分析

邮件发送的整体流程想必大家已经轻车熟路了,现在主要叙述一下 Mail 类的设计过程:

  1. 邮件发送的核心参数是 '目标地址',即邮件要发送到的 E-mail 地址,所以我们设计 Mail::to('oo@xx.me') 作为发送的 '触发 API'。
  2. 目前我们采用最简单的 'SMTP' 方式发送邮件,文档在 这里。配置文件放置在 'MFFC/config/mail.php' 中,依旧返回一个数组。
  3. Mail 类继承了 'Nette\Mail\Message' 类。'Mail::to()' 的时候创建一个 Mail 类的实例(对象)并返回,这时候其实 'BaseController' 中的析构函数中的代码已经会被触发并处理这个对象了。默认的发送人是从配置文件中读取的 'username'。
  4. 'Mail::to()' 支持 字符串 或者数组作为参数,可以一次发送一封或多封邮件。
  5. 'from()'、'title()' 和 'content()' 方法用于丰富邮件内容。'content()' 方法可以直接传递 HTML 代码。
  6. 'from()' 配置不一定都能够成功,部分邮件服务商不支持修改发送人地址。
  7. 这个变量全部组装完成后,被赋值给控制器的 '$mail' 成员变量,然后被析构函数处理,邮件被发送,成功后页面代码被发送回客户端,流程结束。
posted @ 2016-12-23 09:37  Evai  阅读(704)  评论(0编辑  收藏  举报