我快疯了,工资被扣了一半还是没搞定,用socket发邮件问题,救救我吧!!! 支持不支持数据库呢,如果支持数据库的话,你可以使用数据库来模拟EMAIL功能呀,反正只要达到客户的要求就行了。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 我前几天才发了同样的东西,再发一次吧,应该可以帮你.=================inc/text_mail.class.php==========//这个是把邮件编码的类.//这个类没有对邮件进行任何编码,只是普通的text_mail,把邮件头等东西加上去而已.<?phpclass text_mail{ var $reply; var $to; var $from; var $subject; var $body; function text_mail(){ $this->to=""; $this->from=""; $this->subject=""; $this->body=""; $this->reply=""; } function get_mail(){ $mail="From: $this->from \r\n"; $mail.="Reply-To: $this->reply \r\n"; $mail.="To: $this->to \r\n"; $mail.="Subject: $this->subject \r\n"; $mail.="Mime-verson:1.0 \r\n"; $mail.="Content-Type: text/plain;charset=\"GB2312\"\r\n"; $mail.="Content-Transfer-Encoding: 8bit\r\n"; $mail.="\r\n"; $mail.=str_replace("\n.\r\n","\n. \r\n",$this->body); return $mail; }};?>===============inc/smtp_mail.class.php==============<?phpclass smtp_mail{ var $fp=false; var $lastmsg=""; var $authMode=false; var $authLastLine; var $debugMode=false; var $authLoginName; var $authLoginPassword; function read_line(){ $ret=false; $line=fgets($this->fp,1024); if($this->debugMode){ echo "RESPONSE: $line <br>"; flush(); } if(ereg("^([0-9]+).(.*)$",$line,$data)){ $recv_code=$data[1]; $recv_msg=$data[2]; $ret=array($recv_code,$recv_msg); } return $ret; } function dialogue($code,$cmd,$response=false){ $ret=true; if($this->debugMode){ echo "CWD: $cmd <br>"; flush(); } fwrite($this->fp,$cmd."\r\n"); $line=$this->read_line(); if($line==false){ $ret=false; $this->lastmsg=""; } else{ $this->lastmsg="$line[0] $line[1]"; if($line[0]!=$code){ $ret=false; return $ret; } if($response!==false){ $response.="\r\n"; while($line[1]!=$response){ $line=$this->read_line();// $this->lastmsg.="<br>$line[0] $line[1]"; if($line[0]!=$code){ $ret=false; return $ret; } } } return $ret; } } function error_message(){ echo "SMTP Protocol failure (".$this->lastmsg.").<br>"; flush(); } function crlf_encode($data){ $data.="\n"; $data=str_replace("\n","\r\n",str_replace("\r","",$data)); $data=str_replace("\n.\r\n","\n. \r\n",$data); return $data; } function handle_email($from,$to,$data){ $rcpts=explode(",",$to); $err=false; if(!$this->dialogue(250,"HELO")){ $err=true; } if(!$this->dialogue(250,"EHLO",$this->authLastLine)){ $err=true; } if($this->authMode){ if(!$this->dialogue(334,"AUTH LOGIN")) { $err=true; } if(!$this->dialogue(334,base64_encode($this->authLoginName))){ $err=true; } if(!$this->dialogue(235,base64_encode($this->authLoginPassword))){ $err=true; } } if(!$this->dialogue(250,"MAIL FROM: $from") ){ $err=true; } for($i=0;!$err&&$i<count($rcpts);$i++){ if(!$this->dialogue(250,"RCPT TO: $rcpts[$i]")){ $err=true; } } if($err||!$this->dialogue(354,"DATA")||!fwrite($this->fp,$data)||!$this->dialogue(250,"\r\n.")||!$this->dialogue(221,"QUIT") ){ $err=true; } if($err){ $this->error_message(); } return !$err; } function connect($hostname){ if($this->debugMode){ echo "CONNECTING $hostname ..."; } $ret=false; $this->fp=fsockopen($hostname,25); if($this->fp){ $ret=true; if($this->debugMode){ echo "Succeed!<br>"; flush(); } } else{ if($this->debugMode){ echo "Failed!<br>"; flush(); } } return $ret; } function send_email($hostname,$from,$to,$data,$crlf_encode=1){ if(!$this->connect($hostname)){ echo "cannot open connection!<br>\n"; flush(); return false; } $line=$this->read_line(); $ret=false; if($line&&$line[0]=="220"){ if($crlf_encode){ $data=$this->crlf_encode($data); } $ret=$this->handle_email($from,$to,$data); } else{ $this->error_message(); } fclose($this->fp); return $ret; }};?>===================testmail.php======================<?php//include "inc/mime_mail.php";set_time_limit(100);include "inc/text_mail.class.php";include "inc/smtp_mail.class.php";$smtp_server="mailserver here"; //这里为smtp服务器地址.$from="mail sender here"; //发信人$to="mail receiver here"; //收信人$subject="test HERE!!!!!!"; //题目$body="test only! fdsafsdajfkljdklsfsdafdsfdsafdsfsdafdsf"; //内容$mail=new text_mail; //初始化mail主体$mail->from=$from;$mail->to=$to;$mail->subject=$subject;$mail->body=$body;$mail->reply=$from;$data=$mail->get_mail(); $smtp=new smtp_mail; //初始化smtp_mail类$smtp->debugMode=false; //debug模式$smtp->authMode=false; //smtp服务器验证模式(如果服务器要验证才需要)/* 这里几行是当服务器需要验证的时候才用上.//$smtp->authLastLine="OK"; //ehlo命令列出的最后一行的文字//$smtp->authLoginName="auth username";//$smtp->authLoginPassword="auth password";*/$smtp->send_email($smtp_server,$from,$to,$data); //发送邮件?> 我试了,不行,会报错;SMTP Protocol failure (250 2.1.0 [email protected]... Sender ok ). Drate(小虫) : 你好,你所说的我在jsp里用过了,可是这次客户并没有租数据库!pcdreama(峰幻): 你的代码我试了,可我不会改你的代码,好象不行!其实我上面的代码是正确的,只是服务器不支持外部邮箱吧了! 我以经搞定了(只能用内部邮箱),谢谢大家!大家谁能帮个忙,找个支持外部邮箱的smtp server! 我的代码是可以用的啊.之前都已经验证过了.我觉得是smtp服务器的问题吧,把那个服务器公布出来让大家测试一下就知道啦. UP,有没有人知道那个服务器啊?我也做那个发E_mail的程序啊呀! 以上的代碼我也用了,沒用為什么呢?也是報SMTP Protocol failure (). 信息.這是為什么呢? 谢谢pcdreama(峰幻)的程序.今天我也用了那个代码,在两个SMTP Server上试.其中一个服务器开始也是一直都在说 SMTP Protocol failure ().,如下:CONNECTING mail.xxxxx.com.cn ...Succeed!RESPONSE: 220 tsnc-cs1.inc.iac ESMTP Server (Microsoft Exchange Internet Mail Service 5.5.2653.13) ready CWD: HELO RESPONSE: 250 OK CWD: EHLO RESPONSE: 503 Bad Sequence CWD: AUTH LOGIN RESPONSE: 334 VXNlcm5hbWU6 CWD: xxxx RESPONSE: 334 UGFzc3dvcmQ6 CWD: xxxxxxxx RESPONSE: 235 LOGIN authentication successful CWD: MAIL FROM: [email protected] RESPONSE: 250 OK - mail from SMTP Protocol failure (250 OK - mail from ).注意到:CWD: EHLO RESPONSE: 503 Bad Sequence后,我把smtp_mail.class.php中handle_email($from,$to,$data)函数中的:if (!$this->dialogue(250,"EHLO",$this->authLastLine)) $err=true; 注释掉了,结果瞎猫碰死老鼠,竟然能发邮件了,结果如下:CONNECTING mail.xxxxx.com.cn ...Succeed!RESPONSE: 220 tsnc-cs1.inc.iac ESMTP Server (Microsoft Exchange Internet Mail Service 5.5.2653.13) ready CWD: HELO RESPONSE: 250 OK CWD: AUTH LOGIN RESPONSE: 334 VXNlcm5hbWU6 CWD: xxxx RESPONSE: 334 UGFzc3dvcmQ6 CWD: xxxxxxxx RESPONSE: 235 LOGIN authentication successful CWD: MAIL FROM: [email protected] RESPONSE: 250 OK - mail from CWD: RCPT TO: [email protected] RESPONSE: 250 OK - Recipient CWD: DATA RESPONSE: 354 Send data. End with CRLF.CRLF CWD: . RESPONSE: 250 OK CWD: QUIT RESPONSE: 221 closing connection 但是另外一个服务器,则一定不能删掉那几句,必须用pcdreama(峰幻)的程序,结果如下:CONNECTING mail.xxxxxxxx.com ...Succeed!RESPONSE: 220 mail.xxxxxxxx.com Microsoft ESMTP MAIL Service, Version: 5.0.2195.2966 ready at Sun, 29 Sep 2002 15:03:23 +0800 CWD: HELO RESPONSE: 250 mail.xxxxxxxx.com Hello [61.171.xx.xxx] CWD: EHLO RESPONSE: 250-mail.xxxxxxxx.com Hello [61.171.xx.xxx] RESPONSE: 250-TURN RESPONSE: 250-ATRN RESPONSE: 250-SIZE RESPONSE: 250-ETRN RESPONSE: 250-PIPELINING RESPONSE: 250-DSN RESPONSE: 250-ENHANCEDSTATUSCODES RESPONSE: 250-8bitmime RESPONSE: 250-BINARYMIME RESPONSE: 250-CHUNKING RESPONSE: 250-VRFY RESPONSE: 250-X-EXPS GSSAPI NTLM LOGIN RESPONSE: 250-X-EXPS=LOGIN RESPONSE: 250-AUTH GSSAPI NTLM LOGIN RESPONSE: 250-AUTH=LOGIN RESPONSE: 250-X-LINK2STATE RESPONSE: 250-XEXCH50 RESPONSE: 250 OK CWD: AUTH LOGIN RESPONSE: 334 VXNlcm5hbWU6 CWD: xxxx RESPONSE: 334 UGFzc3dvcmQ6 CWD: xxxxxxxxxxxRESPONSE: 235 2.7.0 Authentication successful. CWD: MAIL FROM: [email protected] RESPONSE: 250 2.1.0 [email protected] OK CWD: RCPT TO: [email protected] RESPONSE: 250 2.1.5 [email protected] CWD: DATA RESPONSE: 354 Start mail input; end with . CWD: . RESPONSE: 250 2.6.0 Queued mail for delivery CWD: QUIT RESPONSE: 221 2.0.0 mail.xxxxxxxx.com Service closing transmission channel 如果删掉那几句,结果如下:CONNECTING mail.xxxxxxx.com ...Succeed!RESPONSE: 220 mail.xxxxxxxx.com Microsoft ESMTP MAIL Service, Version: 5.0.2195.2966 ready at Sun, 29 Sep 2002 15:14:36 +0800 CWD: HELO RESPONSE: 250 mail.xxxxxxxx.com Hello [61.171.xx.xxx] CWD: AUTH LOGIN RESPONSE: 503 5.5.2 Send hello first. CWD: xxxx RESPONSE: 500 5.3.3 Unrecognized command CWD: xxxxxxxxxxxRESPONSE: 500 5.3.3 Unrecognized command CWD: MAIL FROM: [email protected] RESPONSE: 250 2.1.0 [email protected] OK SMTP Protocol failure (250 2.1.0 [email protected] OK ).注意到:CWD: AUTH LOGIN RESPONSE: 503 5.5.2 Send hello first.因为少发送了一个EHLO,所以服务器要求先发送hello.至于为什么会有这种情况,我也不懂,只是觉得的确跟服务器的设置很有关系.(e-mail都被xxx掉了,抱歉) 这个类我在本地测试是好的.支持认证http://www.hooday.com/?n=ShowClass&a=36不支持附件 把变量发关到有MAIL SERVERS 网页上不就行了么?http://www.r51.nethttp://bbs.r51.net PHP调用UNIX系统的sendmail命令。 你的报错是因为你的SMTP服务器使用ESMTP协议,这个协议一般情况是需要验证发信者身份的,你可以找一些不需要验证身份的服务器试一下,不过还有其他的解决方法:使用PHP的EXEC(),这个函数可以调用LINUX下的MAIL命令,不过这种方法的可行性较少,因为这台SERVER的管理员知道禁用MAIL()函数,一定也会把EXEC这类函数禁示掉。另一种方法是用CGI(PERL)方法来发邮件,一般支持PHP的WEB服务器都是支持CGI程序的,你可以试试。如果这台服务器跟本就没装或没启动SENDMAIL或QMAIL之类的软件,你只有再研究socket方法了。 什么意思啊请上一楼的楼主说清楚点。好不好啊我很想用21cn.com的来发啊。请各位提供意见。 如果你用w2k的话,配置一下w2k自带的smtp服务就可以了 其实我是想因为我没有自己的独立主机,所以得靠人家的服务器做为外发服务器,但很多人都着重于自己配置服务器的方法,根本不能实现。所以呢,请大家应该把精力放在考虑用别人的smtp服务器的思路,用技术解决这方面的问题。楼主我想也是这样的意思把 这个需要培植php.ini文件,否则无法发送。培植php.ini文件的smtp。比如是新浪,smtp.sina.com下面是程序原代码。http://www.csdn.net/cnshare/soft/13/13021.shtm我们测试过。 在php.ini中配置smtp服务器,只要不支持认证的服务器就可以了,然后用mail函数即可.俺的几个网站都这么干,服务器用的是俺们学校的smtp服务器,不用白不用. 不用急,我已经搞定了....你把下面的代码改成你需要的类就可以了...<?function show_debug($message, $inout) { if($inout=="in") //响应信息 { $m='<< '; } else $m='>> '; $message=Str_replace("<","<",$message); $message=Str_replace(">",">",$message); if(!ereg("\n$", $message)) $message .= "<br>"; $message=nl2br($message); echo "<font color=#999999>".$m.$message."</font>"; } $smtp_server='';$smtp_username='';$smtp_password='';$send_email = '';$to_email = '';$fp = fsockopen ($smtp_server, "25"); set_socket_blocking( $fp, true ); while(true){ $lastmessage=fgets($fp,512); show_debug($lastmessage,"in"); if(substr($lastmessage,3,1)==" ") break;}$message="EHLO ".$smtp_username."\r\n";fputs($fp, $message); show_debug($message,"out");while(true){ $lastmessage=fgets($fp,512); show_debug($lastmessage,"in"); if($lastmessage[3]==" ") break;}$message="AUTH LOGIN\n";fputs($fp, $message); show_debug($message,"out");while(true){ $lastmessage=fgets($fp,512); show_debug($lastmessage,"in"); if($lastmessage[3]==" ") break;}$message=base64_encode($smtp_username)."\r\n";fputs($fp, $message); show_debug($message,"out");while(true){ $lastmessage=fgets($fp,512); show_debug($lastmessage,"in"); if($lastmessage[3]==" ") break;}$message=base64_encode($smtp_password)."\r\n";fputs($fp, $message); show_debug($message,"out");while(true){ $lastmessage=fgets($fp,512); show_debug($lastmessage,"in"); if($lastmessage[3]==" ") break;}$message="MAIL FROM:".$send_email."\r\n";fputs($fp, $message); show_debug($message,"out");while(true){ $lastmessage=fgets($fp,512); show_debug($lastmessage,"in"); if($lastmessage[3]==" ") break;}$message="RCPT TO:".$to_email."\n";fputs($fp, $message);show_debug($message,"out");while(true){ $lastmessage=fgets($fp,512); show_debug($lastmessage,"in"); if($lastmessage[3]==" ") break;}$message="DATA\n";fputs($fp, $message); show_debug($message,"out");while(true){ $lastmessage=fgets($fp,512); show_debug($lastmessage,"in"); if($lastmessage[3]==" ") break;}$message="From: ".$send_email."\r\n";fputs($fp, $message); show_debug($message,"out");$message="To: ".$to_email."\r\n";fputs($fp, $message); show_debug($message,"out");$message="Subject: Test ".$smtp_server." email\r\n";fputs($fp, $message); show_debug($message,"out");$message="Content-Type: text/html; charset=gb2312\r\n";fputs($fp, $message); show_debug($message,"out");$message="\r\n";fputs($fp, $message); show_debug($message,"out");$message="Brainy 在测试 ".$smtp_server." email\r\n";fputs($fp, $message); show_debug($message,"out");$message="\r\n.\r\n";fputs($fp, $message); show_debug($message,"out");while(true){ $lastmessage=fgets($fp,512); show_debug($lastmessage,"in"); if($lastmessage[3]==" ") break;}?> 还有如果不需要身份验证的用"HELO"就可以了...否则就一定得用"EHLO" $fp = fsockopen("服务器名",25); // 链接服务器fputs($fp,"HELO \n"); // 初始话邮件接受发送fputs($fp,"MAIL FROM: 发送人地址 \n");fputs($fp,"RCPT TO: 邮件接受人地址\n");// 初始化邮件内容fputs($fp,"DATA\n");$body = "Subject: 标题 \n\n 邮件内容 \n.\n";// 开始发送fputs($fp,$body); fputs($fp,"QUIT \n"); fclose($fp);基本功能就是上面的几个函数,自己试试吧,是在不行,我帮你。 用Socket发送电子邮件 作者:limodou 在作者所申请的几个PHP 主页空间中,能够提供mail功能的实在不多,总是调用完mail()函数之后就毫无下文了。但是电子邮件在网上生活中的作用越来越大作用我不想再说了,但是如果主页空间不支持mail()发送那么怎么办呢?我也想过通过socket来实现邮件 发送,但无奈对用php 进行socket编程不熟悉,再加上发送邮件要用到SMTP协议,又要读不少的英文了,所 以一直也没有去研究过。终于有一天我发现了一篇文章,关于用socket编程发送邮件。我如获至宝般将其拷 贝下来,并且将其改造成了一个php 可用的类,供大家使用。原来的文章只是一个简单的例子,而且还有一 些错误,在我经过多次的实验、改造终于将其改成了一个直接使用socket,向指定的邮箱发送邮件的类,如 果大家和前面关于发送MIME的文章结合起来,就可以实现在不支持mail()函数的网站上发送邮件了。因为发 送邮件的过程需要时间,可能与mail()的处理机制还不完全一样,所以速度要慢一些,但是可以解决需要发 送邮件功能的燃眉之急,同时你也可以学习用php 进行socket编程。下面就将这个类的实现原理介绍给大家, 同时向大家讲解一些关于SMTP的基本知识。 Socket编程介绍 向大家申明,本人不是一个TCP/IP编程专家,故在此只是讲出了我的一点理解和体会。 使用fsockopen函数打开一个Internet连接,函数语法格式: int fsockopen(string hostname, int port, int [errno], string [errstr], int [timeout]); 参数的意思我想不用讲了,这里由于要使用SMTP协议,所以端口号为25。在打开连接成功后,会返回一 个socket句柄,使用它就可以象使用文件句柄一样的。可使用的操作有fputs(),fgets(),feof(),fclose() 等。 很简单地介绍就到这里吧。 SMTP的基础 基于TCP/IP的因特网协议一般的命令格式都是通过请求/ 应答方式实现的,采用的都是文本信息,所以 处理起来要容易一些。SMTP是简单邮件传输协议的简称,它可以实现客户端向服务器发送邮件的功能。所以 下面所讲的命令是指客户端向服务器发出请求指令,而响应则是指服务器返回给客户端的信息。 SMTP分为命令头和信息体两部分。命令头主要完成客户端与服务器的连接,验证等。整个过程由多条命 令组成。每个命令发到服务器后,由服务器给出响应信息,一般为3 位数字的响应码和响应文本。不同的服 务器返回的响应码是遵守协议的,但是响应正文本则不必。每个命令及响应的最后都有一个回车符,这样使 用fputs()和fgets()就可以进行命令与响应的处理了。SMTP的命令及响应信息都是单行的。信息体蚴怯始?的正文部分,最后的结束行应以单独的"."作为结束行。 客户端一些常用的SMTP指令为: HELO hostname: 与服务器打招呼并告知客户端使用的机器名字,可以随便填写 MAIL FROM: sender_id : 告诉服务器发信人的地址 RCPT TO: receiver_id : 告诉服务器收信人的地址 DATA : 下面开始传输信件内容,且最后要以只含有.的特殊行结束 RESET: 取消刚才的指令,从新开始 VERIFY userid: 校验帐号是否存在(此指令为可选指令,服务器可能不支持) QUIT : 退出连接,结束 服务器返回的响应信息为(格式为:响应码+空格+解释): 220 服务就绪(在socket连接成功时,会返回此信息) 221 正在处理 250 请求邮件动作正确,完成(HELO,MAIL FROM,RCPT TO,QUIT指令执行成功会返回此信息) 354 开始发送数据,结束以 .(DATA指令执行成功会返回此信息,客户端应发送信息) 500 语法错误,命令不能识别 550 命令不能执行,邮箱无效 552 中断处理:用户超出文件空间 下面给出一个简单的命令头(这是在打开socket之后做的),是我向stmp.263.net发邮件的测试结果: HELO limodou 250 smtp.263.net MAIL FROM: [email protected] 250 Ok RCPT TO: [email protected] 250 Ok DATA 354 End data with . To: [email protected] From: [email protected] Subject: test From: [email protected] test . QUIT 250 Ok: queued as C46411C5097E0 这就是一些SMTP的简单知识。相关内容可以查阅RFC。 RFC 821定义了收/发电子邮件的相关指令。 RFC 822则制定了邮件內容的格式。 RFC 2045-2048制定了多媒体邮件內容的格式, RFC 1113, 1422-1424则是讨论如何增进电子邮件的保密性。 send_mail类的实现 现在开始介绍我所编写的发送邮件类。有了上面的预备知识了,下面就是实现了。 类的成员变量 var $lastmessage; //记录最后返回的响应信息 var $lastact; //最后的动作,字符串形式 var $welcome; //用在HELO后面,欢迎用户 var $debug; //是否显示调试信息 var $smtp; //smtp服务器 var $port; //smtp端口号 var $fp; //socket句柄 其中,$lastmessage和$lastact用于记录最后一次响应信息及执行的命令,当出错时,用户可以使用它 们。为了测试需要,我还定义了$debug变量,当其值为true时,会在运行过程中显示一些执行信息,否则无 任何输出。$fp用于保存打开后的socket句柄。 类的构造 -------------------------------------------------------------------------------- function send_mail($smtp, $welcome="", $debug=false) { if(empty($smtp)) die("SMTP cannt be NULL!"); $this->smtp=$smtp; if(empty($welcome)) { $this->welcome=gethostbyaddr("localhost"); } else $this->welcome=$welcome; $this->debug=$debug; $this->lastmessage=""; $this->lastact=""; $this->port="25"; } -------------------------------------------------------------------------------- 这个构造函数主要完成一些初始值的判定及设置。$welcome用于HELO指令中,告诉服务器用户的名字。 HELO指令要求为机器名,但是不用也可以。如果用户没有给出$welcome,则自动查找本地的机器名。 用Socket发送电子邮件 作者:limodou 在作者所申请的几个PHP 主页空间中,能够提供mail功能的实在不多,总是调用完mail()函数之后就毫无下文了。但是电子邮件在网上生活中的作用越来越大作用我不想再说了,但是如果主页空间不支持mail()发送那么怎么办呢?我也想过通过socket来实现邮件 发送,但无奈对用php 进行socket编程不熟悉,再加上发送邮件要用到SMTP协议,又要读不少的英文了,所 以一直也没有去研究过。终于有一天我发现了一篇文章,关于用socket编程发送邮件。我如获至宝般将其拷 贝下来,并且将其改造成了一个php 可用的类,供大家使用。原来的文章只是一个简单的例子,而且还有一 些错误,在我经过多次的实验、改造终于将其改成了一个直接使用socket,向指定的邮箱发送邮件的类,如 果大家和前面关于发送MIME的文章结合起来,就可以实现在不支持mail()函数的网站上发送邮件了。因为发 送邮件的过程需要时间,可能与mail()的处理机制还不完全一样,所以速度要慢一些,但是可以解决需要发 送邮件功能的燃眉之急,同时你也可以学习用php 进行socket编程。下面就将这个类的实现原理介绍给大家, 同时向大家讲解一些关于SMTP的基本知识。 Socket编程介绍 向大家申明,本人不是一个TCP/IP编程专家,故在此只是讲出了我的一点理解和体会。 使用fsockopen函数打开一个Internet连接,函数语法格式: int fsockopen(string hostname, int port, int [errno], string [errstr], int [timeout]); 参数的意思我想不用讲了,这里由于要使用SMTP协议,所以端口号为25。在打开连接成功后,会返回一 个socket句柄,使用它就可以象使用文件句柄一样的。可使用的操作有fputs(),fgets(),feof(),fclose() 等。 很简单地介绍就到这里吧。 SMTP的基础 基于TCP/IP的因特网协议一般的命令格式都是通过请求/ 应答方式实现的,采用的都是文本信息,所以 处理起来要容易一些。SMTP是简单邮件传输协议的简称,它可以实现客户端向服务器发送邮件的功能。所以 下面所讲的命令是指客户端向服务器发出请求指令,而响应则是指服务器返回给客户端的信息。 SMTP分为命令头和信息体两部分。命令头主要完成客户端与服务器的连接,验证等。整个过程由多条命 令组成。每个命令发到服务器后,由服务器给出响应信息,一般为3 位数字的响应码和响应文本。不同的服 务器返回的响应码是遵守协议的,但是响应正文本则不必。每个命令及响应的最后都有一个回车符,这样使 用fputs()和fgets()就可以进行命令与响应的处理了。SMTP的命令及响应信息都是单行的。信息体蚴怯始?的正文部分,最后的结束行应以单独的"."作为结束行。 客户端一些常用的SMTP指令为: HELO hostname: 与服务器打招呼并告知客户端使用的机器名字,可以随便填写 MAIL FROM: sender_id : 告诉服务器发信人的地址 RCPT TO: receiver_id : 告诉服务器收信人的地址 DATA : 下面开始传输信件内容,且最后要以只含有.的特殊行结束 RESET: 取消刚才的指令,从新开始 VERIFY userid: 校验帐号是否存在(此指令为可选指令,服务器可能不支持) QUIT : 退出连接,结束 服务器返回的响应信息为(格式为:响应码+空格+解释): 220 服务就绪(在socket连接成功时,会返回此信息) 221 正在处理 250 请求邮件动作正确,完成(HELO,MAIL FROM,RCPT TO,QUIT指令执行成功会返回此信息) 354 开始发送数据,结束以 .(DATA指令执行成功会返回此信息,客户端应发送信息) 500 语法错误,命令不能识别 550 命令不能执行,邮箱无效 552 中断处理:用户超出文件空间 下面给出一个简单的命令头(这是在打开socket之后做的),是我向stmp.263.net发邮件的测试结果: HELO limodou 250 smtp.263.net MAIL FROM: [email protected] 250 Ok RCPT TO: [email protected] 250 Ok DATA 354 End data with . To: [email protected] From: [email protected] Subject: test From: [email protected] test . QUIT 250 Ok: queued as C46411C5097E0 这就是一些SMTP的简单知识。相关内容可以查阅RFC。 RFC 821定义了收/发电子邮件的相关指令。 RFC 822则制定了邮件內容的格式。 RFC 2045-2048制定了多媒体邮件內容的格式, RFC 1113, 1422-1424则是讨论如何增进电子邮件的保密性。 send_mail类的实现 现在开始介绍我所编写的发送邮件类。有了上面的预备知识了,下面就是实现了。 类的成员变量 var $lastmessage; //记录最后返回的响应信息 var $lastact; //最后的动作,字符串形式 var $welcome; //用在HELO后面,欢迎用户 var $debug; //是否显示调试信息 var $smtp; //smtp服务器 var $port; //smtp端口号 var $fp; //socket句柄 其中,$lastmessage和$lastact用于记录最后一次响应信息及执行的命令,当出错时,用户可以使用它 们。为了测试需要,我还定义了$debug变量,当其值为true时,会在运行过程中显示一些执行信息,否则无 任何输出。$fp用于保存打开后的socket句柄。 类的构造 -------------------------------------------------------------------------------- function send_mail($smtp, $welcome="", $debug=false) { if(empty($smtp)) die("SMTP cannt be NULL!"); $this->smtp=$smtp; if(empty($welcome)) { $this->welcome=gethostbyaddr("localhost"); } else $this->welcome=$welcome; $this->debug=$debug; $this->lastmessage=""; $this->lastact=""; $this->port="25"; } -------------------------------------------------------------------------------- 这个构造函数主要完成一些初始值的判定及设置。$welcome用于HELO指令中,告诉服务器用户的名字。 HELO指令要求为机器名,但是不用也可以。如果用户没有给出$welcome,则自动查找本地的机器名。 差不多快做好了,现在已经收发、查看邮件了czx.cxc.cc/demo/mail 文中并未涉及smtp身份验证的内容。现在的绝大多数公开的smtp服务器都需要身份验证。这个例子你看看,自己灵活运用吧。 下面是一个实际的例子,客户端在WinXP的Command窗口中通过“telnet smtp.263.NET 25="命令连接到263的smtp服务器发信:220 Welcome to coremail System(With Anti-Spam) 2.1EHLO 263.NET250-192.168.30.29250-PIPELINING250-SIZE 10240000250-ETRN250-AUTH LOGIN250 8BITMIMEAUTH LOGIN334 VXNlcm5hbWU6bXlhY2NvdW50334 UGFzc3dvcmQ6bXlwYXNzd29yZA==235 Authentication successfulMAIL FROM:[email protected]250 OkRCPT TO:[email protected]250 OkData354 End data with <CR><LF>.<CR><LF>This is a testing email.haha..250 Ok: queued as AC5291D6406C4QUIT221 Bye上面的内容就是发信的全过程。其中与身份验证有关的主要是第九到第十四行:AUTH LOGIN '客户端输入334 VXNlcm5hbWU6 '服务器提示“Username:="bXlhY2NvdW50 '客户端输入“myaccount="的Base64编码334 UGFzc3dvcmQ6 '服务器提示“Password:="bXlwYXNzd29yZA== '客户端输入“mypassword="的Base64编码235 Authentication successful '服务器端通过验证从上面的分析可以看出,在这个身份验证过程中,服务器和客户端都直接通过Socket传递经过标准Base64编码的纯文本。这个过程可以非常方便的用C#实现,或者直接添加到原有的源代码中。另外,有些ESMTP服务器不支持AUTH LOGIN方式的认证,只支持AUTH CRAM-MD5方式验证。但是这两者之间的区别只是文本的编码方式不同。 如果你用的是linux服务器,可以自己把这个linux服务器设置成为smtp服务器,只要设置一下sendmail服务就可以,关于设置这个服务,在好多的linux站点都有介绍的。只要几步就搞定了。但注意在internet上最好不要让其它人用你的smtp发送大量的垃圾。 php实现把csv文件中的数据导入到数据库中 input button 一个很严重的问题 怎么随机生成多个不相同的数字? 怎么一个if语句能跨两个php段? php检测checkbox是否勾选 html生成word,带图片和样式 超级奇怪的问题。大家来帮帮忙! 那里可以下pear的帮助啊!!!急!!!! php中怎样访问一个别的网站上的php(网页)? php与mysql连接的问题 为什么Undefined index这个错误会存在$_Request调用中? 有函数可以查找字符串中是否含有指定字符吗?
//这个是把邮件编码的类.
//这个类没有对邮件进行任何编码,只是普通的text_mail,把邮件头等东西加上去而已.
<?php
class text_mail{
var $reply;
var $to;
var $from;
var $subject;
var $body; function text_mail(){
$this->to="";
$this->from="";
$this->subject="";
$this->body="";
$this->reply="";
} function get_mail(){
$mail="From: $this->from \r\n";
$mail.="Reply-To: $this->reply \r\n";
$mail.="To: $this->to \r\n";
$mail.="Subject: $this->subject \r\n";
$mail.="Mime-verson:1.0 \r\n";
$mail.="Content-Type: text/plain;charset=\"GB2312\"\r\n";
$mail.="Content-Transfer-Encoding: 8bit\r\n";
$mail.="\r\n";
$mail.=str_replace("\n.\r\n","\n. \r\n",$this->body);
return $mail;
}
};
?>===============inc/smtp_mail.class.php==============
<?php
class smtp_mail{
var $fp=false;
var $lastmsg="";
var $authMode=false;
var $authLastLine;
var $debugMode=false;
var $authLoginName;
var $authLoginPassword; function read_line(){
$ret=false;
$line=fgets($this->fp,1024);
if($this->debugMode){
echo "RESPONSE: $line <br>";
flush();
}
if(ereg("^([0-9]+).(.*)$",$line,$data)){
$recv_code=$data[1];
$recv_msg=$data[2];
$ret=array($recv_code,$recv_msg);
}
return $ret;
} function dialogue($code,$cmd,$response=false){
$ret=true;
if($this->debugMode){
echo "CWD: $cmd <br>";
flush();
}
fwrite($this->fp,$cmd."\r\n");
$line=$this->read_line();
if($line==false){
$ret=false;
$this->lastmsg="";
}
else{
$this->lastmsg="$line[0] $line[1]";
if($line[0]!=$code){
$ret=false;
return $ret;
}
if($response!==false){
$response.="\r\n";
while($line[1]!=$response){
$line=$this->read_line();
// $this->lastmsg.="<br>$line[0] $line[1]";
if($line[0]!=$code){
$ret=false;
return $ret;
}
}
}
return $ret;
}
} function error_message(){
echo "SMTP Protocol failure (".$this->lastmsg.").<br>";
flush();
} function crlf_encode($data){
$data.="\n";
$data=str_replace("\n","\r\n",str_replace("\r","",$data));
$data=str_replace("\n.\r\n","\n. \r\n",$data);
return $data;
} function handle_email($from,$to,$data){
$rcpts=explode(",",$to);
$err=false;
if(!$this->dialogue(250,"HELO")){
$err=true;
}
if(!$this->dialogue(250,"EHLO",$this->authLastLine)){
$err=true;
}
if($this->authMode){
if(!$this->dialogue(334,"AUTH LOGIN")) {
$err=true;
}
if(!$this->dialogue(334,base64_encode($this->authLoginName))){
$err=true;
}
if(!$this->dialogue(235,base64_encode($this->authLoginPassword))){
$err=true;
}
}
if(!$this->dialogue(250,"MAIL FROM: $from") ){
$err=true;
}
for($i=0;!$err&&$i<count($rcpts);$i++){
if(!$this->dialogue(250,"RCPT TO: $rcpts[$i]")){
$err=true;
}
}
if($err||!$this->dialogue(354,"DATA")||!fwrite($this->fp,$data)||!$this->dialogue(250,"\r\n.")||!$this->dialogue(221,"QUIT") ){
$err=true;
}
if($err){
$this->error_message();
}
return !$err;
} function connect($hostname){
if($this->debugMode){
echo "CONNECTING $hostname ...";
}
$ret=false;
$this->fp=fsockopen($hostname,25);
if($this->fp){
$ret=true;
if($this->debugMode){
echo "Succeed!<br>";
flush();
}
}
else{
if($this->debugMode){
echo "Failed!<br>";
flush();
}
}
return $ret;
} function send_email($hostname,$from,$to,$data,$crlf_encode=1){
if(!$this->connect($hostname)){
echo "cannot open connection!<br>\n";
flush();
return false;
}
$line=$this->read_line();
$ret=false;
if($line&&$line[0]=="220"){
if($crlf_encode){
$data=$this->crlf_encode($data);
}
$ret=$this->handle_email($from,$to,$data);
}
else{
$this->error_message();
}
fclose($this->fp);
return $ret;
}
};
?>===================testmail.php======================
<?php
//include "inc/mime_mail.php";
set_time_limit(100);
include "inc/text_mail.class.php";
include "inc/smtp_mail.class.php";$smtp_server="mailserver here"; //这里为smtp服务器地址.
$from="mail sender here"; //发信人
$to="mail receiver here"; //收信人
$subject="test HERE!!!!!!"; //题目
$body="test only!
fdsafsdajfkljdklsfsda
fds
fdsaf
dsfsdafds
f"; //内容$mail=new text_mail; //初始化mail主体
$mail->from=$from;
$mail->to=$to;
$mail->subject=$subject;
$mail->body=$body;
$mail->reply=$from;
$data=$mail->get_mail();
$smtp=new smtp_mail; //初始化smtp_mail类
$smtp->debugMode=false; //debug模式
$smtp->authMode=false; //smtp服务器验证模式(如果服务器要验证才需要)
/* 这里几行是当服务器需要验证的时候才用上.
//$smtp->authLastLine="OK"; //ehlo命令列出的最后一行的文字
//$smtp->authLoginName="auth username";
//$smtp->authLoginPassword="auth password";
*/
$smtp->send_email($smtp_server,$from,$to,$data); //发送邮件
?>
SMTP Protocol failure (250 2.1.0 [email protected]... Sender ok ).
你好,你所说的我在jsp里用过了,可是这次客户并没有租数据库!pcdreama(峰幻):
你的代码我试了,可我不会改你的代码,好象不行!其实我上面的代码是正确的,只是服务器不支持外部邮箱吧了!
我以经搞定了(只能用内部邮箱),谢谢大家!大家谁能帮个忙,找个支持外部邮箱的smtp server!
我觉得是smtp服务器的问题吧,把那个服务器公布出来让大家测试一下就知道啦.
SMTP Protocol failure (). 信息.
這是為什么呢?
CONNECTING mail.xxxxx.com.cn ...Succeed!
RESPONSE: 220 tsnc-cs1.inc.iac ESMTP Server (Microsoft Exchange Internet Mail Service 5.5.2653.13) ready
CWD: HELO
RESPONSE: 250 OK
CWD: EHLO
RESPONSE: 503 Bad Sequence
CWD: AUTH LOGIN
RESPONSE: 334 VXNlcm5hbWU6
CWD: xxxx
RESPONSE: 334 UGFzc3dvcmQ6
CWD: xxxxxxxx
RESPONSE: 235 LOGIN authentication successful
CWD: MAIL FROM: [email protected]
RESPONSE: 250 OK - mail from
SMTP Protocol failure (250 OK - mail from ).注意到:
CWD: EHLO
RESPONSE: 503 Bad Sequence
后,我把smtp_mail.class.php中handle_email($from,$to,$data)函数中的:
if (!$this->dialogue(250,"EHLO",$this->authLastLine))
$err=true;
注释掉了,结果瞎猫碰死老鼠,竟然能发邮件了,结果如下:
CONNECTING mail.xxxxx.com.cn ...Succeed!
RESPONSE: 220 tsnc-cs1.inc.iac ESMTP Server (Microsoft Exchange Internet Mail Service 5.5.2653.13) ready
CWD: HELO
RESPONSE: 250 OK
CWD: AUTH LOGIN
RESPONSE: 334 VXNlcm5hbWU6
CWD: xxxx
RESPONSE: 334 UGFzc3dvcmQ6
CWD: xxxxxxxx
RESPONSE: 235 LOGIN authentication successful
CWD: MAIL FROM: [email protected]
RESPONSE: 250 OK - mail from
CWD: RCPT TO: [email protected]
RESPONSE: 250 OK - Recipient
CWD: DATA
RESPONSE: 354 Send data. End with CRLF.CRLF
CWD: .
RESPONSE: 250 OK
CWD: QUIT
RESPONSE: 221 closing connection 但是另外一个服务器,则一定不能删掉那几句,必须用pcdreama(峰幻)的程序,结果如下:
CONNECTING mail.xxxxxxxx.com ...Succeed!
RESPONSE: 220 mail.xxxxxxxx.com Microsoft ESMTP MAIL Service, Version: 5.0.2195.2966 ready at Sun, 29 Sep 2002 15:03:23 +0800
CWD: HELO
RESPONSE: 250 mail.xxxxxxxx.com Hello [61.171.xx.xxx]
CWD: EHLO
RESPONSE: 250-mail.xxxxxxxx.com Hello [61.171.xx.xxx]
RESPONSE: 250-TURN
RESPONSE: 250-ATRN
RESPONSE: 250-SIZE
RESPONSE: 250-ETRN
RESPONSE: 250-PIPELINING
RESPONSE: 250-DSN
RESPONSE: 250-ENHANCEDSTATUSCODES
RESPONSE: 250-8bitmime
RESPONSE: 250-BINARYMIME
RESPONSE: 250-CHUNKING
RESPONSE: 250-VRFY
RESPONSE: 250-X-EXPS GSSAPI NTLM LOGIN
RESPONSE: 250-X-EXPS=LOGIN
RESPONSE: 250-AUTH GSSAPI NTLM LOGIN
RESPONSE: 250-AUTH=LOGIN
RESPONSE: 250-X-LINK2STATE
RESPONSE: 250-XEXCH50
RESPONSE: 250 OK
CWD: AUTH LOGIN
RESPONSE: 334 VXNlcm5hbWU6
CWD: xxxx
RESPONSE: 334 UGFzc3dvcmQ6
CWD: xxxxxxxxxxx
RESPONSE: 235 2.7.0 Authentication successful.
CWD: MAIL FROM: [email protected]
RESPONSE: 250 2.1.0 [email protected] OK
CWD: RCPT TO: [email protected]
RESPONSE: 250 2.1.5 [email protected]
CWD: DATA
RESPONSE: 354 Start mail input; end with .
CWD: .
RESPONSE: 250 2.6.0 Queued mail for delivery
CWD: QUIT
RESPONSE: 221 2.0.0 mail.xxxxxxxx.com Service closing transmission channel 如果删掉那几句,结果如下:
CONNECTING mail.xxxxxxx.com ...Succeed!
RESPONSE: 220 mail.xxxxxxxx.com Microsoft ESMTP MAIL Service, Version: 5.0.2195.2966 ready at Sun, 29 Sep 2002 15:14:36 +0800
CWD: HELO
RESPONSE: 250 mail.xxxxxxxx.com Hello [61.171.xx.xxx]
CWD: AUTH LOGIN
RESPONSE: 503 5.5.2 Send hello first.
CWD: xxxx
RESPONSE: 500 5.3.3 Unrecognized command
CWD: xxxxxxxxxxx
RESPONSE: 500 5.3.3 Unrecognized command
CWD: MAIL FROM: [email protected]
RESPONSE: 250 2.1.0 [email protected] OK
SMTP Protocol failure (250 2.1.0 [email protected] OK ).
注意到:
CWD: AUTH LOGIN
RESPONSE: 503 5.5.2 Send hello first.
因为少发送了一个EHLO,所以服务器要求先发送hello.至于为什么会有这种情况,我也不懂,只是觉得的确跟服务器的设置很有关系.
(e-mail都被xxx掉了,抱歉)
支持认证http://www.hooday.com/?n=ShowClass&a=36不支持附件
http://bbs.r51.net
我很想用21cn.com的来发啊。请各位提供意见。
培植php.ini文件的smtp。
比如是新浪,smtp.sina.com
下面是程序原代码。
http://www.csdn.net/cnshare/soft/13/13021.shtm
我们测试过。
俺的几个网站都这么干,服务器用的是俺们学校的smtp服务器,不用白不用.
<?
function show_debug($message, $inout)
{
if($inout=="in") //响应信息
{
$m='<< ';
}
else
$m='>> '; $message=Str_replace("<","<",$message);
$message=Str_replace(">",">",$message); if(!ereg("\n$", $message))
$message .= "<br>";
$message=nl2br($message);
echo "<font color=#999999>".$m.$message."</font>";
} $smtp_server='';
$smtp_username='';
$smtp_password='';
$send_email = '';
$to_email = '';$fp = fsockopen ($smtp_server, "25");
set_socket_blocking( $fp, true );
while(true)
{
$lastmessage=fgets($fp,512);
show_debug($lastmessage,"in");
if(substr($lastmessage,3,1)==" ")
break;
}$message="EHLO ".$smtp_username."\r\n";
fputs($fp, $message);
show_debug($message,"out");
while(true)
{
$lastmessage=fgets($fp,512);
show_debug($lastmessage,"in"); if($lastmessage[3]==" ")
break;
}$message="AUTH LOGIN\n";
fputs($fp, $message);
show_debug($message,"out");
while(true)
{
$lastmessage=fgets($fp,512);
show_debug($lastmessage,"in"); if($lastmessage[3]==" ")
break;
}$message=base64_encode($smtp_username)."\r\n";
fputs($fp, $message);
show_debug($message,"out");
while(true)
{
$lastmessage=fgets($fp,512);
show_debug($lastmessage,"in"); if($lastmessage[3]==" ")
break;
}$message=base64_encode($smtp_password)."\r\n";
fputs($fp, $message);
show_debug($message,"out");
while(true)
{
$lastmessage=fgets($fp,512);
show_debug($lastmessage,"in"); if($lastmessage[3]==" ")
break;
}$message="MAIL FROM:".$send_email."\r\n";
fputs($fp, $message);
show_debug($message,"out");
while(true)
{
$lastmessage=fgets($fp,512);
show_debug($lastmessage,"in"); if($lastmessage[3]==" ")
break;
}$message="RCPT TO:".$to_email."\n";
fputs($fp, $message);
show_debug($message,"out");
while(true)
{
$lastmessage=fgets($fp,512);
show_debug($lastmessage,"in"); if($lastmessage[3]==" ")
break;
}
$message="DATA\n";
fputs($fp, $message);
show_debug($message,"out");
while(true)
{
$lastmessage=fgets($fp,512);
show_debug($lastmessage,"in"); if($lastmessage[3]==" ")
break;
}$message="From: ".$send_email."\r\n";
fputs($fp, $message);
show_debug($message,"out");
$message="To: ".$to_email."\r\n";
fputs($fp, $message);
show_debug($message,"out");
$message="Subject: Test ".$smtp_server." email\r\n";
fputs($fp, $message);
show_debug($message,"out");
$message="Content-Type: text/html; charset=gb2312\r\n";
fputs($fp, $message);
show_debug($message,"out");
$message="\r\n";
fputs($fp, $message);
show_debug($message,"out");
$message="Brainy 在测试 ".$smtp_server." email\r\n";
fputs($fp, $message);
show_debug($message,"out");
$message="\r\n.\r\n";
fputs($fp, $message);
show_debug($message,"out");
while(true)
{
$lastmessage=fgets($fp,512);
show_debug($lastmessage,"in"); if($lastmessage[3]==" ")
break;
}
?>
// 链接服务器
fputs($fp,"HELO \n");
// 初始话邮件接受发送
fputs($fp,"MAIL FROM: 发送人地址 \n");
fputs($fp,"RCPT TO: 邮件接受人地址\n");
// 初始化邮件内容
fputs($fp,"DATA\n");
$body = "Subject: 标题 \n\n 邮件内容 \n.\n";
// 开始发送
fputs($fp,$body);
fputs($fp,"QUIT \n");
fclose($fp);
基本功能就是上面的几个函数,自己试试吧,是在不行,我帮你。
作者:limodou
在作者所申请的几个PHP 主页空间中,能够提供mail功能的实在不多,总是调用完mail()函数之后就毫
无下文了。但是电子邮件在网上生活中的作用越来越大作用我不想再说了,但是如果主页空间不支持mail()发送那么怎么办呢?我也想过通过socket来实现邮件
发送,但无奈对用php 进行socket编程不熟悉,再加上发送邮件要用到SMTP协议,又要读不少的英文了,所
以一直也没有去研究过。终于有一天我发现了一篇文章,关于用socket编程发送邮件。我如获至宝般将其拷
贝下来,并且将其改造成了一个php 可用的类,供大家使用。原来的文章只是一个简单的例子,而且还有一
些错误,在我经过多次的实验、改造终于将其改成了一个直接使用socket,向指定的邮箱发送邮件的类,如
果大家和前面关于发送MIME的文章结合起来,就可以实现在不支持mail()函数的网站上发送邮件了。因为发
送邮件的过程需要时间,可能与mail()的处理机制还不完全一样,所以速度要慢一些,但是可以解决需要发
送邮件功能的燃眉之急,同时你也可以学习用php 进行socket编程。下面就将这个类的实现原理介绍给大家,
同时向大家讲解一些关于SMTP的基本知识。 Socket编程介绍
向大家申明,本人不是一个TCP/IP编程专家,故在此只是讲出了我的一点理解和体会。 使用fsockopen函数打开一个Internet连接,函数语法格式: int fsockopen(string hostname, int port, int [errno], string [errstr], int [timeout]); 参数的意思我想不用讲了,这里由于要使用SMTP协议,所以端口号为25。在打开连接成功后,会返回一
个socket句柄,使用它就可以象使用文件句柄一样的。可使用的操作有fputs(),fgets(),feof(),fclose()
等。 很简单地介绍就到这里吧。 SMTP的基础
基于TCP/IP的因特网协议一般的命令格式都是通过请求/ 应答方式实现的,采用的都是文本信息,所以
处理起来要容易一些。SMTP是简单邮件传输协议的简称,它可以实现客户端向服务器发送邮件的功能。所以
下面所讲的命令是指客户端向服务器发出请求指令,而响应则是指服务器返回给客户端的信息。 SMTP分为命令头和信息体两部分。命令头主要完成客户端与服务器的连接,验证等。整个过程由多条命
令组成。每个命令发到服务器后,由服务器给出响应信息,一般为3 位数字的响应码和响应文本。不同的服
务器返回的响应码是遵守协议的,但是响应正文本则不必。每个命令及响应的最后都有一个回车符,这样使
用fputs()和fgets()就可以进行命令与响应的处理了。SMTP的命令及响应信息都是单行的。信息体蚴怯始?
的正文部分,最后的结束行应以单独的"."作为结束行。 客户端一些常用的SMTP指令为: HELO hostname: 与服务器打招呼并告知客户端使用的机器名字,可以随便填写
MAIL FROM: sender_id : 告诉服务器发信人的地址
RCPT TO: receiver_id : 告诉服务器收信人的地址
DATA : 下面开始传输信件内容,且最后要以只含有.的特殊行结束
RESET: 取消刚才的指令,从新开始
VERIFY userid: 校验帐号是否存在(此指令为可选指令,服务器可能不支持)
QUIT : 退出连接,结束
服务器返回的响应信息为(格式为:响应码+空格+解释): 220 服务就绪(在socket连接成功时,会返回此信息)
221 正在处理
250 请求邮件动作正确,完成(HELO,MAIL FROM,RCPT TO,QUIT指令执行成功会返回此信息)
354 开始发送数据,结束以 .(DATA指令执行成功会返回此信息,客户端应发送信息)
500 语法错误,命令不能识别
550 命令不能执行,邮箱无效
552 中断处理:用户超出文件空间
下面给出一个简单的命令头(这是在打开socket之后做的),是我向stmp.263.net发邮件的测试结果: HELO limodou
250 smtp.263.net
MAIL FROM: [email protected]
250 Ok
RCPT TO: [email protected]
250 Ok
DATA
354 End data with .
To: [email protected]
From: [email protected]
Subject: test
From: [email protected]
test
.
QUIT
250 Ok: queued as C46411C5097E0 这就是一些SMTP的简单知识。相关内容可以查阅RFC。 RFC 821定义了收/发电子邮件的相关指令。
RFC 822则制定了邮件內容的格式。
RFC 2045-2048制定了多媒体邮件內容的格式,
RFC 1113, 1422-1424则是讨论如何增进电子邮件的保密性。 send_mail类的实现
现在开始介绍我所编写的发送邮件类。有了上面的预备知识了,下面就是实现了。 类的成员变量 var $lastmessage; //记录最后返回的响应信息
var $lastact; //最后的动作,字符串形式
var $welcome; //用在HELO后面,欢迎用户
var $debug; //是否显示调试信息
var $smtp; //smtp服务器
var $port; //smtp端口号
var $fp; //socket句柄 其中,$lastmessage和$lastact用于记录最后一次响应信息及执行的命令,当出错时,用户可以使用它
们。为了测试需要,我还定义了$debug变量,当其值为true时,会在运行过程中显示一些执行信息,否则无
任何输出。$fp用于保存打开后的socket句柄。 类的构造
--------------------------------------------------------------------------------
function send_mail($smtp, $welcome="", $debug=false)
{
if(empty($smtp)) die("SMTP cannt be NULL!");
$this->smtp=$smtp;
if(empty($welcome))
{
$this->welcome=gethostbyaddr("localhost");
}
else
$this->welcome=$welcome;
$this->debug=$debug;
$this->lastmessage="";
$this->lastact="";
$this->port="25";
}
--------------------------------------------------------------------------------
这个构造函数主要完成一些初始值的判定及设置。$welcome用于HELO指令中,告诉服务器用户的名字。
HELO指令要求为机器名,但是不用也可以。如果用户没有给出$welcome,则自动查找本地的机器名。
作者:limodou
在作者所申请的几个PHP 主页空间中,能够提供mail功能的实在不多,总是调用完mail()函数之后就毫
无下文了。但是电子邮件在网上生活中的作用越来越大作用我不想再说了,但是如果主页空间不支持mail()发送那么怎么办呢?我也想过通过socket来实现邮件
发送,但无奈对用php 进行socket编程不熟悉,再加上发送邮件要用到SMTP协议,又要读不少的英文了,所
以一直也没有去研究过。终于有一天我发现了一篇文章,关于用socket编程发送邮件。我如获至宝般将其拷
贝下来,并且将其改造成了一个php 可用的类,供大家使用。原来的文章只是一个简单的例子,而且还有一
些错误,在我经过多次的实验、改造终于将其改成了一个直接使用socket,向指定的邮箱发送邮件的类,如
果大家和前面关于发送MIME的文章结合起来,就可以实现在不支持mail()函数的网站上发送邮件了。因为发
送邮件的过程需要时间,可能与mail()的处理机制还不完全一样,所以速度要慢一些,但是可以解决需要发
送邮件功能的燃眉之急,同时你也可以学习用php 进行socket编程。下面就将这个类的实现原理介绍给大家,
同时向大家讲解一些关于SMTP的基本知识。 Socket编程介绍
向大家申明,本人不是一个TCP/IP编程专家,故在此只是讲出了我的一点理解和体会。 使用fsockopen函数打开一个Internet连接,函数语法格式: int fsockopen(string hostname, int port, int [errno], string [errstr], int [timeout]); 参数的意思我想不用讲了,这里由于要使用SMTP协议,所以端口号为25。在打开连接成功后,会返回一
个socket句柄,使用它就可以象使用文件句柄一样的。可使用的操作有fputs(),fgets(),feof(),fclose()
等。 很简单地介绍就到这里吧。 SMTP的基础
基于TCP/IP的因特网协议一般的命令格式都是通过请求/ 应答方式实现的,采用的都是文本信息,所以
处理起来要容易一些。SMTP是简单邮件传输协议的简称,它可以实现客户端向服务器发送邮件的功能。所以
下面所讲的命令是指客户端向服务器发出请求指令,而响应则是指服务器返回给客户端的信息。 SMTP分为命令头和信息体两部分。命令头主要完成客户端与服务器的连接,验证等。整个过程由多条命
令组成。每个命令发到服务器后,由服务器给出响应信息,一般为3 位数字的响应码和响应文本。不同的服
务器返回的响应码是遵守协议的,但是响应正文本则不必。每个命令及响应的最后都有一个回车符,这样使
用fputs()和fgets()就可以进行命令与响应的处理了。SMTP的命令及响应信息都是单行的。信息体蚴怯始?
的正文部分,最后的结束行应以单独的"."作为结束行。 客户端一些常用的SMTP指令为: HELO hostname: 与服务器打招呼并告知客户端使用的机器名字,可以随便填写
MAIL FROM: sender_id : 告诉服务器发信人的地址
RCPT TO: receiver_id : 告诉服务器收信人的地址
DATA : 下面开始传输信件内容,且最后要以只含有.的特殊行结束
RESET: 取消刚才的指令,从新开始
VERIFY userid: 校验帐号是否存在(此指令为可选指令,服务器可能不支持)
QUIT : 退出连接,结束
服务器返回的响应信息为(格式为:响应码+空格+解释): 220 服务就绪(在socket连接成功时,会返回此信息)
221 正在处理
250 请求邮件动作正确,完成(HELO,MAIL FROM,RCPT TO,QUIT指令执行成功会返回此信息)
354 开始发送数据,结束以 .(DATA指令执行成功会返回此信息,客户端应发送信息)
500 语法错误,命令不能识别
550 命令不能执行,邮箱无效
552 中断处理:用户超出文件空间
下面给出一个简单的命令头(这是在打开socket之后做的),是我向stmp.263.net发邮件的测试结果: HELO limodou
250 smtp.263.net
MAIL FROM: [email protected]
250 Ok
RCPT TO: [email protected]
250 Ok
DATA
354 End data with .
To: [email protected]
From: [email protected]
Subject: test
From: [email protected]
test
.
QUIT
250 Ok: queued as C46411C5097E0
这就是一些SMTP的简单知识。相关内容可以查阅RFC。 RFC 821定义了收/发电子邮件的相关指令。
RFC 822则制定了邮件內容的格式。
RFC 2045-2048制定了多媒体邮件內容的格式,
RFC 1113, 1422-1424则是讨论如何增进电子邮件的保密性。 send_mail类的实现
现在开始介绍我所编写的发送邮件类。有了上面的预备知识了,下面就是实现了。 类的成员变量 var $lastmessage; //记录最后返回的响应信息
var $lastact; //最后的动作,字符串形式
var $welcome; //用在HELO后面,欢迎用户
var $debug; //是否显示调试信息
var $smtp; //smtp服务器
var $port; //smtp端口号
var $fp; //socket句柄 其中,$lastmessage和$lastact用于记录最后一次响应信息及执行的命令,当出错时,用户可以使用它
们。为了测试需要,我还定义了$debug变量,当其值为true时,会在运行过程中显示一些执行信息,否则无
任何输出。$fp用于保存打开后的socket句柄。 类的构造
--------------------------------------------------------------------------------
function send_mail($smtp, $welcome="", $debug=false)
{
if(empty($smtp)) die("SMTP cannt be NULL!");
$this->smtp=$smtp;
if(empty($welcome))
{
$this->welcome=gethostbyaddr("localhost");
}
else
$this->welcome=$welcome;
$this->debug=$debug;
$this->lastmessage="";
$this->lastact="";
$this->port="25";
}
--------------------------------------------------------------------------------
这个构造函数主要完成一些初始值的判定及设置。$welcome用于HELO指令中,告诉服务器用户的名字。
HELO指令要求为机器名,但是不用也可以。如果用户没有给出$welcome,则自动查找本地的机器名。
czx.cxc.cc/demo/mail
这个例子你看看,自己灵活运用吧。
220 Welcome to coremail System(With Anti-Spam) 2.1
EHLO 263.NET
250-192.168.30.29
250-PIPELINING
250-SIZE 10240000
250-ETRN
250-AUTH LOGIN
250 8BITMIME
AUTH LOGIN
334 VXNlcm5hbWU6
bXlhY2NvdW50
334 UGFzc3dvcmQ6
bXlwYXNzd29yZA==
235 Authentication successful
MAIL FROM:[email protected]
250 Ok
RCPT TO:[email protected]
250 Ok
Data
354 End data with <CR><LF>.<CR><LF>
This is a testing email.
haha.
.
250 Ok: queued as AC5291D6406C4
QUIT
221 Bye
上面的内容就是发信的全过程。其中与身份验证有关的主要是第九到第十四行:
AUTH LOGIN '客户端输入
334 VXNlcm5hbWU6 '服务器提示“Username:="
bXlhY2NvdW50 '客户端输入“myaccount="的Base64编码
334 UGFzc3dvcmQ6 '服务器提示“Password:="
bXlwYXNzd29yZA== '客户端输入“mypassword="的Base64编码
235 Authentication successful '服务器端通过验证
从上面的分析可以看出,在这个身份验证过程中,服务器和客户端都直接通过Socket传递经过标准Base64编码的纯文本。这个过程可以非常方便的用C#实现,或者直接添加到原有的源代码中。
另外,有些ESMTP服务器不支持AUTH LOGIN方式的认证,只支持AUTH CRAM-MD5方式验证。但是这两者之间的区别只是文本的编码方式不同。
但注意在internet上最好不要让其它人用你的smtp发送大量的垃圾。