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

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

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

  1. "require": {
  2.  
  3. "codingbean/macaw": "dev-master",
  4.  
  5. "illuminate/database": "*",
  6.  
  7. "filp/whoops": "*",
  8.  
  9. "nette/mail": "*"
  10.  
  11. }

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

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

  1. <?php
  2.  
  3. use Nette\Mail\Message;
  4.  
  5. date_default_timezone_set('PRC');
  6.  
  7. /**
  8. * Mail
  9. */
  10.  
  11. class Mail
  12.  
  13. {
  14.  
  15. public $config;
  16.  
  17. // [String] e-mail
  18.  
  19. protected $from;
  20.  
  21. // [Array] e-mail list
  22.  
  23. protected $to;
  24.  
  25. protected $title;
  26.  
  27. protected $body;
  28.  
  29. protected $mail;
  30.  
  31. /**
  32. * Mail constructor.
  33. * @param $to
  34. */
  35. function __construct($values)
  36.  
  37. {
  38. $this->mail = new Message;
  39.  
  40. $this->config = require_once BASE_PATH . '/config/mail.php';
  41.  
  42. $this->mail->setFrom($this->config['username']);
  43.  
  44. if ( !is_array($values) ) {
  45.  
  46. $values = [$values];
  47.  
  48. }
  49.  
  50. foreach ($values as $email) {
  51.  
  52. $this->mail->addTo($email);
  53.  
  54. }
  55.  
  56. }
  57.  
  58. /**
  59. * 发件人
  60. * @param null $from
  61. * @return $this
  62. */
  63. public function from($from=null)
  64.  
  65. {
  66.  
  67. if ( !$from ) {
  68.  
  69. throw new InvalidArgumentException("邮件发送地址不能为空!");
  70.  
  71. }
  72.  
  73. $this->mail->setFrom($from);
  74.  
  75. return $this;
  76.  
  77. }
  78.  
  79. /**
  80. * 收件人
  81. * @param null $to
  82. * @return Mail
  83. */
  84. public static function to($values=null)
  85.  
  86. {
  87.  
  88. if ( !$values ) {
  89.  
  90. throw new InvalidArgumentException("邮件接收地址不能为空!");
  91.  
  92. }
  93.  
  94. return new Mail($values);
  95.  
  96. }
  97.  
  98. /**
  99. * 邮件标题
  100. * @param null $title
  101. * @return $this
  102. */
  103. public function title($title=null)
  104.  
  105. {
  106.  
  107. if ( !$title ) {
  108.  
  109. throw new InvalidArgumentException("邮件标题不能为空!");
  110.  
  111. }
  112.  
  113. $this->mail->setSubject($title);
  114.  
  115. return $this;
  116.  
  117. }
  118.  
  119. /**
  120. * 邮件内容
  121. * @param null $content
  122. * @return $this
  123. */
  124. public function content($content=null)
  125.  
  126. {
  127.  
  128. if ( !$content ) {
  129.  
  130. throw new InvalidArgumentException("邮件内容不能为空!");
  131.  
  132. }
  133.  
  134. $this->mail->setHTMLBody($content);
  135.  
  136. return $this;
  137.  
  138. }
  139.  
  140. function __destruct()
  141. {
  142.  
  143. $mailer = new Nette\Mail\SmtpMailer($this->config);
  144.  
  145. $mailer->send($this->mail);
  146.  
  147. }
  148.  
  149. }

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

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

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

  1. <?php
  2.  
  3. return [
  4.  
  5. 'host' => 'smtp.163.com',
  6.  
  7. 'username' => 'Evai <xxx@163.com>',
  8.  
  9. 'password' => 'password',
  10.  
  11. 'secure' => '',
  12.  
  13. 'context' => [
  14. 'ssl' => [
  15.  
  16. ],
  17. ],
  18.  
  19. ];
  1. routs.php中添加一条路由:
  1. Route::get('mail', 'HomeController@mail');
  1.  

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' 成员变量,然后被析构函数处理,邮件被发送,成功后页面代码被发送回客户端,流程结束。

构建自己的PHP框架(邮件发送)的更多相关文章

  1. Java+Selenium3框架设计篇5-如何实现邮件发送测试报告

    https://blog.csdn.net/u011541946/article/details/77278837 本篇继续回答网友的问题,这个主题是如何通过邮件发送测试报告.通过邮件发送测试报告,这 ...

  2. 使用Quartz框架定时发送预警邮件

    1.  Quartz定时发送预警邮件 1.1.   需求及实现思路 定时查询库存预警信息,一旦存在库存预警的商品,则发邮件通知相关人员 1.2.   Quartz框架 Quartz是OpenSymph ...

  3. jenkins构建邮件自动发送,测试邮件发送成功,构建项目邮件发送不成功的问题

    提示问题: Connection error sending email,retrying once more in 10 seconds…… Connection error sending ema ...

  4. yii2.0 框架邮件的发送

    第一步: 在main-local.php中的components中配置mailer: $config = [ 'components' => [ 'mailer' => [ 'class' ...

  5. ABP框架系列之二十四:(Email-Sending-EF-电子邮件发送)

    Introduction Email sending is a pretty common task for almost every application. ASP.NET Boilerplate ...

  6. CI(CodeIgniter)框架下使用非自带类库实现邮件发送

    在项目开发过程中,需要到了邮件提醒功能.首先想到的是CI自身带不带邮件发送类,查看帖子,发现CI本身自带,然后试着利用CI自身带的类库来实现,经过搜搜很多帖子,不少开发者反馈CI自身的Email类有问 ...

  7. springboot+kafka+邮件发送(最佳实践)

    导读 集成spring-kafka,生产者生产邮件message,消费者负责发送 引入线程池,多线程发送消息 多邮件服务器配置 定时任务生产消息:计划邮件发送 实现过程 导入依赖 <proper ...

  8. 手把手0基础项目实战(一)——教你搭建一套可自动化构建的微服务框架(SpringBoot+Dubbo+Docker+Jenkins)...

    原文:手把手0基础项目实战(一)--教你搭建一套可自动化构建的微服务框架(SpringBoot+Dubbo+Docker+Jenkins)... 本文你将学到什么? 本文将以原理+实战的方式,首先对& ...

  9. 循序渐进VUE+Element 前端应用开发(33)--- 邮件参数配置和模板邮件发送处理

    在系统处理中,有时候需要发送邮件通知用户,如新增用户的邮件确认,密码找回,以及常规订阅消息.通知等内容处理,都可以通过邮件的方式进行处理.本篇随笔介绍结合VUE+Element 前端,实现系统的邮件参 ...

随机推荐

  1. POJ 1751 Highways (ZOJ 2048 ) MST

    http://poj.org/problem?id=1751 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2048 题目大 ...

  2. java根据xml配置文件导出excel通用方法

    java web项目中时常会用到导出功能,而导出excel几乎是每个项目必备的功能之一.针对形形色色的导出方法及个人平时的工作经验,特将导出excel方法整理成通用的方法,根据xml配置来实现特定的导 ...

  3. HDU4268 Alice and Bob 【贪心】

    Alice and Bob Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  4. Linux下图形界面调试工具kdbg安装及測试

    1.Ubuntu系统下安装 Ubuntu系统安装比較方便,直接apt-get即可 apt-get install kdbg 2.centos 安装 首先,在这个地址下下载rpm包.然后使用rpm命令安 ...

  5. 【Samza系列】实时计算Samza中文教程(四)—API概述

    上一篇和大家一起宏观上学习了Samza平台的架构,重点讲了一下数据缓冲层和资源管理层.剩下的一块非常重要的SamzaAPI层本节作为重点为大家展开介绍.     当你使用Samza来实现一个数据流处理 ...

  6. 利用Powershell获取公司内部机器的资源信息,作为企业兴许资产管理的基本途径!

    今天一个哥们问我是否用Powershell 实现.我好久没有写脚本,脚本的协作和调试还是费了一些时间,兴许调试了下.运作没有问题,大家能够參考以下的脚本来丰富您企业须要做的一些事情,脚本代码例如以下: ...

  7. js进阶正则表达式9量词2(^和&作用:/^HTML5$/g匹配不到aHTML5b中的HTML5,不然是可以匹配到的)(/\d+(?=cm)/g)((?!cm))

    js进阶正则表达式9量词2(^和&作用:/^HTML5$/g匹配不到aHTML5b中的HTML5,不然是可以匹配到的)(/\d+(?=cm)/g)((?!cm)) 一.总结 ^和&作用 ...

  8. 【u011】乘法难题

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] 乘法难题是一种用一行的卡片来玩的单人游戏,每张卡片上有一个正整数.在游戏者从中拿出一卡片,并且得到一个 ...

  9. android WebView总 结

    浏览器控件是每个开发环境都具备的,这为马甲神功提供了用武之地,windows的有webbrowser,android和ios都有webview.只是其引擎不同,相对于微软的webbrowser,and ...

  10. OpenGLES 关于 数学 的分支 - 线性变化量、离散量、随机量

    关于 数学 的分支 - 线性变化量.离散量.随机量 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作 ...