您的位置:首页 > 编程语言 > PHP开发

php发送邮件原理

2015-06-03 14:31 513 查看
本文乃转载
一个发送E-MAIL的脚本也许是你能够在Web 站点上找到的最普通的脚本之一了,虽然它很简单,一个邮件脚本有时会令程序员非常沮丧.PHP中有一个叫做mail()的函数,它只需要知道接收方的地址 和信件主体就可以发送邮件,但是要让mail()按你的意思运行你还需要解决一些棘手的问题.

  要使mail()能够运行,你必须有一 个SMTP服务器以便PHP能够连接上去.不管这个服务器对邮件程序多么重要,大多数人对它如何运转没有一星半点的概念.在本教程中,我们将揭示SMTP 的秘密并解决一些使用PHP发送邮件的常见问题.而本文中的另一些主题将包括循环遍历一个地址列表的方法以及同时以文本和HTML格式向接收者发送一个邮 件的方法.

SMTP是简单邮件传输协议(Simple Mail Transfer Protocol)的缩写,而一个SMTP服务器是一台运行这种协议并发出邮件的计算机.运行这种协议实际上指的是运行诸如Sendmail和Qmail 的程序--如果你使用的是一台非Windows计算机的话.在Windows平台上,作为Windows NT Service Pack一部分或是内建于Windows 2000内部的SMTP服务程序就是典型的这种程序.

我并不是说SMTP软件包就只有那些,但 是它们是最普通的.如果你的Web站点使用了互联网服务提供者的主机软件包(Internet Service Provider's virtual hosting package)的一部分,那么SMTP服务程序就应该已经在这台计算机上安装了.如果你是一台位于ISP或是室内的计算机的系统管理员,那么你很有可能 已经在这台计算机上安装了某种SMTP软件,用来处理从Web服务器发送邮件的过程.

但是,如果你是一个个人用户并只有一个开发用的 Web服务程序运行在你的个人电脑上,你可能没有在自己的机器上运行SMTP软件.下面是一个非常简单但是准确的拇指定律:如果你是一个Windows用 户而从没有看见SMTP服务器这样的字眼,那么你就没有运行这个程序.如果你确实没有,那么你有两种选择: 安装,配置,和维护一个SMTP服务程序(如果你不知道那是怎么一回事的话就不推荐你使用这种方法)或是使用一个现存的SMTP服务器.

" 如果一个服务器现在没有运行的话,我又怎么使用它呢?"你可能要问.如果你的计算机是通过拨号连接(或是DSL或电缆)连到互联网的话,你可以使用你 ISP的外发邮件服务器.例如,如果你开发用的 计算机是一个Windows98的系统并使用56kbps modem通过EarthLink连接到互联网,那么你就可以使用mail.earthlink.net作为你的SMTP服务器.不论你对你的外发邮件服 务器使用什么样的邮件客户端(Eudora, Outlook, Netscape Mail等等),它们都将和你的PHP代码使用你的SMTP服务器的过程一样.技巧就是使PHP知道一点点事实.

在php.ini管理配置文件里,有几个条目需要被设置以便mail()函数能够正常运行.在改变它们以前,搞清楚它们都是做什么用的.你可以使用phpinfo()函数通过创建一个文件来显示系统当前的配置情况,这个文件包括:

<? phpinfo() ?>

保存这个文件,将它放置到你的Web服务程序的文件根目录,然后通过你的浏览器访问它.你应该可以看到一个被优美的格式化了的信息,显示你的配置情况.你要查看的条目如下:

SMTP

sendmail_from

sendmail_path

如果你没有使用windows,那么sendmail_path指令就是你唯一要担心的东西.如果你正在使用Windows,你就需要看看最后两个指令.

如果你使用的是Linux或是一个Unix变种,sendmail_path看起来应该象这样:

sendmail_path = /usr/sbin/sendmail

或者如果你使用Qmail:

sendmail_path = /var/qmail/bin/sendmail

在这条指令里,你还可以设置配置参数来指明队列缓冲选项或是显示的设置Return-Path头,如下所示:

sendmail_path = /usr/sbin/sendmail -t -fyou@yourdomain.com

作 为一个非Windows用户,这就是你要做的一切了.如果你使用的是Windows,你有更多的事情要做.你还需要看一看SMTP和 sendmail_from的值.不要被sendmail_from指令名字中的sendmail弄迷糊了.虽然你没有在Windows上使用名叫 Sendmail的程序,但那只是指令的名字.不要被它吓到了.

在你的phpinfo()显示的结果里,看看SMTP和sendmail_from的缺省值--它们要么是空白,要么包含了胡乱的值.你应该把它们改成有意义的值.

如果你决心在这台电脑上运行一个SMTP服务程序,你在php.ini文件中的条目就应该如下:

SMTP = localhost

但是,如果你要使用你ISP(在这个例子中是EarthLink)的外发邮件服务器,那么php.ini中的邮件看起来应该如下:

SMTP = mail.earthlink.net

你也可以使用IP地址而不是域名,因为计算机不区分这两种条目.

第二条配置指令是sendmail_from,它应该被设置成From头中的电子邮件地址.它可以在脚本里被修改但是通常作为缺省值使用.下面就是这个配置指令的示例youraddress@yourdomain.com指的是你自己的邮件地址.

sendmail_from = youraddress@yourdomain.com

在做了这些配置上的改动以后,重启Web服务程序然后使用phpinfo()函数来验证这些修改.在这些工作完成以后,你就可以用PHP来发送电子邮件了.

mail()函数是非常简单的:只有五个参数,而其中的两个是可选的.这些参数是:

接收方地址

主题

信件内容

其它文件信息头(可选)

SMTP服务程序的其它配置选项(可选)

附加的头参数控制了诸如CC, BCC, Reply-To之类的邮件功能,或者其它遵循SMTP协议的功能.在这个例子中,我只使用From 和 Reply-To信息头.

如果你想给我发邮件但你使用的是一个非Windows系统, 程序代码就应该如下:

<?

$to = "julie@thickbook.com";

$subject = "ZDNet Developer article";

$msg = "I completely understand SMTP servers now!";

$headers = "From: me@mycompany.com\nReply-To:someoneelse@mycompany.com";

$config = "-fwebmaster@mycompany.com";

mail("$to", "$subject", "$msg", "$headers", "$config");

echo "finished!";

?>

如果你使用的是一个基于Windows的SMTP服务,那么你有可能不需要使用第五个参数,而且在附加的头信息参数中(也就是第四个参数),你需要将它们分开写--使用\r\n而不是\n.所以,同样的一个邮件通过基于Windows的SMTP服务发送的代码如下:

<?

$to = "julie@thickbook.com";

$subject = "ZDNet Developer article";

$msg = "I completely understand SMTP servers now!";

$headers = "From: me@mycompany.com\r\nReply-To:someoneelse@mycompany.com";

mail("$to", "$subject", "$msg", "$headers");

echo "finished!";

?>

脚本中的echo语句使你的Web浏览器在脚本运行完成的时候向你显示一条信息.如果不写echo语句,你就会得到一个"空文件"的对话框,因为没有任何输出能够发送到浏览器端.

只要能够连接到指定的SMTP服务器mail()函数就会返回真值.但是这并不意味着邮件成功的到达了接收方那里.mail()函数不会等待或报告SMTP服务器发来的成功/错误代码.

mail() 函数有可能返回假值,然后给你警告"无法连接,在第x行"或是"未知的错误,在第x行."如果这两条信息中的任何一条出现了,你就应该检查 php.ini中的SMTP值.引起这些消息有两种可能:SMTP服务器瘫痪了,或者PHP无法连接到它.无论是这两种情况中的哪一种,你的邮件都无法被 发送出去.

这个脚本对这些参数使用硬编码的值.使用一个简单的HTML表单,你就可以在这些参数中插入一些值并拥有一个良好的反馈表单.

一旦你知道了如何给一个人发送邮件,你可能按奈不住要把同一个邮件发送给许多接收者--就象新闻信件一样.所有这些牵涉到一个漂亮轻巧的循环来遍历一个接收者的列表并将邮件发送给他们.mail函数的形式还是相同的

网站应用中向客户发送邮件是常见的一个功能。SMTP协议貌似简单,而且资料繁多,但要彻底搞清楚客户端服务器之间的身份和关系处理,也不是件容易的事。

本文简明扼要对smtp交换过程中身份和条件进行说明,使初次接触smtp开发的能有个清晰的处理思路。错误之处请多指正。

作者:wdy,本文最初发布于 http://blog.csdn.net/aryang ,转载请注明出处。

先说说smtp的基本原理, 邮件客户端(outlook)和发送方smtp服务器之间,  发送方smtp服务器和接受方smtp服务器之间,走的都是smtp协议.

先说说我们最常见的情况:用outlook发邮件,从 jack@abc.com 发往 rose@xyz.com
outlook里写好邮件后发送,会连接到帐号里登记的smtp服务器25端口,开始smtp会话:

   mail from: <jack@abc.com>

   rcpt to:<rose@xyz.com>

abc.com服务器发现邮件的mail from 是本域的(abc.com),这种情况下smtp服务器一般需要验证用户身份,验证通过提交邮件,邮件进入服务器的发送队列。 服务器投递邮件的进程或线程,扫描发送队列,取出邮件后分析要往哪发。 服务器发现邮件是发往 xyz.com,不是本域,先通过dns服务器查询 xyz.com域的mx记录,假设为 smtp.xyz.com,邮件投递进程连接 smtp.xyz.com 的25端口,开始smtp会话

   mail from: <jack@abc.com>

   rcpt to:<rose@xyz.com>

xyz.com服务器判断邮件是来自别的域,发往本域,所以不需要验证用户。不过有可能的情况是xyz.com服务器先检查一下发信服务器的ip地址,和mail from 里的域名对应的mx记录是否匹配,不匹配的拒收。如果没有符合什么拒收条件,那么xyz.com手下这封信,放入rose的邮件夹,rose可以通过pop3收取邮件。

如果 abc.com发送邮件失败的话,邮件进入发送失败队列,可能直接扔掉,或者再试着重发n次,如果都不成功,会通知发件人或别的什么,这要看服务器的处理。

现在再说说php发邮件,首先要搞清楚,要用什么身份发送邮件。第一种:把自己当作outlook之类的客户端,先连到发信服务器,提交邮件后让发件服务器往外发送。第二种:把自己当作发信服务器,直接通过smtp连接收件人的服务器发送邮件。

这里我不推荐第二种方式,原因是:如果你php所在服务器的域名,ip,mx记录没有严格设置好的话,一般收件服务器有很大的几率会拒收;发送邮件本身的传输过程时间无法控制,如果和收件服务器有很大的延时,会严重影响自己的web服务器的工作,另外也不具有失败重发等处理。

对于发送邮件,windows和unix和很大的差别。windows一般来说都是像outlook那样的方式,用smtp协议连到发件服务器发送邮件。unix有自己的传统方式,就是unix主机自带 smtp server,传统的就是sendmail。另外还有个“sendmail”的概念,这里说的是一个程序的名字,无论是sendmail,qmail,postfix等等,都提供这个命令程序,通过它,可以把邮件放入本地邮件发送队列,让sendmail,qmail,postfix之类的投递程序去投递发送。sendmail程序一般是从标准输入里读入邮件内容。php的mail()函数实际上会打开sendmail程序,通过标准输入把邮件内容传给它,由sendmail程序来发送,剩下的就不管了。

所以大家可以看到,php里关于mail() 这个函数的说明,如果是在windows上,一般是设置 php.ini里 SMTP 和 smtp_port 选项的值,通过类outlook客户端的方式发送,但是这种方式的致命弱点是不支持smtp验证,而现在邮件服务器基本都是需要smtp验证的。uxni下一般需要设置 sendmail_path ,来说明sendmail程序的路径。当然windows上也可以用sendmail程序发送。

如果是unix,最理想的情况是,你的php所在的web服务器本身也是个smtp server,并设置好了mx记录等等,或者你有个能发送邮件的sendmail程序(自己写,封装smtp发送)那么先配置好 php.ini 里的sendmail_path,通过mail()函数就直接发送了。

如果没有能用的sendmail程序,那么就要通过socket 用smtp协议发送了,php这方面有很多扩展的库,可以直接拿来用。建议连上一个服务器让他帮你发,不建议直接连收件服务器(原因前面说了)。这里还有就是不建议直接在网页上php里连接发送,推荐的方式是把邮件写到数据库或文件里,让另一个程序(php,perl,python 都可以写)扫描后通过sokcet连接发送。这样既给用户有了好的响应体验,也可以控制发送的过程。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: