【C#】C#对电子邮件的收发操作
目录结构:
1.简介
邮件传输常用的协议有,SMTP、POP3、IMAP4。他们都属于TCP/IP协议,默认状态下分别通过TCP端口25,110,和143建立链接。
SMTP协议
SMTP的全称是“Simple Mail Transfer Protocol”,即简单邮件传输协议。它是一组用于从源地址到目的地址传输邮件的规范,通过它来控制邮件的中转方式。SMTP 协议属于TCP/IP协议簇,它帮助每台计算机在发送或中转信件时找到下一个目的地。SMTP 服务器就是遵循SMTP协议的发送邮件服务器。SMTP认证,简单地说就是要求必须在提供了账户名和密码之后才可以登录 SMTP 服务器,这就使得那些垃圾邮件的散播者无可乘之机。增加 SMTP 认证的目的是为了使用户避免受到垃圾邮件的侵扰。
POP协议
POP邮局协议负责从邮件服务器中检索电子邮件。它要求邮件服务器完成下面几种任务之一:从邮件服务器中检索邮件并从服务器中删除这个邮件;从邮件服务器中检索邮件但不删除它;不检索邮件,只是询问是否有新邮件到达。POP协议支持多用户互联网邮件扩展,后者允许用户在电子邮件上附带二进制文件,如文字处理文件和电子表格文件等,实际上这样就可以传输任何格式的文件了,包括图片和声音文件等。在用户阅读邮件时,POP命令所有的邮件信息立即下载到用户的计算机上,不在服务器上保留。
IMAP协议
互联网信息访问协议(IMAP)是一种优于POP的新协议。和POP一样,IMAP也能下载邮件、从服务器中删除邮件或询问是否有新邮件,但IMAP克服了POP的一些缺点。例如,它可以决定客户机请求邮件服务器提交所收到邮件的方式,请求邮件服务器只下载所选中的邮件而不是全部邮件。客户机可先阅读邮件信息的标题和发送者的名字再决定是否下载这个邮件。通过用户的客户机电子邮件程序,IMAP可让用户在服务器上创建并管理邮件文件夹或邮箱、删除邮件、查询某封信的一部分或全部内容,完成所有这些工作时都不需要把邮件从服务器下载到用户的个人计算机上。
简单来说,SMTP协议主要是用于发邮件,POP和IMAP协议用于读取、删除、下载邮件。结合QQ邮箱和网易邮箱,笔者认为,QQ邮箱更注重POP协议方面,网易邮箱比较注重SMTP协议方面,下面笔者将会对其原由进行阐述,希望对读者有所帮助。
在利用第三方对QQ邮箱和网易邮箱进行邮件操作之前,需要在各自的后台开启POP/SMTP服务,并且获取到授权码(网易邮箱若关闭客户端授权码,则可以直接用登录密码)。
2.发送邮件
发送邮件应该使用SMTP协议。有关SMTP协议的具体内容,这里笔者就不再阐述了。
C#对发送邮件的库封装得已经比较好了,开发人员可以很方便的完成发送邮件的操作。在System.Net.Mail命名空间中封装了对发送邮件的操作,下面是使用QQ邮箱发送的案例:
MailMessage message = new MailMessage(); //设置发件人,发件人需要与设置的邮件发送服务器的邮箱一致 MailAddress fromAddr = new MailAddress("2965372061@qq.com"); message.From = fromAddr; //设置收件人,可添加多个,添加方法与下面的一样 message.To.Add("2965372061@qq.com"); //设置抄送人 message.CC.Add("2965372061@qq.com"); //设置邮件标题 message.Subject = "通知"; //设置邮件内容 message.Body = "Hello world"; //设置邮件发送服务器,服务器根据你使用的邮箱而不同,可以到相应的 邮箱管理后台查看 SmtpClient client = new SmtpClient("smtp.qq.com", 25); //设置发送人的邮箱账号和授权码 client.Credentials = new NetworkCredential("2965372061@qq.com", "授权码"); //启用ssl,也就是安全发送 client.EnableSsl = true; //发送邮件 client.Send(message); Console.WriteLine("发送成功"); Console.ReadLine();
上面发送的是文本格式,接下来介绍如何发送HTML格式的文件。如何想要发送HTML格式的邮件,那么只需要指定IsBodyHtml为true即可。
message.Body="<h1>Hello World</h1>"; message.IsBodyHtml=true;
如果想要发送附件的话,那么应该往Message实例中的Attachments 属性中添加一个Attachment(附件)实例。
关于QQ邮件的发送就讨论到这里,接下来讨论一下网易邮件的发送。网易邮件的发送较为麻烦,这和网易邮箱的反垃圾邮件机制有关。网易为了希望用户能够得到纯净的电子邮件网络环境,减少垃圾邮件,系统对会对发送的信件做判定,并限制对垃圾的邮件的发送。
下面是网易发送邮件的代码,笔者测试能够成功发送邮件:
MailMessage message = new MailMessage(); //设置发件人,发件人需要与设置的邮件发送服务器的邮箱一致 MailAddress fromAddr = new MailAddress("18011389221@163.com"); message.From = fromAddr; message.To.Add("18011389221@163.com");//自己接收 //设置邮件标题 message.Subject = "通知"; //设置邮件内容 message.Body = "Hello world"; //设置邮件发送服务器,服务器根据你使用的邮箱而不同,可以到相应的 邮箱管理后台查看 SmtpClient client = new SmtpClient("smtp.163.com", 25); //设置发送人的邮箱账号和授权码 client.Credentials = new NetworkCredential("18011389221@163.com", "授权码"); //发送邮件 client.Send(message); Console.WriteLine("发送成功"); Console.ReadLine();
笔者只在自己给自己发邮件中测试成功过,在给别的邮箱中发邮件时总是被判定为垃圾邮件。如果读者测试时并不能够成功发送邮件,可按照如下几部步骤检查:
1.检查客户端授权码是否开启,授权码是否停用
2.检查是否开启POP3/SMTP服务
3.将发件人添加到白名单中
4.取消智能收信分类
5.不要设置抄送人
从上面可以看出,在SMTP服务中网易邮箱比QQ邮箱的判断要更加严格。
3.读取邮件
读取邮件要用到的协议为POP3协议。然而C#的类库中,并没有对POP3协议进行封装。QQ邮箱在POP3协议的建立中,使用了SSL,这使得数据的传输更加的安全。然而网易邮箱并没有使用SSL协议。
如果是电脑客户端通过CMD命令与POP服务器建立链接的话,网易邮箱的操作(telnet)没什么难度。但是QQ邮箱的操作(openssl)就相对比较复杂了,在使用openssl命令与主机建立连接时,必需传入证书。C#对SSL已经有过包装,通过C#可以轻松的与QQ邮箱和网易邮箱POP协议主机建立连接。
在开始之前,读者可能需要先了解一些POP3协议的知识,关于POP3文档读者可以自行度娘。这里笔者列举出,POP3协议中的命令码:
命令 | 描述 |
USER [username] | 用户名 |
PASS [password] | 密码 |
APOP [Name,Digest] | 认可Digest是MD5消息摘要 |
STAT | 处理请求服务器发回关于邮箱的统计资料,如邮件总数和总字节数 |
UIDL [Msg#] | 处理返回邮件的唯一标识符,POP3会话的每个标识符都将是唯一的 |
LIST [Msg#] | 处理返回邮件数量和每个邮件的大小 |
RETR [Msg#] | 处理返回由参数标识的邮件的全部文本 |
DELE [Msg#] | 处理服务器将由参数标识的邮件标记为删除,由quit命令执行 |
RSET | 处理服务器将重置所有标记为删除的邮件,用于撤消DELE命令 |
TOP [Msg# n] | 处理服务器将返回由参数标识的邮件前n行内容,n必须是正整数 |
NOOP | 处理服务器返回一个肯定的响应 |
QUIT | 终止会话 |
接下来笔者连接QQ邮箱POP服务主机,展示一些常见的命令使用:
TcpClient clientSocket = new TcpClient(); clientSocket.Connect("pop.qq.com", 995);//连接到QQ邮箱POP服务器 //建立SSL连接 SslStream stream = new SslStream( clientSocket.GetStream(), false, (object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors errors) => { return true;//接收所有的远程SSL链接 }); stream.AuthenticateAsClient("pop.qq.com");//验证 //得到输入流 StreamReader reader = new StreamReader(stream, Encoding.Default, true); //得到输出流 StreamWriter writer = new StreamWriter(stream); Console.WriteLine(reader.ReadLine());//以+Ok开头,表示连接成功 writer.WriteLine("USER 2965372061@qq.com"); writer.Flush(); Console.WriteLine(reader.ReadLine());//+Ok 表示用户名正确 writer.WriteLine("PASS 授权码"); writer.Flush(); Console.WriteLine(reader.ReadLine());//+Ok 表示密码正确 writer.WriteLine("STAT"); writer.Flush(); Console.WriteLine(reader.ReadLine());//获得邮件数 +OK 189 1058197 表示 189封邮件,1058197b writer.WriteLine("RETR 1"); writer.Flush(); String result = null;//获得第1封邮件的内容,读取的内容需要使用base64解码 while ((result = reader.ReadLine()) != null) { Console.WriteLine(reader.ReadLine()); } Console.ReadLine();
读者也可以测试连接网易邮箱POP服务器,
1.网易邮箱POP服务器的远程地址是:pop.163.com:995。
2.无需建立SSL链接