在php中使用SMTP通过密抄批量发送邮件续:修正

前不久我写过的一篇关于用socket发送邮件的随笔---在php中使用SMTP通过密抄批量发送邮件,算是对那几天工作的小结。但是,通过这几天的使用,的确发现了一些问题。

首先,如果没有记错的话,以前我有提到我们公司的服务器是放在美国的,跑的是linux。但是,我在本地测试的时候,为了图个速度快,实际上,测试各项功能时,我使用了126的邮箱进行发送的。实际上,马上就证实了这个是我的疏忽。投入使用后,突然发现问题大条了。原来使用密抄的目的,是为了让各收件人间无法知道邮件还发给了谁,但是通过那台服务器发送的邮件,密抄地址居然全部列在上面,以至于有个收件的客户回了一封信给我们“Please send emails to mass recipients as bc (blind copy) so everyone doesn't have all email addresses.”

 

但是,我们的确是使用了密抄的啊,不能啊。但是,我在服务器上发给了自己,的确如此。

 

========================我是证据==============================

查看收到的邮件的头信息,也包含了本不应存在的bcc信息

 

可以我在本地测试,结果还是可以。那就神奇了,一样的代码,但是结果不一样。试了好几次,发现只要是使用qq、126之类的服务器来发送邮件,就不会显示。于是,就考虑是不是由于服务器上邮件发送程序不一样引起的或者是我的构造的信件格式有问题。于是,我用foxmail发送了一封到美国的服务器,结果他可以。看来是我的标头不规范了,qq、126能识别,美国佬的不行。

 

那知道了就改吧。通过抓包软件,可以得到一份完整的通讯记录,如下:

220 126.com Anti-spam GT for Coremail System (126com[20101010])

EHLO xin478-PC

250-mail
250-PIPELINING
250-AUTH LOGIN PLAIN
250-AUTH=LOGIN PLAIN
250-coremail 1Uxr2xKj7kG0xkI17xGrU7I0s8FY2U3Uj8Cz28x1UUUUU7Ic2I0Y2UrGJqy-UCa0xDrUUUUj250 8BITMIME


AUTH LOGIN

334 xxxxxxx

eGHuNDc7

334 xxxxxxxxxx


ODU1NzE2

235 Authentication successful

MAIL FROM: <xxxxxx@126.com>

250 Mail OK

RCPT TO: <noreply@xxxxx.com>

250 Mail OK


RCPT TO: <44522303@qq.com>

250 Mail OK

RCPT TO: <noreply@yoberryks.com>

250 Mail OK

RCPT TO: <44522303@qq.com>

250 Mail OK


Data

354 End data with <CR><LF>.<CR><LF>


Date: Mon, 25 Oct 2010 16:32:49 +0800
From: "xin478" <xin478@126.com>
To: "noreply" <noreply@xxxxx.com>
Cc: "44522303" <44522303@qq.com>
Subject: this is topic
Message-ID: <201010251632482022640@126.com>
X-mailer: Foxmail 6, 15, 201, 22 [cn]
Mime-Version: 1.0
Content-Type: multipart/alternative;
          boundary="=====003_Dragon220658716328_====="


This is a multi-part message in MIME format.

 

--=====003_Dragon220658716328_=====
Content-Type: text/plain;
charset="gb2312"
Content-Transfer-Encoding: 7bit

this is content

--=====003_Dragon220658716328_=====
Content-Type: text/html;
charset="gb2312"
Content-Transfer-Encoding: base64

PCFET0NUWVBFIEhUTUwgUFVCTElDICItLy9XM0MvL0RURCBIVE1MIDQuMCBUcmFuc2l0aW9uYWwv
L0VOIj4NCjxIVE1MPjxIRUFEPg0KPFNUWUxFIHR5cGU9dGV4dC9jc3M+QGltcG9ydCB1cmwoIEU6
XFRlbXBcSW50ZXJuZXQgwdnKsc7EvP5cc2Nyb2xsYmFyLmNzcyApOw0KPC9TVFlMRT4NCg0KPFNU
WUxFIHR5cGU9dGV4dC9jc3M+QGltcG9ydCB1cmwoIEU6XFRlbXBcSW50ZXJuZXQgwdnKsc7EvP5c
c2Nyb2xsYmFyLmNzcyApOw0KPC9TVFlMRT4NCg0KPFNUWUxFIHR5cGU9dGV4dC9jc3M+QGltcG9y
dCB1cmwoIEU6XFRlbXBcSW50ZXJuZXQgwdnKsc7EvP5cc2Nyb2xsYmFyLmNzcyApOw0KPC9TVFlM
RT4NCg0KPFNUWUxFIHR5cGU9dGV4dC9jc3M+QGltcG9ydCB1cmwoIEU6XFRlbXBcSW50ZXJuZXQg
wdnKsc7EvP5cc2Nyb2xsYmFyLmNzcyApOw0KPC9TVFlMRT4NCg0KPFNUWUxFIHR5cGU9dGV4dC9j
c3M+QGltcG9ydCB1cmwoIEU6XFRlbXBcSW50ZXJuZXQgwdnKsc7EvP5cc2Nyb2xsYmFyLmNzcyAp
Ow0KPC9TVFlMRT4NCg0KPE1FVEEgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PUdCMjMxMiIg
aHR0cC1lcXVpdj1Db250ZW50LVR5cGU+DQo8TUVUQSBuYW1lPUdFTkVSQVRPUiBjb250ZW50PSJN
U0hUTUwgOS4wMC43OTMwLjE2NDA2Ij48TElOSyByZWw9c3R5bGVzaGVldCANCmhyZWY9IkJMT0NL
UVVPVEV7bWFyZ2luLVRvcDogMHB4OyBtYXJnaW4tQm90dG9tOiAwcHg7IG1hcmdpbi1MZWZ0OiAy
ZW19Ij48L0hFQUQ+DQo8Qk9EWSBzdHlsZT0iTUFSR0lOOiAxMHB4OyBGT05ULUZBTUlMWTogdmVy
ZGFuYTsgRk9OVC1TSVpFOiAxMHB0Ij4NCjxESVY+PEZPTlQgc2l6ZT
0yIGZhY2U9VmVyZGFuYT50
aGlzIGlzIGNvbnRlbnQ8L0ZPTlQ+PC9ESVY+PC9CT0RZPjwvSFRNTD4NCg==

--=====003_Dragon220658716328_=====--


.

250 Mail OK queued as smtp1,C8mowKDLuQOxQMVMWetQAA--.41003S2 1287995571


QUIT

221 Bye

 

于是,大体是就明了了,基本上流程是这样的

一、建立TCP连接。
二、客户端发送HELO命令以标识发件人自己的身份,然后客户端发送MAIL命令服务器端正希望以OK作为响应,表明准备接收。
三、客户端发送RCPT命令,以标识该电子邮件的计划接收人,可以有多个RCPT行
四、协商结束,发送邮件,用命令DATA发送
五、以.表示结束输入内容一起发送出去
六、用QUIT命令退出结束此次发送。

 

而对于SMTP的命令而言,大抵用到的有这几种

  • HELO   向服务器标识用户身份
  • MAIL   初始化邮件传输mail from: <xxx>
  • RCPT   标识单个的邮件接收人;常在MAIL命令后面可有多个rcpt to: <xxx>
  • DATA   在单个或多个RCPT命令后,表示所有的邮件接收人已标识,初始化数据传输,以.结束
  • NOOP   无操作,服务器应响应OK
  • RSET   重置会话,当前传输被取消
  • QUIT   结束会话

我们可以观察到,在整个通讯的过程中,标头中并没有出现BCC的关键字,只是把邮件接收者都用RCPT TO按顺序都送出去了,我一直以为这个BCC是要的,而且为了区别,这封邮件我也抄送了一份(注意是抄送而不是密送),这个抄送的地址赫然在目 Cc: "44522303" <44522303@qq.com>

所以,我推测这个BCC是不用写的,不在To里面的和不在CC里面的,就是BCC,于是,我去掉了代码里输出BCC到标头这个行,重新发送了一次,的确,就可以了,不会显示密抄名单了。

 

但是,随即又发现一个新的问题,就是在收件人那栏里,使用密抄的话,不会显示当前收件人,而是会显示用MAIL TO 送出去的那个地址。在规范里,MAIL TO,CC,BCC三者只要有其中一个就可以了,于是,我又去掉了原来TO,这下,再发的时候,就看不到错误的收件人了。

 

这封是密抄给noreply@xx.com的邮件,但是在noreplay的账户里区看到了收件人为xin478@126.com

修改后,这个收件人就不会显示了

 

估计,使用密抄的话,这个收件人的问题没有什么好的办法了。如果有好解决方法的兄弟,告知我一声。

 

修改后的代码,请移步到前文 在php中使用SMTP通过密抄批量发送邮件,我更新在那边了。

posted @ 2010-10-25 17:02  xin478  阅读(1014)  评论(0编辑  收藏  举报