在php中发送邮件可以用自带的mail()函数,但是这个函数不足点很明显,最主要是咱本机上没有安装smtp服务就没法使用mail()。
当然现在还有php其他的插件、类什么的,那些也许功能齐全,可是外加就感觉不爽。
那其他办法的话,一般会想到通过SMTP服务器来发送邮件,但是也会产生一系列问题(具体有哪些问题可见参考资料"无须SMTP服务器中转直接发送电子邮件")。对于目前我的需求来说,只需要发送邮件,并不需要接受功能,所以想到如果发邮件要绑定某个邮箱,就感到非常不爽,所以最终还是决定用smtp协议直接发送邮件,这样也省了用户验证这个步骤,可以随时随地发邮件。
方法很简单,如下:
一、找到目标邮箱的SMTP服务器的IP 地址
只要向域名服务器发送查询“163.com”等的目标邮箱服务器地址,便可找到目标邮箱SMTP服务器的IP 地址,该查询指令被称作MX(Mail Exchange)邮件交换服务器的地址查询。
方法1:获取本机DNS,然后与DNS服务器通信实现MX指令查询。(可见参考资料"无须SMTP服务器中转直接发送电子邮件")
方法2:利用windows自带的nslookup工具,可以轻松实现MX查询。
方法3(推荐):用nslookup工具固然方便,但是毕竟要执行外部程序,有点不爽,现在php5.3提供了更加方便的命令,应该就是从nslookup上扩展出来的,getmxrr($hostname,$hosts)只需要提供远程邮局服务器地址,就可以轻松得到所有的该服务器域名了,说明信息见“http://cn.php.net/manual/en/function.getmxrr.php”,里面还能看到nslookup在php中的应用,对于php5.3以下配置的也可以参考这里,非常实用。
二、用socket_create和socket_connect连接目标邮箱服务器, SMTP端口一般为25.
要使用socket,首先要确保php.ini中的extension=php_sockets.dll扩展打开,看phpInfo()显示的内容里,socket模块是否为enable。
注,网上有很多人用fsockopen(), 咱没试过,不好比较
三、SMTP邮件提交
SMTP协议参考[RFC821], 最基本的命令如下:
--------------------------------------------------------------------------
HELO 目标邮箱服务器域名 *这个目前不清楚有什么作用,乱写或者不写好像都没什么关系
MAIL FROM: <发送者邮箱地址> *初始化邮件传输,对于直接用协议发邮件的,可以不写,也可以自定义,只要是有效邮箱地址即可
RCPT TO: <目标邮箱地址> *标识单个的邮件接收人;常在MAIL命令后面, 可有多个rcpt to:
DATA *在单个或多个RCPT命令后,表示所有的邮件接收人已标识,并初始化数据传输,以"."结束。
......邮件内容......
QUIT *结束会话
邮件内容基本格式:
---------------------------------------------------------------------------
From: *这里不一定要和发送者邮箱地址一致,可以随便,只控制邮件显示而已
To: *同上
Subject: 标题 *到此为止邮件头部基本设定完毕,如果后面要开始邮件正文,一定要记得这行后面加两个回车键
以上每条命令都要以回车键("/r/n”)结束
每条命令用socket_write进行提交,socket_read读取服务器应答信息,socket_strerror读取错误信息
四、如果要给邮件添加附件或图片等非文本信息的时候,就要用到MIME,这个相对比较复杂,这里不多说,规则请参看[RFC2046]。
参考资料:
在PHP中发送MIME邮件:http://tech.ccidnet.com/art/1110/20040121/848443_1.html
邮件原文详细介绍--神奇的MIME:http://hi.baidu.com/ourstyle/blog/item/17a0b7dd3ffb9f315882dd2c.html
电子邮件的结构:http://fuzhong1983.blog.163.com/blog/static/1684705200931521341504/
RFC821 简单邮件传输协议(SMTP): http://www.cnpaf.net/rfc/rfc821.txt
RFC2046 MIME:http://www.cnpaf.net/rfc/rfc2046.txt
无须SMTP服务器中转直接发送电子邮件:http://tech.ddvip.com/2009-01/1232502707106615.html
使用SMTP协议发送邮件:http://www.winu.cn/htmls/177/071/?PHPSESSID=a7d3234d549a7c86ec6b340ee2d2fb56
通过SOCKET发送邮件:http://www.alixixi.com/program/a/2008050731579.shtml
SMTP结构及原理: http://blog.antbiz.net/post/19.html
VC++ SMTP协议电子邮件传送剖析: http://www.yesky.com/191/1640691_1.shtml
不知道是不是hotmail不支持smtp协议,还是其他原因,发hotmail邮件时,日志显示发送成功的“250 Mail queued for delivery.”,可是hotmail就是收不到邮件。
不过在连接hotmail服务器时有一条日志值得注意“220 col0-mc4-f17.Col0.hotmail.com Sending unsolicited commercial or bulk e-mail to Microsoft's computer network is prohibited. Other restrictions are found at http://privacy.msn.com/Anti-spam/. Violations will result in use of equipment located in California and other states. Mon, 19 Apr 2010 17:44:02 -0700”,分析产生这个问题大概原因是,hotmail的反解析不到邮件发出地址,然后就直接不接受邮件,不像其他邮件服务器把邮件放入垃圾箱,可恶的是它竟然不给出失败的消息,反而显示成功。
网上查说解决这个问题的方法是去做反解和spf,这个对现阶段没什么意义,所以发hotmail邮件以及邮件被放入垃圾箱等问题等以后再研究了。
该方面预留参考资料:
邮件发送hotmail问题:http://qwqg.mobibal.com/?p=1427
通过JavaMail访问Hotmail邮箱: http://studyroom.ccut.edu.cn/print.php?/8630
接收发送邮件其他方法参考资料:
PHP SMTP Class: http://www.tellinya.com/read/2008/03/18/326.html
PHP中发送邮件的几种方法总结: http://www.webjx.com/htmldata/2005-09-08/1126134755.html
在php中用socket发送电子邮件_邮件服务器: http://www.west263.com/www/info/66736-1.htm
PHP的Jmai组件及发送邮件实例代码:http://www.westphp.com/bbs/archiver/tid-1073.html
设置xampp的mail服务:http://www.swordair.com/blog/?p=88
用sendmail.exe成功在本机apache+php用mail()函数发送邮件成功: http://blog.youkuaiyun.com/kunga0814/archive/2009/12/10/4979621.aspx
DOS命令发邮件:http://apps.hi.baidu.com/share/detail/2135937
(注:用dos命令发邮件其本质也就是连接邮件服务器用smtp协议发邮件)
其他参考资料
中文RFC文档_协议分析网: http://www.cnpaf.net/class/RFC/
企业邮箱拒信常规问题对照表:http://www.net.cn/service/faq/youx/mailsy/200905/3781.html