学习socket编程之一:用smtp协议发送邮件
写这篇文章的目的是做为我学习socket编程的记录,本身已经没有什么技术含量了,这篇文章的内容基本上全部是参考网上的资料而写出来的,在这里首先感谢研究并写出这些技术文章的同仁。如果你已经了解了这些技术也望多多交流分享啊。我就开始捣鼓了。
以前做的所有项目中,当需要用到发送邮件功能的时候,我的第一个念头就是使用jmail组件。也因为这样自己一直也没有深入研究过smtp协议是怎样工作的。最近的工作中刚好又要发送邮件功能,且不能在服务器上安装第三方组件,恰好自己又开始对socket编程产生兴趣。就想着用socket来实现。
想好了就开始做,首先使用google搜索,可以找出一大堆的关于smtp协议的资料,推荐一个好的网站给大家——中国协议网(http://www.cnpaf.net/),上面有各种协议的介绍和RFC文档。
.SMTP基本命令集:
命令 描述
------------------------------
HELO 向服务器标识用户身份
发送者能欺骗,说谎,但一般情况下服务器都能检测到。
MAIL 初始化邮件传输
mail from:
RCPT 标识单个的邮件接收人;常在MAIL命令后面
可有多个rcpt to:
DATA 在单个或多个RCPT命令后,表示所有的邮件接收人已标识,并初始化数据传输,以.结束。
VRFY 用于验证指定的用户/邮箱是否存在;由于安全方面的原因,服务器常禁止此命令
EXPN 验证给定的邮箱列表是否存在,扩充邮箱列表,也常被禁用
HELP 查询服务器支持什么命令
NOOP 无操作,服务器应响应OK
QUIT 结束会话
RSET 重置会话,当前传输被取消
如果你的机器上安装了IIS的话,你可以在windows命令窗口输入
telnet localhost 25
helo localhost
mail from: jimyhsu@163.com
rcpt to: jimyhsu@163.com
...
来测试smtp发信了。
呵呵,大概了解了smtp协议后,我们就开始使用socket这个好东西了。socket被成为TCP/IP协议的API,能做的事情太多了。其实现在的socket5已经支持TCP/IP和UDP等协议了。这里我们需要用到的是
System.Net.Sockets.TcpClient和System.Net.Sockets.NetworkStream,大家可以通过msdn多了解System.Net.Sockets的各个成员。
具体代码如下:
TcpClient SmtpServ = new TcpClient(smtp,25);
listBox1.Items.Clear();
//--显示服务器初始信息
NetworkStream NetStrm = SmtpServ.GetStream();
StreamReader RdStrm = new StreamReader(SmtpServ.GetStream());
listBox1.Items.Add(RdStrm.ReadLine());
sendData = "HELO localhost" + CRLF;
szData = System.Text.Encoding.ASCII.GetBytes(sendData.ToCharArray());
NetStrm.Write(szData, 0, szData.Length);
listBox1.Items.Add(RdStrm.ReadLine());
//--标志发件人
sendData = "MAIL FROM:" + "<" + from + ">" + CRLF;
szData = System.Text.Encoding.ASCII.GetBytes(sendData.ToCharArray());
NetStrm.Write(szData, 0, szData.Length);
listBox1.Items.Add(RdStrm.ReadLine());
//--标志收件人
sendData = "RCPT TO:" + "<" + to + ">" + CRLF;
szData = System.Text.Encoding.ASCII.GetBytes(sendData.ToCharArray());
NetStrm.Write(szData, 0, szData.Length);
listBox1.Items.Add(RdStrm.ReadLine());
//--准备发送内容
sendData = "DATA" + CRLF;
szData = System.Text.Encoding.ASCII.GetBytes(sendData.ToCharArray());
NetStrm.Write(szData, 0, szData.Length);
listBox1.Items.Add(RdStrm.ReadLine());
//--发送主题
sendData = "SUBJECT: " + subject + CRLF;
//--发送内容
sendData = sendData + content + CRLF;
//--'结束发送
sendData = sendData + "." + CRLF;
szData = System.Text.Encoding.ASCII.GetBytes(sendData.ToCharArray());
NetStrm.Write(szData, 0, szData.Length);
listBox1.Items.Add(RdStrm.ReadLine());
//--退出
sendData = "QUIT" + CRLF;
szData = System.Text.Encoding.ASCII.GetBytes(sendData.ToCharArray());
NetStrm.Write(szData, 0, szData.Length);
listBox1.Items.Add(RdStrm.ReadLine());
//--关闭连接
NetStrm.Close();
RdStrm.Close();
listBox1.Items.Add("连接关闭");
listBox1.Items.Add("发送成功");
下一节将讨论ftp协议的socket编程。