c#中邮件收发处理(POP3,IMAP,SMTP)

来源: 随心所欲 - 博客园
  本文涉及的内容:
  1:自己制作Pop3Helper
  信件格式的处理有麻烦
  2:使用现成的pop3类
  LumiSoft.Net.POP3.Client;
  有两种处理方法
  3:使用IMAP收邮件
  功能似乎更多,比起pop3来。
  4:SMTP发送邮件
  关于 Mailbox unavailable. The server response was: 5.7.1 Unable to relay for xx 的错误处理

  自己写一个POP3的接收程序并不是很简单。主要问题就是如何处理信件的格式。
其处理方法不是太复杂,用一个tcp联接就可以了。
这是代码
public class Pop3Helper
{
string _pop3server;
string _user;
int _port;
string _pwd;

public TcpClient _server;
public NetworkStream _netStream;
public StreamReader _reader;
public string _data;
public byte[] _charData;
public string _CRLF = "\r\n";

private string _log;
public string LogMSG
{
get { return _log; }
}
///
///
///
///
///
///
///
public Pop3Helper(string server, int port, string user, string pwd)
{
_pop3server = server;
_port = port;
_user = user;
_pwd = pwd;
}
///
/// connect
///
public void Connect()
{
//create a tcp connection
_server = new TcpClient(_pop3server, _port);

//prepare
_netStream = _server.GetStream();
_reader = new StreamReader(_server.GetStream());
if (!CheckResult(_reader.ReadLine()))
throw new Exception("Connect Error");

//login
_data = "USER " + this._user + _CRLF;
_charData = System.Text.Encoding.ASCII.GetBytes(_data.ToCharArray());
_netStream.Write(_charData, 0, _charData.Length);
if (!CheckResult(_reader.ReadLine()))
throw new Exception("User Error");

_data = "PASS " + this._pwd + _CRLF;
_charData = System.Text.Encoding.ASCII.GetBytes(_data.ToCharArray());
_netStream.Write(_charData, 0, _charData.Length);
if (!CheckResult(_reader.ReadLine()))
throw new Exception("Pass Error");

}
///
/// get message Numbers
///
///
public int GetMailCount()
{
try
{
_data = "STAT" + _CRLF;
_charData = System.Text.Encoding.ASCII.GetBytes(_data.ToCharArray());
_netStream.Write(_charData, 0, _charData.Length);
string resp = _reader.ReadLine();
string[] tokens = resp.Split(new char[] { ' ' });
return Convert.ToInt32(tokens[1]);
}
catch (Exception ex)
{
return 0;
}
}

public string GetMail(int id)
{
string line;
string content = "";
try
{
//get by id
_data = "RETR " + id + _CRLF;
_charData = System.Text.Encoding.ASCII.GetBytes(_data.ToCharArray());
_netStream.Write(_charData, 0, _charData.Length);
line = _reader.ReadLine();

if (line[0] != '-')
{
//end with '.'
while (line != ".")
{
line = _reader.ReadLine();
content += line + "\r\n";
}
}

return content;
}
catch (Exception err)
{
Log(err.Message);
return "Error";
}
}
public void DeleteMail(int id)
{
_data = "DELE" + id + _CRLF;
_charData = System.Text.Encoding.ASCII.GetBytes(_data.ToCharArray());
_netStream.Write(_charData, 0, _charData.Length);
if (!CheckResult(_reader.ReadLine()))
throw new Exception("Delete Error");

}
///
/// close connection
///
public void Close()
{

_data = "QUIT" + _CRLF;
_charData = System.Text.Encoding.ASCII.GetBytes(_data.ToCharArray());
_netStream.Write(_charData, 0, _charData.Length);

//close
_netStream.Close();
_reader.Close();
}
private bool CheckResult(string reply)
{
Log(reply);
if (reply.IndexOf("+OK") > -1)
return true;
else
return false;
}
private void Log(string msg)
{
_log += msg + "\r\n";
}
}
。。。。。
  但是这种方式的一个问题就是关于解析信件的格式。如果是附件的话,他也直接给出了二进制,不容易使用。

  所以,可以使用一个现成的工具:LumiSoft.Net.POP3.Client。这里面已经给写好了实现,用起来也很简单。
这是一个简单的用法(这里使用了两种处理方式,前一种是不建议使用的)
。。
  using (POP3_Client pop3 = new POP3_Client())
  {
  //与Pop3服务器建立连接
  pop3.Connect(_popServer, _pop3port,false);
  //验证身份
  pop3.Authenticate(_user, _pwd, false);

  //get all messages
  POP3_MessagesInfo infos = pop3.GetMessagesInfo();
  foreach (POP3_MessageInfo info in infos)
  {
  byte[] bytes = pop3.GetMessage(info.MessageNumber);
  Mime mime = Mime.Parse(bytes);
  HandleMail(mime);
  //delete it at last
  //pop3.DeleteMessage(info.MessageNumber);
  }
  //the second way to do it
//for (int i = 0; i < pop3.Messages.Count; i++)
  //{
  // byte[] bytes = pop3.Messages.MessageToByte();
  // Mime mime = Mime.Parse(bytes);
  // HandleMail(mime);
  // //delete it at last
  // //pop3.DeleteMessage(pop3.Messages.SequenceNumber);
//}。
。。。
取得的邮件可以这要给获得。
#region pop3
  //string customer = mime.MainEntity.To.ToAddressListString(); //cargo company
  //string sender = mime.MainEntity.From.ToAddressListString(); //this is customer who send
  #endregion
  string customer = MailboxesToString(envelope.To); //cargo company
  string sender = MailboxesToString(envelope.From); //this is customer who send
。。。
  除此之外,它提供的另外一个工具是IMAP,它操作起来更加方便。代码如下:

IMAP_Client clnt = new IMAP_Client();
  try
  {
  clnt.Connect("mail.xx.com", 143, false);
  clnt.Authenticate("user", "password");
  string[] folders = clnt.GetFolders(); //get all types
  string folder = "Inbox";
  clnt.SelectFolder(folder);
  IMAP_SequenceSet sequence_set = new IMAP_SequenceSet();
  // All messages
  sequence_set.Parse(string.Format("{0}:{1}", 1, clnt.MessagesCount));
  IMAP_FetchItem[] fetchItems = clnt.FetchMessages(
  sequence_set,
  IMAP_FetchItem_Flags.UID | IMAP_FetchItem_Flags.MessageFlags | IMAP_FetchItem_Flags.Size | IMAP_FetchItem_Flags.Envelope,
  true, false
  );
  //int count =0;
  foreach (IMAP_FetchItem fetchItem in fetchItems)
  {
  IMAP_Envelope envelope = fetchItem.Envelope;
  //hanldle it, means read and search and reply
  try
  {
  HandleMail(envelope);
  //count++;
  }
  catch (Exception ex)
  {
  Log("Sys", ex.Message);
}
  }
  //delete it after hanlde
  clnt.DeleteMessages(sequence_set, false);
  //disconnect
  clnt.Disconnect();

  //MessageBox.Show(count.ToString() + " of " + fetchItems .Length+ " Success");
  }
  catch (Exception x)
  {
  Log("Sys", x.Message);
  //MessageBox.Show(x.Message);
  }

。。
  上边都是如何收邮件。
  关于如何发送邮件是比较简单的。这里提供两种方式。
  第一种方式是使用网上的smtp。这种方式必须要提供用户名和密码。这个适合于web应用,使用的smtp也是网上的,我一般使用163的smtp,基本没有问题。
  第二种方式是使用本地的smtp。不需要提供密码,用户也可以是不存在的(垃圾邮件是不是就是这么产生的?),但是必要要提供smtp端口号。

  第二种方法测试的时候有时候会报错“Mailbox unavailable. The server response was: 5.7.1 Unable to relay for xxx”,查过资料之后(在baidu上没找到,还是google信息多一点),才发现问题原来是IIS里SMTP服务的配置有问题。
这样修改可以解决:到开SMTP属性—>Access页面Reply Restrictions/ Reply-Only this Below选项,加上自己的ip:127.0.0.1(允许本机,使用loalhost,如果是允许其他机器,类似设置)
代码如下
public class EMail
  {
static public string accountName;
static public string password;
static public string smtpServer;
static public int smtpPort;

///
/// need password,username, smtpserver
///
///
///
///
static public void SendMail(string sendTo, string subject, string body)
  {
//.net smtp
  System.Web.Mail.MailMessage mailmsg = new System.Web.Mail.MailMessage();
  mailmsg.To = sendTo;
  //mailmsg.Cc = cc;
  mailmsg.Subject = subject;
  mailmsg.Body = body;

  //sender here
  mailmsg.From = EMail.accountName;
  // certify needed
  mailmsg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate", "1"); //1 is to certify
  //the user id
  mailmsg.Fields.Add(
  "http://schemas.microsoft.com/cdo/configuration/sendusername",
  EMail.accountName);
  //the password
  mailmsg.Fields.Add(
  "http://schemas.microsoft.com/cdo/configuration/sendpassword",
  EMail.password);

  System.Web.Mail.SmtpMail.SmtpServer = EMail.smtpServer;
  System.Web.Mail.SmtpMail.Send(mailmsg);

}
#region send mail2
///
/// need username,smtp,smtp port
///
///
///
///
  static public void SendMail2(string sendTo, string subject, string body)
  {
  System.Net.Mail.MailMessage msg = new System.Net.Mail.MailMessage();
  msg.To.Add(sendTo);
msg.From = new System.Net.Mail.MailAddress(accountName );

msg.Subject = subject;
msg.SubjectEncoding = System.Text.Encoding.UTF8;
msg.Body = body; //
msg.BodyEncoding = System.Text.Encoding.UTF8;
msg.IsBodyHtml = false;
//msg.Priority = MailPriority.High; //

  System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient();
client.Host = smtpServer;
client.Port = smtpPort;
  //client.Credentials = new System.Net.NetworkCredential("user@xxx.com", "pass");
client.Send(msg);

}
#endregion
}

友情提示:此文并不表示本站肯定持有相同观点,转载请注明出处。
 您可能对 [C#] 的这些文章也感兴趣:

C#重点知识详解(一)  C#精髓集合(6)
C#中的委托与事件[翻译]  C#程序控制开始菜单的弹出
C#锐利体验(3.1)  C#实现遗传算法,模拟花朵的进化
DotMSN机器人自动掉线的问题  C#3.0 新特性速览(2)
蜘蛛/爬虫程序的多线程控制(C#语言)  C#的多线程机制初探(7)
C#调用非托管DLL的APIs  如何使用C#调用非托管DLL函数
使用.NET对事件进行编程  单元测试和事先测试开发(1)
开发应用时如何利用C#自定义属性  .NET的目标(二)
在C#程序设计中使用Win32类库  C#读取POP3邮件的操作
用C#实现Web服务器  使用C#控制远程计算机的服务