php 利用个人邮箱,利用 Composer 完善自己的 PHP 框架(二)——发送邮件

利用 Composer 完善自己的 PHP 框架(二)——发送邮件

2014-10-18 / 阅读数:23506 / 分类: PHP

回顾

上一篇文章中,我们手工建造了一个简易的视图加载器,顺便引入了错误处理包,让我们的 MFFC 框架在 M、V、C 三个方面都达到了“好用”的水平。View 是一个可插拔组件,在本篇文章中我们要创建另一个可插拔组件——邮件发送模块。

正文

我们采用 '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;

/**

* \Mail

*/

class Mail extends Message

{

public $config;

// [String] e-mail

protected $from;

// [Array] e-mail list

protected $to;

protected $title;

protected $body;

function __construct($to)

{

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

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

if ( is_array($to) ) {

foreach ($to as $email) {

$this->addTo($email);

}

} else {

$this->addTo($to);

}

}

public function from($from=null)

{

if ( !$from ) {

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

}

$this->setFrom($from);

return $this;

}

public static function to($to=null)

{

if ( !$to ) {

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

}

return new Mail($to);

}

public function title($title=null)

{

if ( !$title ) {

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

}

$this->setSubject($title);

return $this;

}

public function content($content=null)

{

if ( !$content ) {

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

}

$this->setHTMLBody($content);

return $this;

}

}

Mail 类和 View 类工作的方式基本一致:$this->mail = Mail::to(['ooxx@gmail.com', 'ooxx@qq.com'])

->from('MotherFucker ')

->title('Fuck Me!')

->content('

Hello~~

');

上面这段代码位于 HomeController 中, 'View::make()' 那行代码的下面。

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

return [

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

'username' => 'ooxx@163.com',

'password' => 'password',

'secure' => ''

];

Mail 和 View 一样也在 BaseController 的析构函数 __destruct() 函数中处理,现在这个 function 长这样:public function __destruct()

{

$view = $this->view;

if ( $view instanceof View ) {

extract($view->data);

require $view->view;

}

$mail = $this->mail;

if ( $mail instanceof Mail ) {

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

$mailer->send($mail);

}

}

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

4796555f2bc33b4fd99326e68b1c4583.png

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

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

分析

邮件发送的整体流程想必大家已经轻车熟路了,现在主要叙述一下 Mail 类的设计过程:邮件发送的核心参数是 '目标地址',即邮件要发送到的 E-mail 地址,所以我们设计 Mail::to('oo@xx.me') 作为发送的 '触发 API'。

目前我们采用最简单的 'SMTP' 方式发送邮件,文档在 这里。配置文件放置在 'MFFC/config/mail.php' 中,依旧返回一个数组。

Mail 类继承了 'Nette\Mail\Message' 类。'Mail::to()' 的时候创建一个 Mail 类的实例(对象)并返回,这时候其实 'BaseController' 中的析构函数中的代码已经会被触发并处理这个对象了。默认的发送人是从配置文件中读取的 'username'。

'Mail::to()' 支持 字符串 或者数组作为参数,可以一次发送一封或多封邮件。

'from()'、'title()' 和 'content()' 方法用于丰富邮件内容。'content()' 方法可以直接传递 HTML 代码。

'from()' 配置不一定都能够成功,部分邮件服务商不支持修改发送人地址。

这个变量全部组装完成后,被赋值给控制器的 '$mail' 成员变量,然后被析构函数处理,邮件被发送,成功后页面代码被发送回客户端,流程结束。

WRITTEN BY

9918749bb4d134e0a0a19c7c9d51aff8.png

程序员,Swift Contributor,正在写《iOS 可视化编程与 Auto Layout》。

评论:

57cc501f9d257e8e3bcbb185fc67cade?s=40&d=mm&r=g

lhh

2018-03-02 14:10

phpstorm 点进去能找到mail类,但是报错是Class 'Services\Mail' not found

11e1a5ccc9613e276fc733071d4fb4ce?s=40&d=mm&r=g

daode

2020-08-25 18:31

@lhh:composer dump-autoload 试试

17795660dc39be85b37e2e2a4b81fd6f.png

小样

2018-01-31 15:37

按照配置配置完成mail服务之后,报错

SMTP server did not accept . with error: 554 DT:SPM 163 smtp2,DNGowACnMfatcXFaOgQVAA--.297S2 1517384109,please see http://mail.163.com/help/help_spam_16.htm?ip=61.149.143.14&hostid=smtp2&time=1517384109

请问博主,这是啥情况呢?是配置项没有配对还是程序验证上哪里出问题了呢

17795660dc39be85b37e2e2a4b81fd6f.png

jason

2017-07-10 16:43

我想请教大佬@JohnLui,到目前为止,View或者Mail这类功能再析构中触发是基于性能考虑,或者是什么考虑?

f2eb4aff4d2bcce79de0c4ced545de54.png

2017-07-10 16:49

@jason:我把 TinyView 放到析构中触发是为了不侵入主流程。。。

至于 Mail,这东西比较耗时,实际场景下一般使用队列系统,异步发送。

871af37b0a5b26e8b8c9c1f200445a81?s=40&d=mm&r=g

haha

2017-06-06 19:25

config/mail.php 由163换车搜狐的邮箱就可以了,163的邮箱安全验证比较严格导致

return [

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

'username' => 'xxxxx@sohu.com',

'password' => 'xxxxx',

'secure'   => ''

];

17795660dc39be85b37e2e2a4b81fd6f.png

kun

2017-04-05 19:44

我的也没有报错,效果也和博主的一样,可为什么没有收到呢 ,应该还是发送不成功。

17795660dc39be85b37e2e2a4b81fd6f.png

crlt_

2018-01-17 10:34

@kun:可以看看你的垃圾箱

81ab8ca1c3b1db061fd29f909acd9c13?s=40&d=mm&r=g

风无心

2016-08-18 18:22

markdown写出来的文档,直接让人有种跪舔的冲动

d73cc2ea81e3990b76ab9e9ac53689f6?s=40&d=mm&r=g

woodstig3

2015-08-21 21:48

按照教主的示例做下来,总是返回:“No connection could be made because the target machine actively refused it.”这好像是SMTP服务器的设置问题,但是查看了163的邮箱设置,确实打开了SMTP服务了,为什么无法连接上呢?

d73cc2ea81e3990b76ab9e9ac53689f6?s=40&d=mm&r=g

woodstig3

2015-08-23 15:25

@woodstig3:问题没有找到,但是从教主的github主页上把Mail.php下下来重新跑就没这个问题了。但是邮件似乎还没有发出去。再查!

发表评论:

昵称

邮件地址 (选填)

个人主页 (选填)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/504776.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

启动马达接线实物图_东元伺服驱动马达

东元伺服驱动马达&#xff0c;我公司主营德国SEW&#xff0c;德国法勒VAHLE, 德国UNING&#xff0c;德国同驰Tschan&#xff0c;意大利威卡WESTCAR&#xff0c;德国久茂JUMO&#xff0c;瑞士ABB等几大世界品牌产品。东元伺服驱动马达&#xff0c; 工业机器人电动伺服系统的一般…

三维数据平滑处理_黑白象片的密度信息 卫星数据处理 遥感制图 三维建模 善图科技...

黑白象片的密度信息象片上的黑白变化&#xff0c;可划分为若干等级&#xff0c;此等级称之为灰阶。象片上的灰阶数受洗印技术及目视分辨能力的限制&#xff0c;一般不超过10个灰阶。灰阶较多时&#xff0c;象片上层次分明易于分辨一些细节。但灰阶的增多必导至对比度相对下降&a…

oracle左连接数据会对不上吗,一周工作总结–左连接造成的一些问题-Oracle

一周工作总结–左连接造成的一些问题今天有同事告诉我&#xff0c;有个SQL执行了好久好久执行不出来&#xff0c;我说好就是多久&#xff1f;她说一天左右了。真是令人咋舌的SQL。于是我要来了SQL看了看执行计划&#xff0c;确实让人咋舌。下图中就是执行计划的截图&#xff1a…

网页设计上机考试原题_全国计算机三级信息安全考试 经验分享

为什么选择信息安全&#xff1f;误打误撞报的名&#xff0c;正好又听说是三级里面最好过的。1&#xff09;时间&#xff1a;九月份的考试&#xff0c;大概六月份报名。我在9月2日开学后&#xff0c;才开始准备的&#xff0c;也就二十几天的时间&#xff0c;而且我白天课不少&am…

newifi mini固件_如何在vmware虚拟机中安装OpenWrt系统,含x86固件编译教程

"OpenWrt项目是针对嵌入式设备的Linux操作系统"&#xff0c; 这是官方给出的定义。OpenWrt确实是一个非常好的嵌入式学习系统&#xff0c;目前市面上上千款设备支持运行OpenWrt&#xff0c;如小米路由、newifi、netgear路由、360路由等。各大wifi芯片厂商sdk开始采用…

宝塔linux忘记密码,宝塔忘记登录入口了怎么解决 宝塔面板密码忘记了怎么办

因为性能和安全性上的突出优势&#xff0c;现在用宝塔LINUX面板配置网站环境的站长越来越多&#xff0c;但一些粗心大意的站长经常会遇到这个问题&#xff0c;密码想不起来了&#xff0c;入口链接忘记了&#xff0c;宝塔忘记登录入口了怎么解决 宝塔面板密码忘记了怎么办呢&…

minitab怎么算西格玛水平_六西格玛黑带培训工具因子分析的使用

六西格玛黑带培训工具因子分析的使用-张驰咨询一、该命令用于将数据结构简化为较少的量&#xff0c;因子分析的重点是确定能够解释数据变异大的因子数量。二、对话框内容。1、variables&#xff1a;输入需包含在分析中的变量栏。2、Numberoffactorstoextract&#xff1a;输入需…

linux curl 编译命令,linux 编译 curl 出错

编译curl make 死活不通过&#xff0c;唉执行参数如下&#xff0c;谢谢各位帮忙看看这一步一切正常rootdebian:~/curl-7.45.0# ./configure --with-sslmake一顿编译之后 ...... 然后出错了../lib/.libs/libcurl.so: undefined reference to SSLv2_client_method../lib/.libs/li…

linux 禁用smb服务,Samba 4.11 发布,更好的可扩展性与默认禁用SMB1

Samba 4.11是这个SMB/CIFS/AD实现的最新大功能更新&#xff0c;用于提供与Linux和其他平台更好的Windows互操作性。 Samba 4.11的变化非常多&#xff0c;我们有点惊讶它没有被称为Samba 5.0。也许最令人兴奋的是Samba 4.11具有很大的可扩展性改进&#xff0c;它应该能够扩展到1…

elementui table渲染不出来_测试开发不会前端?ElementUI你需要了解一下

在测试部门内平台类工具的开发需求越来越多&#xff0c;因此也推动了测试开发职位薪水逐步升高。如果开发一个web测试平台&#xff0c;前端技术是必不可少的&#xff0c;像是js、css等。一般在企业内&#xff0c;一个正式产品的前后端开发是职责分明的。端开发只负责业务逻辑&a…

python 画图 线标注_最简洁的Python时间序列可视化实现

TUSHARE 金融与技术学习兴趣小组 翻译整理、编辑 | 一只小绿怪兽译者简介&#xff1a;北京第二外国语学院国际商务专业研一在读&#xff0c;目前在学习Python编程和量化投资相关知识。作者&#xff1a;DataCamp时间序列数据在数据科学领域无处不在&#xff0c;在量化金融领域也…

linux伙伴系统接口,Linux伙伴系统(一)--伙伴系统的概述

伙伴系统的概述Linux内核内存管理的一项重要工作就是如何在频繁申请释放内存的情况下&#xff0c;避免碎片的产生。Linux采用伙伴系统解决外部碎片的问题&#xff0c;采用slab解决内部碎片的问题&#xff0c;在这里我们先讨论外部碎片问题。避免外部碎片的方法有两种&#xff1…

linux 集群 lvs,linux集群--LVS集群

拓扑图&#xff1a;1、LVS配置脚本&#xff1a;需要安装&#xff1a;ipvsadm-1.24-10.i386.rpmvi /etc/rc.d/init.d/lvsdr#!/bin/bashvip192.168.0.116web1192.168.0.104web2192.168.0.114./etc/rc.d/init.d/functionscase "$1" instart)echo "startlvs-dr&quo…

服务器连接工具mat_将个人笔记本改造成Linux简易服务器

实验过程1、开启Ubuntu系统的ssh服务开启之后其他电脑就可以通过ssh登录Ubuntu服务器&#xff0c;通过安装openssh-server就可以达到目的。(1)查看主机有没有ssh服务在Ubuntu系统桌面右击后点击“打开终端”&#xff0c;输入一下命令&#xff1a;ssh localhost若出现&#xff1…

以下对c语言函数的描述中正确的是,以下对C语言函数的有关描述中,正确的是

摘要&#xff1a;它决习定于的学后天&#xff0c;下语密切关系的能与社力是会文化有。关描透性的是起渗利尿可引。认的r默链接路径是(&#xff0c;述中在建点时立站。...它决习定于的学后天&#xff0c;下语密切关系的能与社力是会文化有。函数人感型的偏好感受觉很丰富。关描透…

创建前缀一样的文件_SpringBoot:配置文件属性读取

SpringBoot中默认加载的是application.properties或者application.yaml文件&#xff0c;当然也支持自定义的属性文件。我们可以在此文件中写一些自己想要的配置信息&#xff0c;然后在用的地方读取。默认属性文件在application.properties文件中添加配置信息&#xff0c;如下&a…

c语言 算术平均滤波法_单片机数字滤波的算法

单片机主要作用是控制外围的器件&#xff0c;并实现一定的通信和数据处理。但在某些特定场合&#xff0c;不可避免地要用到数学运算&#xff0c;尽管单片机并不擅长实现算法和进行复杂的运算。下面主要是介绍如何用单片机实现数字滤波。在单片机进行数据采集时&#xff0c;会遇…

参数 携带 跳转_微信小程序:页面跳转及参数传递

本文首发自个人自有博客&#xff1a;【FaxMiao个人博客】&#xff0c;一个关注Web前端开发技术、关注用户体验、记录前端点滴&#xff0c;坚持更多原创&#xff0c;为大家提供高质量技术博文&#xff01;前言小程序的跳转方法有很多种&#xff0c;有的人一直只用wx.navigateTo跳…

android fragment 管理器,Android Fragment 與 Fragment管理器

Android Fragment 與 Fragment管理器首先談談Fragement的需求過去開發人員認為界面之間的跳轉只需要使用多個activity組成就行了&#xff1b;例如下圖中&#xff0c;在Activity-A管理的界面中單擊按鈕后&#xff0c;Activity-A響應事件並啟動Activity-B&#xff1b;而用戶在單擊…

android 手机 报证书错误,Android设备中的SSL证书错误

了解网络科技近年来高速增长&#xff0c;对人们日常生活的影响可通过PC端和移动设备的使用增长数据可以推断。在数字化技术的今天&#xff0c;用户也希望能够在移动设备上保护网站的信息以及用户的数据。SSL证书是保护网站信息的安全协议&#xff0c;也是目前互联网站点必备的安…