php下使用SMTP发邮件的代码
程序员文章站
2022-05-25 23:13:52
最近一个项目需要用到smtp发送邮件,之前的库类不存在了,又不喜欢安装pear或者使用pear的net/smtp类,感觉太复杂了。就直接从discuz中抽取出核心稍微修改了...
最近一个项目需要用到smtp发送邮件,之前的库类不存在了,又不喜欢安装pear或者使用pear的net/smtp类,感觉太复杂了。就直接从discuz中抽取出核心稍微修改了下。
从协议分析网上,查找到smtp协议的命令和应答,smtp协议在发送smtp和接收smtp之间的会话是靠发送smtp的smtp命令和接收smtp反馈的应答来完成的。常用的命令如下:
hello<domain><crlf>识别发送方到接收smtp的一个hello命令
mail from:<reverse-path><crlf><reverse-path>为发送者地址。此命令告诉接收方一个新邮件发送的开始,并对所有的状态和缓冲区进行初始化。此命令开始一个邮件传输处理,最终完成将邮件数据传送到一个或多个邮箱中。
rcpt to:<forward-path><crlf><forward-path>标识各个邮件接收者的地址
data<crlf>
接收smtp将把其后的行为看作邮件数据去处理,以<crlf>.<crlf>标识数据的结尾。
rest<crlf>退出/复位当前的邮件传输
noop<crlf>要求接收smtp仅做ok应答。(用于测试)
quit<crlf>要求接收smtp返回一个ok应答并关闭传输。
vrfy<string><crlf>验证指定的邮箱是否存在,由于安全因素,服务器多禁止此命令。
expn<string><crlf>验证给定的邮箱列表是否存在,扩充邮箱列表,也常禁止使用。
help<crlf>查询服务器支持什么命令
注:<crlf>为回车、换行,ascii码分别为13、10(十进制)。
另外,可以在command下,使用telnet来进行简单的手工使用smtp。
比如:
telnet smtp.263.net 25
trying 211.150.96.25...
connected to smtp.263.net.
escape character is '^]'.
220 welcome to coremail system(with anti-spam) 2.1 for 263(040326)
helo weiqiong@cctk.net
250 smtp.263.net
mail from:weiqiong@cctk.net
250 ok
rcpt to:g2_t1@263.net
250 ok
data
354 end data with <cr><lf>.<cr><lf>
haha
.
250 ok: queued as b9e452ff3e
quit
221 bye
connection closed by foreign host.
在此基础上就可以写出一个简单的smtp类了。
<?
class stmp{
private $mailcfg=array();
private $error_msg='';
function __construct($mailcfg){
$this->mailcfg=$mailcfg;
}
public function send($mail){
$mailcfg=$this->mailcfg;
if(!$fp = fsockopen($mailcfg['server'], $mailcfg['port'], $errno, $errstr, 30)) {
return $this->error("($mailcfg[server]:$mailcfg[port]) connect - unable to connect to the smtp server, please check your \"mail_config.php\".");
}
stream_set_blocking($fp, true);
$lastmessage = fgets($fp, 512);
if(substr($lastmessage, 0, 3) != '220') {
return $this->error("$mailcfg[server]:$mailcfg[port] connect - $lastmessage");
}
fputs($fp, ($mailcfg['auth'] ? 'ehlo' : 'helo')." ".$mailcfg['auth_username']."\r\n");
$lastmessage = fgets($fp, 512);
if(substr($lastmessage, 0, 3) != 220 && substr($lastmessage, 0, 3) != 250) {
return $this->error("($mailcfg[server]:$mailcfg[port]) helo/ehlo - $lastmessage");
}
while(1) {
if(substr($lastmessage, 3, 1) != '-' || empty($lastmessage)) {
break;
}
$lastmessage = fgets($fp, 512);
}
if($mailcfg['auth']) {
fputs($fp, "auth login\r\n");
$lastmessage = fgets($fp, 512);
if(substr($lastmessage, 0, 3) != 334) {
return $this->error("($mailcfg[server]:$mailcfg[port]) auth login - $lastmessage");
}
fputs($fp, base64_encode($mailcfg['auth_username'])."\r\n");
$lastmessage = fgets($fp, 512);
if(substr($lastmessage, 0, 3) != 334) {
return $this->error("($mailcfg[server]:$mailcfg[port]) username - $lastmessage");
}
fputs($fp, base64_encode($mailcfg['auth_password'])."\r\n");
$lastmessage = fgets($fp, 512);
if(substr($lastmessage, 0, 3) != 235) {
return $this->error("($mailcfg[server]:$mailcfg[port]) password - $lastmessage");
}
$email_from = $mailcfg['from'];
}
fputs($fp, "mail from: <".preg_replace("/.*\<(.+?)\>.*/", "\\1", $email_from).">\r\n");
$lastmessage = fgets($fp, 512);
if(substr($lastmessage, 0, 3) != 250) {
fputs($fp, "mail from: <".preg_replace("/.*\<(.+?)\>.*/", "\\1", $email_from).">\r\n");
$lastmessage = fgets($fp, 512);
if(substr($lastmessage, 0, 3) != 250) {
return $this->error("($mailcfg[server]:$mailcfg[port]) mail from - $lastmessage");
}
}
$email_to=$mail['to'];
foreach(explode(',', $email_to) as $touser) {
$touser = trim($touser);
if($touser) {
fputs($fp, "rcpt to: <$touser>\r\n");
$lastmessage = fgets($fp, 512);
if(substr($lastmessage, 0, 3) != 250) {
fputs($fp, "rcpt to: <$touser>\r\n");
$lastmessage = fgets($fp, 512);
return $this->error("($mailcfg[server]:$mailcfg[port]) rcpt to - $lastmessage");
}
}
}
fputs($fp, "data\r\n");
$lastmessage = fgets($fp, 512);
if(substr($lastmessage, 0, 3) != 354) {
return $this->error("($mailcfg[server]:$mailcfg[port]) data - $lastmessage");
}
$str="to: $email_to\r\nfrom: $email_from\r\nsubject: ".$mail['subject']."\r\n\r\n".$mail['content']."\r\n.\r\n";
fputs($fp, $str);
fputs($fp, "quit\r\n");
return true;
}
public function get_error(){
return $this->error_msg;
}
private function error($msg){
$this->error_msg.=$msg;
return false;
}
}
?>
简单的调用例子:
<?
$mailcfg['server'] = 'smtp.163.com';
$mailcfg['port'] = '25';
$mailcfg['auth'] = 1;
$mailcfg['from'] = 'test <test@163.com>';
$mailcfg['auth_username'] = 'test';
$mailcfg['auth_password'] = 'password';
$stmp=new stmp($mailcfg);
$mail=array('to'=>'test@gmail.com','subject'=>'测试标题','content'=>'邮件内容<a href="http://www.phpobject.net">php面向对象</a>');
if(!$stmp->send($mail)){
echo $stmp->get_error();
}else{
echo 'mail succ!';
}
?>
如果发送成功,你就可以去邮箱查看邮件了。^_^
从协议分析网上,查找到smtp协议的命令和应答,smtp协议在发送smtp和接收smtp之间的会话是靠发送smtp的smtp命令和接收smtp反馈的应答来完成的。常用的命令如下:
hello<domain><crlf>识别发送方到接收smtp的一个hello命令
mail from:<reverse-path><crlf><reverse-path>为发送者地址。此命令告诉接收方一个新邮件发送的开始,并对所有的状态和缓冲区进行初始化。此命令开始一个邮件传输处理,最终完成将邮件数据传送到一个或多个邮箱中。
rcpt to:<forward-path><crlf><forward-path>标识各个邮件接收者的地址
data<crlf>
接收smtp将把其后的行为看作邮件数据去处理,以<crlf>.<crlf>标识数据的结尾。
rest<crlf>退出/复位当前的邮件传输
noop<crlf>要求接收smtp仅做ok应答。(用于测试)
quit<crlf>要求接收smtp返回一个ok应答并关闭传输。
vrfy<string><crlf>验证指定的邮箱是否存在,由于安全因素,服务器多禁止此命令。
expn<string><crlf>验证给定的邮箱列表是否存在,扩充邮箱列表,也常禁止使用。
help<crlf>查询服务器支持什么命令
注:<crlf>为回车、换行,ascii码分别为13、10(十进制)。
另外,可以在command下,使用telnet来进行简单的手工使用smtp。
比如:
telnet smtp.263.net 25
trying 211.150.96.25...
connected to smtp.263.net.
escape character is '^]'.
220 welcome to coremail system(with anti-spam) 2.1 for 263(040326)
helo weiqiong@cctk.net
250 smtp.263.net
mail from:weiqiong@cctk.net
250 ok
rcpt to:g2_t1@263.net
250 ok
data
354 end data with <cr><lf>.<cr><lf>
haha
.
250 ok: queued as b9e452ff3e
quit
221 bye
connection closed by foreign host.
在此基础上就可以写出一个简单的smtp类了。
<?
class stmp{
private $mailcfg=array();
private $error_msg='';
function __construct($mailcfg){
$this->mailcfg=$mailcfg;
}
public function send($mail){
$mailcfg=$this->mailcfg;
if(!$fp = fsockopen($mailcfg['server'], $mailcfg['port'], $errno, $errstr, 30)) {
return $this->error("($mailcfg[server]:$mailcfg[port]) connect - unable to connect to the smtp server, please check your \"mail_config.php\".");
}
stream_set_blocking($fp, true);
$lastmessage = fgets($fp, 512);
if(substr($lastmessage, 0, 3) != '220') {
return $this->error("$mailcfg[server]:$mailcfg[port] connect - $lastmessage");
}
fputs($fp, ($mailcfg['auth'] ? 'ehlo' : 'helo')." ".$mailcfg['auth_username']."\r\n");
$lastmessage = fgets($fp, 512);
if(substr($lastmessage, 0, 3) != 220 && substr($lastmessage, 0, 3) != 250) {
return $this->error("($mailcfg[server]:$mailcfg[port]) helo/ehlo - $lastmessage");
}
while(1) {
if(substr($lastmessage, 3, 1) != '-' || empty($lastmessage)) {
break;
}
$lastmessage = fgets($fp, 512);
}
if($mailcfg['auth']) {
fputs($fp, "auth login\r\n");
$lastmessage = fgets($fp, 512);
if(substr($lastmessage, 0, 3) != 334) {
return $this->error("($mailcfg[server]:$mailcfg[port]) auth login - $lastmessage");
}
fputs($fp, base64_encode($mailcfg['auth_username'])."\r\n");
$lastmessage = fgets($fp, 512);
if(substr($lastmessage, 0, 3) != 334) {
return $this->error("($mailcfg[server]:$mailcfg[port]) username - $lastmessage");
}
fputs($fp, base64_encode($mailcfg['auth_password'])."\r\n");
$lastmessage = fgets($fp, 512);
if(substr($lastmessage, 0, 3) != 235) {
return $this->error("($mailcfg[server]:$mailcfg[port]) password - $lastmessage");
}
$email_from = $mailcfg['from'];
}
fputs($fp, "mail from: <".preg_replace("/.*\<(.+?)\>.*/", "\\1", $email_from).">\r\n");
$lastmessage = fgets($fp, 512);
if(substr($lastmessage, 0, 3) != 250) {
fputs($fp, "mail from: <".preg_replace("/.*\<(.+?)\>.*/", "\\1", $email_from).">\r\n");
$lastmessage = fgets($fp, 512);
if(substr($lastmessage, 0, 3) != 250) {
return $this->error("($mailcfg[server]:$mailcfg[port]) mail from - $lastmessage");
}
}
$email_to=$mail['to'];
foreach(explode(',', $email_to) as $touser) {
$touser = trim($touser);
if($touser) {
fputs($fp, "rcpt to: <$touser>\r\n");
$lastmessage = fgets($fp, 512);
if(substr($lastmessage, 0, 3) != 250) {
fputs($fp, "rcpt to: <$touser>\r\n");
$lastmessage = fgets($fp, 512);
return $this->error("($mailcfg[server]:$mailcfg[port]) rcpt to - $lastmessage");
}
}
}
fputs($fp, "data\r\n");
$lastmessage = fgets($fp, 512);
if(substr($lastmessage, 0, 3) != 354) {
return $this->error("($mailcfg[server]:$mailcfg[port]) data - $lastmessage");
}
$str="to: $email_to\r\nfrom: $email_from\r\nsubject: ".$mail['subject']."\r\n\r\n".$mail['content']."\r\n.\r\n";
fputs($fp, $str);
fputs($fp, "quit\r\n");
return true;
}
public function get_error(){
return $this->error_msg;
}
private function error($msg){
$this->error_msg.=$msg;
return false;
}
}
?>
简单的调用例子:
<?
$mailcfg['server'] = 'smtp.163.com';
$mailcfg['port'] = '25';
$mailcfg['auth'] = 1;
$mailcfg['from'] = 'test <test@163.com>';
$mailcfg['auth_username'] = 'test';
$mailcfg['auth_password'] = 'password';
$stmp=new stmp($mailcfg);
$mail=array('to'=>'test@gmail.com','subject'=>'测试标题','content'=>'邮件内容<a href="http://www.phpobject.net">php面向对象</a>');
if(!$stmp->send($mail)){
echo $stmp->get_error();
}else{
echo 'mail succ!';
}
?>
如果发送成功,你就可以去邮箱查看邮件了。^_^
推荐阅读
-
windwos下使用php连接oracle数据库的过程分享
-
PHP下使用mysqli的函数连接mysql出现warning: mysqli::real_connect(): (hy000/1040): ...
-
使用php批量删除数据库下所有前缀为prefix_的表
-
php下获取http状态的实现代码
-
php代码中使用换行及( 或 和br)的应用
-
Linux下使用Shell脚本实现ftp的自动上传下载的代码小结
-
使用PHP导出Redis数据到另一个Redis中的代码
-
使用php+apc实现上传进度条且在IE7下不显示的问题解决方法
-
PHP中的traits实现代码复用使用实例
-
使用PHP下载CSS文件中的图片的代码