用QQ来向其他邮箱发邮件时,若用SMTP,则会发送不成功。可参照http://www.cnblogs.com/chhuic/archive/2009/09/26/1574375.html随笔。经查找相关资料,原来是为了防止垃圾邮件的发送,邮件提供商都使用了ESMTP协议了,以下是采用ESMTP协议来达到QQ发送邮件的目的。
下面我把源代码贴出来,由于有比较详细的说明,在些不多解释了。
以下是测试用例:
163邮箱向QQ邮箱发送
QQ邮箱向163邮箱发送
QQ向163发送成功界面:
QQ向163发过程:
下面我把源代码贴出来,由于有比较详细的说明,在些不多解释了。
Code
1 NetworkStream ns = null;
2 string mailString = string.Empty;
3
4 /**//// <summary>
5 /// 发送邮件
6 /// </summary>
7 /// <param name="smtpServer">smtp服务器名或者IP</param>
8 /// <param name="port">smtp服务器开放的端口</param>
9 /// <param name="isEsmtp">是否需要验证</param>
10 /// <param name="userName">用户名</param>
11 /// <param name="userPwd">密码</param>
12 /// <param name="mail">邮件对象</param>
13 /// <returns></returns>
14 public bool SendMail(string smtpServer, int port, bool isEsmtp, string userName, string userPwd, Mail2 mail)
15 {
16 TcpClient client = new TcpClient();
17 IPAddress ip = Dns.GetHostAddresses(smtpServer)[0];
18 IPEndPoint remoteEP = new IPEndPoint(ip, port);
19 client.Connect(remoteEP);
20 if (client.Connected)
21 {
22
23 ns = client.GetStream();
24 if (GetStatusCode() != 220)
25 {
26 return false;
27 }
28 SendCmd("HELO " + smtpServer + "\r\n");
29 if (GetStatusCode() != 250)
30 {
31 return false;
32 }
33 if (isEsmtp)
34 {
35 SendCmd("AUTH LOGIN\r\n");
36 if (GetStatusCode() != 334)
37 { return false; }
38 SendCmd(GetBase64String(userName) + "\r\n");
39 if (GetStatusCode() != 334)
40 { return false; }
41 SendCmd(GetBase64String(userPwd) + "\r\n");
42 if (GetStatusCode() != 235)
43 { return false; }
44 }
45 SendCmd("MAIL FROM: <" + mail.MailFrom + ">\r\n");//必须加个‘<’、‘>’,否则出现500 bad Syntax 错误,即命令语法错误
46 if (GetStatusCode() != 250)
47 { return false; }
48 foreach (string to in mail.MailTo)
49 {
50 SendCmd("RCPT TO: <" + to + ">\r\n");//必须加个‘<’、‘>’,否则出现500 bad Syntax 错误,即命令语法错误
51 if (GetStatusCode() != 250)
52 { return false; }
53 }
54 SendCmd("data\r\n");
55 if (GetStatusCode() != 354)
56 { return false; }
57 StringBuilder content = new StringBuilder();
58
59 content.AppendFormat("From:{0}\r\n", mail.MailFrom);
60 string toTxt = string.Empty;
61 foreach (string to in mail.MailTo)
62 {
63 toTxt += to + ";";
64 }
65 toTxt = toTxt.Substring(0, toTxt.Length - 1);
66 content.AppendFormat("To:{0}\r\n", toTxt);//发送到达邮件
67 content.AppendFormat("Date:{0}\r\n", mail.SendDate.ToString());//发送时间
68 content.AppendFormat("Subject:{0}\r\n", mail.Subject);//邮件主题
69 content.Append("\r\n");
70 content.Append(mail.Content);//邮件内容
71 content.Append("\r\n.\r\n");
72 SendCmd(content.ToString());
73 if (GetStatusCode() != 250)//250 表示命令执行成功
74 {
75 return false;
76
77 }
78 else
79 {
80 return true;
81 }
82 }
83 else
84 {
85 return false;
86 }
87 }
88 /**//// <summary>
89 /// 发送邮件命令
90 /// </summary>
91 /// <param name="cmd">命令</param>
92 private void SendCmd(string cmd)
93 {
94 byte[] data = Encoding.UTF8.GetBytes(cmd);
95 ns.Write(data, 0, data.Length);
96 ns.Flush();//提交
97 }
98 /**//// <summary>
99 /// 得到发送邮件命令状态
100 /// </summary>
101 /// <returns></returns>
102 private int GetStatusCode()
103 {
104 byte[] data = new byte[1024];
105 int i = ns.Read(data, 0, data.Length);
106 string str = Encoding.UTF8.GetString(data, 0, i);//获取返回命令字符串
107 if (str.Length > 3)
108 {
109 str = str.Substring(0, 3);
110 }//得到命令标识,由三位数字来表示,具体含义可参考ESMTP相关文档
111 int code = 0;
112 try
113 {
114 code = int.Parse(str);
115 }
116 catch { }
117 return code;
118 }
119 /**//// <summary>
120 /// BASE64 加密
121 /// </summary>
122 /// <param name="source"></param>
123 /// <returns></returns>
124 private string GetBase64String(string source)
125 {
126 byte[] data = Encoding.UTF8.GetBytes(source);
127 return Convert.ToBase64String(data);
128 }
1 NetworkStream ns = null;
2 string mailString = string.Empty;
3
4 /**//// <summary>
5 /// 发送邮件
6 /// </summary>
7 /// <param name="smtpServer">smtp服务器名或者IP</param>
8 /// <param name="port">smtp服务器开放的端口</param>
9 /// <param name="isEsmtp">是否需要验证</param>
10 /// <param name="userName">用户名</param>
11 /// <param name="userPwd">密码</param>
12 /// <param name="mail">邮件对象</param>
13 /// <returns></returns>
14 public bool SendMail(string smtpServer, int port, bool isEsmtp, string userName, string userPwd, Mail2 mail)
15 {
16 TcpClient client = new TcpClient();
17 IPAddress ip = Dns.GetHostAddresses(smtpServer)[0];
18 IPEndPoint remoteEP = new IPEndPoint(ip, port);
19 client.Connect(remoteEP);
20 if (client.Connected)
21 {
22
23 ns = client.GetStream();
24 if (GetStatusCode() != 220)
25 {
26 return false;
27 }
28 SendCmd("HELO " + smtpServer + "\r\n");
29 if (GetStatusCode() != 250)
30 {
31 return false;
32 }
33 if (isEsmtp)
34 {
35 SendCmd("AUTH LOGIN\r\n");
36 if (GetStatusCode() != 334)
37 { return false; }
38 SendCmd(GetBase64String(userName) + "\r\n");
39 if (GetStatusCode() != 334)
40 { return false; }
41 SendCmd(GetBase64String(userPwd) + "\r\n");
42 if (GetStatusCode() != 235)
43 { return false; }
44 }
45 SendCmd("MAIL FROM: <" + mail.MailFrom + ">\r\n");//必须加个‘<’、‘>’,否则出现500 bad Syntax 错误,即命令语法错误
46 if (GetStatusCode() != 250)
47 { return false; }
48 foreach (string to in mail.MailTo)
49 {
50 SendCmd("RCPT TO: <" + to + ">\r\n");//必须加个‘<’、‘>’,否则出现500 bad Syntax 错误,即命令语法错误
51 if (GetStatusCode() != 250)
52 { return false; }
53 }
54 SendCmd("data\r\n");
55 if (GetStatusCode() != 354)
56 { return false; }
57 StringBuilder content = new StringBuilder();
58
59 content.AppendFormat("From:{0}\r\n", mail.MailFrom);
60 string toTxt = string.Empty;
61 foreach (string to in mail.MailTo)
62 {
63 toTxt += to + ";";
64 }
65 toTxt = toTxt.Substring(0, toTxt.Length - 1);
66 content.AppendFormat("To:{0}\r\n", toTxt);//发送到达邮件
67 content.AppendFormat("Date:{0}\r\n", mail.SendDate.ToString());//发送时间
68 content.AppendFormat("Subject:{0}\r\n", mail.Subject);//邮件主题
69 content.Append("\r\n");
70 content.Append(mail.Content);//邮件内容
71 content.Append("\r\n.\r\n");
72 SendCmd(content.ToString());
73 if (GetStatusCode() != 250)//250 表示命令执行成功
74 {
75 return false;
76
77 }
78 else
79 {
80 return true;
81 }
82 }
83 else
84 {
85 return false;
86 }
87 }
88 /**//// <summary>
89 /// 发送邮件命令
90 /// </summary>
91 /// <param name="cmd">命令</param>
92 private void SendCmd(string cmd)
93 {
94 byte[] data = Encoding.UTF8.GetBytes(cmd);
95 ns.Write(data, 0, data.Length);
96 ns.Flush();//提交
97 }
98 /**//// <summary>
99 /// 得到发送邮件命令状态
100 /// </summary>
101 /// <returns></returns>
102 private int GetStatusCode()
103 {
104 byte[] data = new byte[1024];
105 int i = ns.Read(data, 0, data.Length);
106 string str = Encoding.UTF8.GetString(data, 0, i);//获取返回命令字符串
107 if (str.Length > 3)
108 {
109 str = str.Substring(0, 3);
110 }//得到命令标识,由三位数字来表示,具体含义可参考ESMTP相关文档
111 int code = 0;
112 try
113 {
114 code = int.Parse(str);
115 }
116 catch { }
117 return code;
118 }
119 /**//// <summary>
120 /// BASE64 加密
121 /// </summary>
122 /// <param name="source"></param>
123 /// <returns></returns>
124 private string GetBase64String(string source)
125 {
126 byte[] data = Encoding.UTF8.GetBytes(source);
127 return Convert.ToBase64String(data);
128 }
以下是测试用例:
163邮箱向QQ邮箱发送
QQ邮箱向163邮箱发送
QQ向163发送成功界面:
QQ向163发过程:
IP:119.147.18.223
Port:25
begin connect .....
connected
220 Esmtp QQ Mail Server
HELO smtp.qq.com
250 Esmtp OK
AUTH LOGIN
334 VXNlcm5hbWU6
user:XXXXXXXXXXXX
334 XXXXXXXXXXXX
passXXXXXXXXXXXX=
235 Authentication successful
MAIL FROM: <123456@qq.com>
250 Ok
RCPT TO: <test@163.com>
250 Ok
data
354 End data with <CR><LF>.<CR><LF>
From:123456@qq.com
To:test@163.com
Date:0001-1-1 0:00:00
Subject:Subject
body text
.
250 Ok: queued as
========================================
2009年10月22日上传:
源代码打包下载:MailDemo(VS2008)