火星文 技术研习社

Noname Cat, Keep Thinking
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

SMTP 实验备忘

Posted on 2006-07-01 19:20  剑廿三  阅读(969)  评论(0编辑  收藏  举报

一. 登入验证

smtp.126.com 需要 身份验证

使用以下指令:
AUTH LOGIN
username
password

其中,username 和 password 是邮箱帐户的用户名和密码,发送前需要进行 base64 编码
且以上指令必须在 HELO 之后执行,执行完AUTH LOGIN 才能执行 MAIL FROM
否则会报命令顺序错误。

Java 的 base64 编码方法是:

String user = (new sun.misc.BASE64Encoder()).encode("myusername".getBytes());
String password = (new sun.misc.BASE64Encoder()).encode("mypassword".getBytes());
   
解码方法是把 Encoder 改为 Decoder

验证通过后服务器会返回以下消息:

235 Authentication successful

二. 发送邮件指令

《Java 网络程序设计》(清华大学出版社)一书的例子是用 BufferedWriter 来做 outData 的:

this.outData = new BufferedWriter(new OutputStreamWriter(cs.getOutputStream()));

这种方式需要使用 this.outData.write(command.charAt(i)); 来按字节(Byte)发送信息。
其中 command 是一个 String 字符串。

事实上可以使用 PrintWriter 来做 outData:

this.outData = new PrintWriter(cs.getOutputStream());

这种方式的发送信息只需要这样就可以了:

this.outData.println(command);
        
if
(isFlush){
    
this
.outData.flush();
}

如果要在这部分向控制台输出调试信息,应把输出的方法体写在 flush() 后。如果写在 if(isFlush) 之后,即还没有 flush 就向控制台产生输出的话,会使邮件服务器返回“无法从客户端获得邮件数据”的消息。

三. 发送邮件正文

邮件正文一定要一次过 flush,邮件正文包含下列信息:

Date:
From:
To:
Subject:

here is content

其中,每行的结尾要以 \r\n 分隔。也可以先发送到 outData,在正文结束前的所有行都不要 flush,最后才 flush。

正式的正文,如上文的“here is content”,与 Subject 之类的标记行之间,要有至少一个空行。这样才会被其他邮件客户端认为这部分是邮件正文。

如果消息格式成功,这时服务器会返回

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

这时候 flush 一个“.”字符串过去,就会收到像这样的回复:

250 Mail OK queued as smtp3,wKjSjROAixpUZKZEytWjAg==.31009S2

最后发送一个“QUIT”,正确应该收到这样的回复:

221 Bye

四. 完整一次 SMTP 的 log 记录:

HELO smtp.126.com
220 126.com Coremail SMTP(Anti Spam) System
AUTH LOGIN
250 OK
abcdefg==
334 dXNlcm5hbWU6
zxcvbbnmddd
334 UGFzc3dvcmQ6
MAIL FROM: <
abcd@126.com>
235 Authentication successful
RCPT TO: <
zxcvb@126.com>
250 Mail OK
DATA
250 Mail OK
Subject: apple smtp
 this is an apple. thank you  all the same!

354 End data with <CR><LF>.<CR><LF>
.
250 Mail OK queued as smtp3,wKjSjROAixpUZKZEytWjAg==.31009S2
QUIT
221 Bye

更专业的描述:

SMTP:简单邮件传送协议

  1、SMTP协议:

  用TCP进行的邮件交换是由报文传送代理MTA(Message Transfer Agent)完成的。两个MTA之间用NVT ASCII进行通信,客户向服务器发出命令,服务器用数字应答码和可选的字符串进行响应。
  常见的SMTP命令,其中只有5个SMTP命令用于发送邮件:HELLO、MAIL、RCTP、DATA和QUIT。
  HELO:标识自己
  MAIL:启动用户代理
  RCPT:标识接收方
  DATA:邮件报文内容
  QUIT:退出
  RSET:异常中止当前的邮件事务并使两端复位
  VRFY:使客户能够询问发送方以验证接收方地址,而无需向接收方发送邮件。
  NOOP:强迫服务器响应一个OK应答码,不做任何事。

  2、信封、首部和正文

  (1) 信封:由MTA用来交付。
  MAIL From:xiaoj@njb.swirebev.com
  RCPT To:xiaoj@hotmail.com
  (2) 首部:由用户代理使用。共有9个字段:Received、Message_Id、From、Data、Reply-To、X-Phone、X-Mailer、To、Subject。每个首部字段都包含一个名、紧跟一个冒号,接着是字段值
  (3)正文:是发送给接收用户报文的内容。当用DATA命令发送时,先发送首部,紧跟一个空行,然后是正文。用DATA发送的各行都必须小于1000字节

  用户接收正文部分,加上一些首部字段,并把结果传给MTA。MTA加上一些首部字段,加上信封,并把结果发给另以MTA。所有这一些都以NVT ASCII格式发送。

  3、扩充的SMTP

  要使用ESMTP,首先通过EHLO命令而不是HELO命令启动与服务器的会话。它会显示扩充命令:EXPN、SIZE、HELP、8BITMIME、XADR等。SIZE命令是让客户在MAIL FROM命令中以字节的多少指定报文的大小,这样服务器可以在客户开始发送报文之前验证它是否接收该长度的报文。8BITMIME允许客户把关键字BODY加到MAIL FROM命令中,指定正文中是否包含NVT ASCII(默认)或8位数据。除非客户收到服务器响应EHLO命令发来的8BITMIME关键字,否则禁止客户发送任何非NVT ASCII字符。

  (1) 首部变化:非ASCII字符

  用途主要是为了允许发送方名、接收方名以及主题中使用其他的字符
  首部字段中可以包含编码字(coded word),其格式如下:

  =?charset?encoding?encoded-text?=

  charset表示字符集,有效值时us-ascii和iso-8859-x。
  encoding是一个单个字符用来指定编码方法,支持2个值:
  ◆ Q:意思是引号中可打印的,目的是用于拉丁字符集。大多数字符作为NVT ASCII发送的。任何要发送的字符若第8位是1则被作为3个字符发送,第一个字符是"=",跟着两个16进制数,如0xe9,则发送3个字符"=E9",空格通常作为下划线或三个字符"=20"发送。
  ◆ B:意思是以64为基数的编码。文本中的3个连续字节(24位)被编码为4个6位值,用于表示所有可能的6位值的64个NVT ASCII字符。当要编码的个数不是3的倍数时,等号被用作填充符。

  (2) 正文变化:通用Internet邮件扩充可以把结构置入正文,这就是MIME,即通用Internet扩充。MIME不要求任何扩充,但加入了一些告知收件者正文结构的新标题,正文仍然可以用NVT ASCII发送,而不考虑邮件内容。MIME定义5个新标题:
  Mime-version:当前版本是1.0
  Content-Tyoe:内容类型是无格式ASCII文本,即Internet邮件的默认选择。可以为:  text,multipart,message,application,image,audio,video。
  Content-Transfer-Encoding:内容传送编码有5中:7bit(即NVT ASCII ),quoted-printable,base64,8bit,binary。
  Content-ID:
  Content-Description: