如果你会用socket来编写网络程序的话,那么下面这个东西应该不会很难(easy更为准确)。
你想拥有一个自己的电子邮件发送系统吗?If u want it, then do it.
一般我们只需关心客户端处的发送,服务器怎么样就不关我们的事了(sohu或者163可能不这么想问题
)。利用socket就可以很方便的来实现。
在用connect()成功连接对方服务器后,在客户机上要做的只是发送协议命令即可。这里简要说明一下SMTP的格式。我们用C代表clinet,S代表server。注:RFC协议下一般不区分参数的大小写。
1.SMTP client say 'hello' to SMTP server.
Format: HELO 发送方的主机名 <CRLF> //<CRLF> is '\r'+'\n'
eg:
C: HELO ZZZ // ZZZ is the hostname
S: 250 zzz Hello smtp.163.com,please to meet you
上面这条命令告诉SMTP server你想向他发邮件。250为同意的响应码,如果是550,表示server拒绝了你。
2.To tell the server where the client comes from.
Format: MAIL FROM: 发信人的电子邮件地址 <CRLF>
eg:
C: MAIL FROM: YY@163.com
S: 250 OK
client发送这条命令告知server发信人邮件地址。当投递失败server会根据这个地址退回错误邮件。如果返回250表示session将继续进行。550表示server不想deliver for u。553表示syntax error。
3.To tell where u want to deliver.
Format: RCPT TO: 收信人邮箱地址 <CRLF>
eg:
C: RCPT TO: lau_jia@operamail.com
S: 250<lau_jia@operamail.com>,Recipient ok
clinet发送对方email地址,服务器负责将随后client发送的信件送到这个地址。250表示成功接受命令,553表示邮件地址不合法。
4.Ask for sending the mail.
Format: DATA <CRLF>
eg:
C: DATA
S: 354 Start mail input;end with<CRLF>.<CRLF>
这 个命令比较特殊,只有命令,而没有参数。他告知服务器现在要准备发送邮件内容了。354表示server已经准备好了接收邮件数据,client可以发送 邮件了。并且响应中也提醒了client邮件要以<CRLF>.<CRLF>来结尾,表示邮件结束。如果邮件内容是一行开头一个 句号,那么server会误以为邮件结束。解决方法就是将一个句号写作两个句号相连,作为SMTP协议,会将两个句号自动删掉一个,恢复原来数据面貌。
接下去就可以发送数据了,在收到354后,client可以直接发送email的数据了,直到server收到<CRLF>.<CRLF>为止。这时server会发送一个一个是否成功的指示响应,一般为:
250 ok,message saved
如果响应为503,表示上面的1,2,3,4条命令顺序不对。
5.I wanna do nothing.
Format: NOOP <CRLF>
server收到这个命令什么也不做,仅以250 ok作答,这个可用来测试server与client之间的连接。
6.Is the email address legal.
Format: VRFY 电子邮箱地址 <CRLF>
eg:
C: VRFY ZHANG@263.COM
S: 550 Unknown address:<ZHANG>
or
252 Couldn't verify<ZHANG@263.COM>but will attempt delivery anyway
550表示邮箱的地址格式不合法或者无法发送,如果是252表示邮箱地址格式合法,但是不能确定该邮箱是否存在且有效,但是server愿意尝试发送。
7.Reset the SMTP server.
Format: RSET <CRLF>
这个用来复位链接状态。server收到这个命令后恢复到接收到HELO之前的状态,并以250 ok作答。
8.Ask for help info.
Format: HELP<CRLF>
or
HELP 命令关键字 <CRLF>
对于单纯的HELP命令,服务器返回可用命令的摘要列表,以及关于server的一般信息。关于带关键字的HELP命令,server给出详细帮助信息。
9.I quit.
Format: QUIT <CRLF>
eg:
C: QUIT
S: 221 smtp.163.com ESMTP server closing connection
server接收到后返回221,并关闭TCP连接。
下面给出SMTP常见的响应码:
221 系统状态或者系统帮助应答。
214 帮助信息。
220 服务就绪。
221 服务器关闭传输通道。
250 请求的邮件操作已经完成。
251 非本地用户,按照前向路径(forward-path)转发。
354 启动邮件输入,要求邮件以<CRLF>.<CRLF>结束。
421 服务不可用,关闭传输通道。
450 没有执行请求的邮箱操作,因为邮箱不可用。
451 处理过程出错,请求的操作中止。
452 系统存储空间不够,请求的操作没有发生。
500 语法错误,无法识别命令。
501 参数或者变元存在语法错误。
502 命令不能识别。
503 错误的命令序列。
504 命令的参数不能实现。
550 请求的操作不能发生,邮箱不可用。
551 用户不在本地,请尝试使用前向路径。
552 超出存储分配,请求的邮件操作中止。
553 请求的操作不能执行,因为信箱语法错误。
554 事务失败。
以上就是一般的响应,更多的可以参考RFC2821。
如果想把邮件写的正规一点(好像是FOXMAIL发的一样),可以在邮件内容前加上下面的内容。
From: XXX@xxx.com //表示是哪里发送的
To: XXX@xxx.com //表示要发给谁
Date: Fri,1 Dec 06 14:32:22 EST //表示发送日期
Subject: lunch with me //主题
正文。。。。。。。。。。。。。
如果想抄送等可以加上下面的关键字段(只给出常用的)
Reply-To: xxx@xxx.com //表示这是一封回信
Cc: xxx@xxx.com //抄送
Bcc: xxx@xx.com //密抄送
注意这些头信息中From和Date字段对于标准的服务器是必须要有的,To,Cc,Bcc必须要有一个,其它可选。
通过上述介绍可以发现SMTP有其局限性,于是扩展出了MIME来支持多媒体,不过这个有点复杂了,有兴趣的人可以参考文后的文献。
目前大多数的邮件服务器都支持POP3的服务,这是一种和SMTP类似的协议方式,但是更简单。看下面一个实际的POP3回话例子:
(Connect to the pop3 server...)
S:+OK POP3 server ready //服务器已经准备就绪
C:USER Wang //用户名是Wang
S:+OK
C: PASS table //密码是table
S:+OK login successful //登陆成功
C:LIST //列出邮件清单
S:1 AAAA //第一封信
S:2 BBBB
S:3 CCCC
C:RETR 1 //取回第一封信
S:+OK(send message 1)
C: DELE 1 //删除第一封信
S:+OK
C:RETR 2
S:+OK(send message 2)
C: DELE 2
S:+OK
C:QUIT //退出回话
S:+OK POP3 server disconnecting //POP3断开连接
可以看到应答要比SMTP要简单的多,只有两个应答"+OK"表示成功,"-ERR"表示失败。
下面介绍一些常用命令:
1.USER
Format: USER 用户名 <CRLF>
eg:
C: USER
S: -ERR missing user name argument
C: USER Liu
S: +OK
这个命令用来登陆邮箱时输入用户名。
2.PASS
Format: PASS 口令 <CRLF>
有时在发送完login信息后还是无法登陆,这是因为已经有一个进程登陆了该邮箱,POP3只能独占邮箱访问权,这时如果还要登陆,不能简单的只发送PASS命令,还要重发USER命令。
3.QUIT
中止会话。POP3服务器更新邮箱状态,删除有删除标记(DELE来标记)的邮件,并释放邮箱进程。
4.NOOP
这个命令do nothing,可以用来检测连接。
5.STAT
请求返回邮件数量和邮箱大小,但是不包括已做删除标记的邮件。
eg:
C: STAT
S: +OK 5 9086
6.LIST
Format 1:LIST<CRLF>
这个用来返回所有邮件的信息(序号和大小)。
eg:
C: LIST
S: +OK
1 2090
2 4080
...
...
Format 2:LIST 邮件序号<CRLF>
返回指定序号邮件的信息。如果该邮件已被标记了删除或者不存在,则返回出错信息。
7.RETR
Format: RETR 邮件序号 <CRLF>
用来取回序号指定的邮件。应答为多行应答,包括信头和信体,如果有附件,附件以文本形式返回。最后以和SMTP一样的格式表示中止。
eg:
C: RETR 1
S: +OK 13100 octets
Received:...
Data:...
From:...
...
...
...<CRLF>
.
<CRLF>
8.TOP
Format: TOP 邮件序号 行数 <CRLF>
取回指定邮件的邮件头和指定信体行数。如果行数为0或不指定,则返回头信息和空白行。注意有些POP3并没实现该命令。
9.DELE
Format: DELE 邮件序号 <CRLF>
该命令不会真正删除邮件,而只是加了一个删除标记,只有在正常更新邮箱后才会真正删除。一般为用QUIT命令退出后更新邮箱。
10.REST
复位邮箱,原来被标记删除的全部取消删除标记。
11.UIDL
Format: UIDL 邮件序号 <CRLF>
这个命令返回每封信的唯一标示号,一般只以简单的1,2,3来表示邮件会容易混淆,这个可以帮助client来准确的定位邮件。
参考文献:
网络编程实用教程第10章, 叶树华,高志红 编著,人民邮电出版社
你想拥有一个自己的电子邮件发送系统吗?If u want it, then do it.

一般我们只需关心客户端处的发送,服务器怎么样就不关我们的事了(sohu或者163可能不这么想问题

在用connect()成功连接对方服务器后,在客户机上要做的只是发送协议命令即可。这里简要说明一下SMTP的格式。我们用C代表clinet,S代表server。注:RFC协议下一般不区分参数的大小写。
1.SMTP client say 'hello' to SMTP server.
Format: HELO 发送方的主机名 <CRLF> //<CRLF> is '\r'+'\n'
eg:
C: HELO ZZZ // ZZZ is the hostname
S: 250 zzz Hello smtp.163.com,please to meet you
上面这条命令告诉SMTP server你想向他发邮件。250为同意的响应码,如果是550,表示server拒绝了你。
2.To tell the server where the client comes from.
Format: MAIL FROM: 发信人的电子邮件地址 <CRLF>
eg:
C: MAIL FROM: YY@163.com
S: 250 OK
client发送这条命令告知server发信人邮件地址。当投递失败server会根据这个地址退回错误邮件。如果返回250表示session将继续进行。550表示server不想deliver for u。553表示syntax error。
3.To tell where u want to deliver.
Format: RCPT TO: 收信人邮箱地址 <CRLF>
eg:
C: RCPT TO: lau_jia@operamail.com
S: 250<lau_jia@operamail.com>,Recipient ok
clinet发送对方email地址,服务器负责将随后client发送的信件送到这个地址。250表示成功接受命令,553表示邮件地址不合法。
4.Ask for sending the mail.
Format: DATA <CRLF>
eg:
C: DATA
S: 354 Start mail input;end with<CRLF>.<CRLF>
这 个命令比较特殊,只有命令,而没有参数。他告知服务器现在要准备发送邮件内容了。354表示server已经准备好了接收邮件数据,client可以发送 邮件了。并且响应中也提醒了client邮件要以<CRLF>.<CRLF>来结尾,表示邮件结束。如果邮件内容是一行开头一个 句号,那么server会误以为邮件结束。解决方法就是将一个句号写作两个句号相连,作为SMTP协议,会将两个句号自动删掉一个,恢复原来数据面貌。
接下去就可以发送数据了,在收到354后,client可以直接发送email的数据了,直到server收到<CRLF>.<CRLF>为止。这时server会发送一个一个是否成功的指示响应,一般为:
250 ok,message saved
如果响应为503,表示上面的1,2,3,4条命令顺序不对。
5.I wanna do nothing.
Format: NOOP <CRLF>
server收到这个命令什么也不做,仅以250 ok作答,这个可用来测试server与client之间的连接。
6.Is the email address legal.
Format: VRFY 电子邮箱地址 <CRLF>
eg:
C: VRFY ZHANG@263.COM
S: 550 Unknown address:<ZHANG>
or
252 Couldn't verify<ZHANG@263.COM>but will attempt delivery anyway
550表示邮箱的地址格式不合法或者无法发送,如果是252表示邮箱地址格式合法,但是不能确定该邮箱是否存在且有效,但是server愿意尝试发送。
7.Reset the SMTP server.
Format: RSET <CRLF>
这个用来复位链接状态。server收到这个命令后恢复到接收到HELO之前的状态,并以250 ok作答。
8.Ask for help info.
Format: HELP<CRLF>
or
HELP 命令关键字 <CRLF>
对于单纯的HELP命令,服务器返回可用命令的摘要列表,以及关于server的一般信息。关于带关键字的HELP命令,server给出详细帮助信息。
9.I quit.
Format: QUIT <CRLF>
eg:
C: QUIT
S: 221 smtp.163.com ESMTP server closing connection
server接收到后返回221,并关闭TCP连接。
下面给出SMTP常见的响应码:
221 系统状态或者系统帮助应答。
214 帮助信息。
220 服务就绪。
221 服务器关闭传输通道。
250 请求的邮件操作已经完成。
251 非本地用户,按照前向路径(forward-path)转发。
354 启动邮件输入,要求邮件以<CRLF>.<CRLF>结束。
421 服务不可用,关闭传输通道。
450 没有执行请求的邮箱操作,因为邮箱不可用。
451 处理过程出错,请求的操作中止。
452 系统存储空间不够,请求的操作没有发生。
500 语法错误,无法识别命令。
501 参数或者变元存在语法错误。
502 命令不能识别。
503 错误的命令序列。
504 命令的参数不能实现。
550 请求的操作不能发生,邮箱不可用。
551 用户不在本地,请尝试使用前向路径。
552 超出存储分配,请求的邮件操作中止。
553 请求的操作不能执行,因为信箱语法错误。
554 事务失败。
以上就是一般的响应,更多的可以参考RFC2821。
如果想把邮件写的正规一点(好像是FOXMAIL发的一样),可以在邮件内容前加上下面的内容。
From: XXX@xxx.com //表示是哪里发送的
To: XXX@xxx.com //表示要发给谁
Date: Fri,1 Dec 06 14:32:22 EST //表示发送日期
Subject: lunch with me //主题
正文。。。。。。。。。。。。。
如果想抄送等可以加上下面的关键字段(只给出常用的)
Reply-To: xxx@xxx.com //表示这是一封回信
Cc: xxx@xxx.com //抄送
Bcc: xxx@xx.com //密抄送
注意这些头信息中From和Date字段对于标准的服务器是必须要有的,To,Cc,Bcc必须要有一个,其它可选。
通过上述介绍可以发现SMTP有其局限性,于是扩展出了MIME来支持多媒体,不过这个有点复杂了,有兴趣的人可以参考文后的文献。
目前大多数的邮件服务器都支持POP3的服务,这是一种和SMTP类似的协议方式,但是更简单。看下面一个实际的POP3回话例子:
(Connect to the pop3 server...)
S:+OK POP3 server ready //服务器已经准备就绪
C:USER Wang //用户名是Wang
S:+OK
C: PASS table //密码是table
S:+OK login successful //登陆成功
C:LIST //列出邮件清单
S:1 AAAA //第一封信
S:2 BBBB
S:3 CCCC
C:RETR 1 //取回第一封信
S:+OK(send message 1)
C: DELE 1 //删除第一封信
S:+OK
C:RETR 2
S:+OK(send message 2)
C: DELE 2
S:+OK
C:QUIT //退出回话
S:+OK POP3 server disconnecting //POP3断开连接
可以看到应答要比SMTP要简单的多,只有两个应答"+OK"表示成功,"-ERR"表示失败。
下面介绍一些常用命令:
1.USER
Format: USER 用户名 <CRLF>
eg:
C: USER
S: -ERR missing user name argument
C: USER Liu
S: +OK
这个命令用来登陆邮箱时输入用户名。
2.PASS
Format: PASS 口令 <CRLF>
有时在发送完login信息后还是无法登陆,这是因为已经有一个进程登陆了该邮箱,POP3只能独占邮箱访问权,这时如果还要登陆,不能简单的只发送PASS命令,还要重发USER命令。
3.QUIT
中止会话。POP3服务器更新邮箱状态,删除有删除标记(DELE来标记)的邮件,并释放邮箱进程。
4.NOOP
这个命令do nothing,可以用来检测连接。
5.STAT
请求返回邮件数量和邮箱大小,但是不包括已做删除标记的邮件。
eg:
C: STAT
S: +OK 5 9086
6.LIST
Format 1:LIST<CRLF>
这个用来返回所有邮件的信息(序号和大小)。
eg:
C: LIST
S: +OK
1 2090
2 4080
...
...
Format 2:LIST 邮件序号<CRLF>
返回指定序号邮件的信息。如果该邮件已被标记了删除或者不存在,则返回出错信息。
7.RETR
Format: RETR 邮件序号 <CRLF>
用来取回序号指定的邮件。应答为多行应答,包括信头和信体,如果有附件,附件以文本形式返回。最后以和SMTP一样的格式表示中止。
eg:
C: RETR 1
S: +OK 13100 octets
Received:...
Data:...
From:...
...
...
...<CRLF>
.
<CRLF>
8.TOP
Format: TOP 邮件序号 行数 <CRLF>
取回指定邮件的邮件头和指定信体行数。如果行数为0或不指定,则返回头信息和空白行。注意有些POP3并没实现该命令。
9.DELE
Format: DELE 邮件序号 <CRLF>
该命令不会真正删除邮件,而只是加了一个删除标记,只有在正常更新邮箱后才会真正删除。一般为用QUIT命令退出后更新邮箱。
10.REST
复位邮箱,原来被标记删除的全部取消删除标记。
11.UIDL
Format: UIDL 邮件序号 <CRLF>
这个命令返回每封信的唯一标示号,一般只以简单的1,2,3来表示邮件会容易混淆,这个可以帮助client来准确的定位邮件。
参考文献:
网络编程实用教程第10章, 叶树华,高志红 编著,人民邮电出版社