从零构建SMTP邮件发送类
来源:互联网 发布:java单行注释快捷键 编辑:程序博客网 时间:2024/06/05 22:19
从零构建SMTP邮件发送类
- 从零构建SMTP邮件发送类
- SMTP连接和发送过程如下
- SMPT协议常用命令
- 下面开始我们的整体构建一个简单的SMTP邮件发送类
- 下面附上源码注释
SMTP(Simple Mail Transfer Protocol,简单邮件传输协议)是由原地址到目的地址传送邮件的一组规则,用来控制信件的中转方式。SMTP协议属于TCP/IP协议簇,其使每台计算机在发送或中转信件时能到找下一个目的地。通过使用指定的服务器,把E-mail寄到收件人的服务器上。
SMTP连接和发送过程如下:
- 建立TCP连接。
- 客户端发送
HELO
命令标识发件人自己的身份,客户端发送MAIL命令。服务器以OK作为响应,表明准备接收。 - 使用
AUTH
命令登录SMTP服务器,输入用户名和密码(注意,用户名和密码都需要使用base64加密)。 - 客户端发送
RCPT
命令,标识该电子邮件的计划接收人,可以有多个RCPT行。服务器以OK作为想要,表示愿意为收件人发送邮件。 - 协商结束后,使用DATA命令发送。
- 以
.
号表示结束,输入内容一起发送出去,结束此次发送,用QUIT
命令退出。
例如:使用Telnet创建一个SMTP会话,其中S代表服务器,C代表客户端,如下图所示
注意: 上述命令并不一定会一次性成功,服务器可能会返回错误响应,客户端应该安装协议规定的顺序输入后续命令(或重复执行失败的命令、或重置会话、或退出会话等)。
SMPT协议常用命令
下面开始我们的整体,构建一个简单的SMTP邮件发送类
简单介绍一下我们使用的socket函数,我们使用fsockopen()来连接SMTP服务器,使用fsockopen的好处是把Socket连接绑定到一个流觞,然后使用各种操作流的函数操作这个Socket连接。fsockopen()函数的用法:
resource fscokopen(string $hostname, int $port, int [$errno], string [$errstr], int [$timeout]);
参数说明如下:
$hostname
要连接的服务器路径$port
要绑定的端口$errno
保存连接发生错误时的错误号$errstr
保存错误信息$timeout
设置连接的超时时间,单位秒
下面附上源码、注释。
<?phpnamespace smtp; // 设置这个命令空间是保证不和其他冲突,可以删除class Smtp{ /** * @var string 保存要连接的SMTP服务器 */ private $host; /** * @var int 要绑定的端口号 */ private $port = 25; /** * @var string 保存要连接的SMTP服务器用户名 */ private $user; /** * @var string 保存要连接的SMTP服务器密码 */ private $pass; /** * @var bool 标识是否开启调试模式,默认关闭 */ private $debug = false; /** * @var resource 保存与SMTP服务器连接的句柄 */ private $sock; /** * @var bool 标识使用什么格式发送邮件,false 普通文本, true HTML */ private $isHTML = false; /** * @var int 连接超时时间 */ private $timeout = 10; /** * Smtp constructor. * @param string $host * @param int $port * @param string $user * @param string $pass * @param bool $isHTML * @param bool $debug * @param int $timeout */ public function __construct( $host, $port, $user, $pass, $isHTML = false, $debug = false, $timeout = 10 ) { $this->host = $host; $this->port = $port; $this->user = base64_encode( $user ); $this->pass = base64_encode( $pass ); $this->isHTML = $isHTML; $this->debug = $debug; // 连接到服务器 $this->sock = @fsockopen( $this->host, $this->port, $errno, $errstr, $this->timeout ); // 判断连接是否成功 if ( ! $this->sock ) { die( "Error number: $errno, Error message: $errstr" ); } // 判断连接成功返回的状态码是否正确 $response = fgets( $this->sock ); if ( strpos( $response, "220" ) === false ) { die( "Server error: $response" ); } } /** * 向服务器发送命令 * @param string $cmd 需要执行的命令 * @param int $returnCode 命令的返回码 * @return bool */ private function doCommand( $cmd, $returnCode ) { fwrite( $this->sock, $cmd ); $response = fgets( $this->sock ); if ( strpos( $response, "{$returnCode}" ) === false ) { $this->showDebug( $response ); return false; } return true; } /** * 显示调试信息 * @param $message string */ private function showDebug( $message ) { if ( $this->debug ) { echo "<p>Debug: {$message}</p>"; } } /** * 判断邮件是否符合要求 * @param $email string * @return bool */ private function isEmail( $email ) { $pattern = "/^[^_][\w]*@[\w.]+[\w]*[^_]$/"; if ( preg_match( $pattern, $email ) ) { return true; } else { return false; } } /** * 执行邮件发送 * @param string $from 发送邮件者 * @param string $to 接收邮件者 * @param string $subject 邮件的主题 * @param string $body 邮件的内容 * @return bool */ public function send( $from, $to, $subject, $body ) { if ( ! $this->isEmail( $from ) OR ! $this->isEmail( $to ) ) { $this->showDebug( "Please enter valid from/to email." ); return false; } if ( empty( $subject ) OR empty( $body ) ) { $this->showDebug( "Please enter subject/content." ); return false; } $detail = "FROM:{$from}\r\n"; $detail .= "TO:{$to}\r\n"; $detail .= "Subject:{$subject}\r\n"; if ( $this->isHTML ) { $detail .= "Content-Type: text/html;\r\n"; } else { $detail .= "Content-Type: text/plain\r\n"; } $detail .= "charset=utf-8\r\n\r\n"; $detail .= $body; // 执行命令 $this->doCommand( "HELO {$this->host}\r\n", 250 ); // 客户端向服务端发送HELO表明身份 $this->doCommand( "AUTH LOGIN\r\n", 334 ); // 客户端发送命令登录SMTP服务器 $this->doCommand( "{$this->user}\r\n", 334 ); // 输入用户的名 $this->doCommand( "{$this->pass}\r\n", 235 ); // 输入密码 $this->doCommand( "MAIL FROM: <{$from}>\r\n", 250 ); // 设置发件人 $this->doCommand( "RCPT TO: <{$to}>\r\n", 250 ); // 设置收件人 $this->doCommand( "DATA\r\n", 354 ); // 设置邮件内容 $this->doCommand( "$detail\r\n.\r\n", 250 ); // 发送邮件 $this->doCommand( "QUIT\r\n", 221 ); // 退出SMTP服务器 return true; }}// 下面是测试用例$smtp = new \smtp\Smtp( 'smtp.163.com', 25, 'fsyzxz@163.com', 'xfj529js515', true, true, 3 );$subject = 'this is email subject';$body = 'this is test smtp email content';var_dump( $smtp->send( 'fsyzxz@163.com', '1207791534@qq.com', $subject, $body ) );
测试结果如图:
阅读全文
1 0
- 从零构建SMTP邮件发送类
- smtp 发送邮件类
- PHP模拟SMTP发送邮件的类
- PHP邮件发送类(SMTP)
- php使用smtp封装类发送邮件
- C#发送SMTP邮件
- SMTP发送邮件
- .net smtp发送邮件
- 使用SMTP发送邮件
- smtp邮件发送
- 用SMTP发送邮件
- MailMessage、Smtp发送邮件
- Telnet发送SMTP邮件
- php SMTP发送邮件
- Java SMTP发送邮件
- C#smtp发送邮件
- 使用SMTP发送邮件
- 使用SMTP发送邮件
- Word Break--lintcode
- 自定义memcpy和strcpy
- hive构建数据仓库
- ref out返回参数的区别
- Android apk动态加载机制的研究
- 从零构建SMTP邮件发送类
- Kyligence Analytics Platform Enterprise
- 开始的开始
- [自制操作系统] BMP格式文件读取&图形界面系统框架-应用接口设计
- leetcode题解-29. Divide Two Integers
- MyBatis之延迟加载
- 颠倒的价牌
- 根据IP/掩码位获取IP的起始范围、IP总数、IP属不属于某个网段或者打印网段内所有的IP
- 页面之间传递参数