最近因为不是太忙,所以就心血来潮的用Lumisoft写了个Web端的邮件收发系统。在此记录开发历程。
一、首先先介绍下这个系统的基本思路:把邮件从服务器下载下来然后保存到本地,查看邮件的时候再加载邮件信息。这里,都是用XML,来存储邮件的基本信息。
二、用到的类
Mail_Item类记录邮件的基本信息
Person类记录的是邮件用户名及名称
Attachment 类记录附件的基本信息
Mail_Summary 邮件信息概要类,用于显示邮件列表
User 用户信息类,记录用户信息
/// <summary>
/// 邮件的基本信息
/// </summary>
public class Mail_Item
{
/// <summary>
/// The unique mail Identity in Mail Server
/// </summary>
public string Mail_Id { get; set; }
/// <summary>
/// Mail sender
/// </summary>
public Person Mail_From { get; set; }
/// <summary>
/// Mail Receiver
/// </summary>
public List<Person> Mail_To = new List<Person>();
/// <summary>
/// Mail copy to
/// </summary>
public List<Person> Mail_CopyTo = new List<Person>();
public string Mail_Subject { get; set; }
/// <summary>
/// Mail content path in localhost
/// </summary>
public string Mail_Body { get; set; }
/// <summary>
/// Mail receive date
/// </summary>
public string Mail_Date { get; set; }
/// <summary>
/// Mail attachments
/// </summary>
public List<Attachment> Mail_Attachment = new List<Attachment>();
/// <summary>
/// mail is read or unread
/// </summary>
public bool IsRead { get; set; }
public bool IsDeleted { get; set; }
}
三、接收邮件
主要步骤有:登录服务器-->判断当前邮件在系统中是否已经存在了->下载邮件,并且保存邮件的基本信息
接收邮件代码:
public static List<Mail_Item> ReceiveMail(User user, out int mailNum)
{
string baseBodyPath = @"Mails\" + user.Server + @"\" + user.Identity + @"\Mails\";
string baseAttPath = @"Mails\" + user.Server + @"\" + user.Identity + @"\Attachments\";
CreateFoder(user);
mailNum = 0;
string _mailServer = user.Server;
string _isHelpAccount = user.Account;
string _isHelpPassword = user.Password;
List<Mail_Item> mails = new List<Mail_Item>();
if (string.IsNullOrEmpty(_mailServer) || string.IsNullOrEmpty(_isHelpAccount) || string.IsNullOrEmpty(_isHelpPassword))
{
return mails;
}
string _mailId = string.Empty;
string _subject = string.Empty; //主题
string _body = string.Empty; //正文
string _receiveDate = string.Empty;//接收时间
// Int64 maxUID = GetXmkUserInfo(_mailServer, _isHelpAccount, _isHelpPassword).MaxMailID; //获取上一次接收邮件最大的ID
//if (maxUID < 0)
//{
// return mails;
//}
using (POP3_Client pop = new POP3_Client())
{
try
{
pop.Connect(_mailServer, 110, false);
pop.Login(_isHelpAccount, _isHelpPassword);
POP3_ClientMessageCollection messages = pop.Messages;
//1415170251.6684.Qmail,S=866235:第一部分是递增的
//最后一份邮件都不是最新的,要提示
// _mailId = messages[messages.Count - 1].UID;
for (int i = messages.Count - 1; 0 <= i; i--)
{
_mailId = messages[i].UID;
//try
//{
// byte[] bt = messages[i].HeaderToByte();
// Mail_Message mime_header = Mail_Message.ParseFromByte(bt);
// Mail_h_Received[] r = mime_header.Received;
//}
//catch
//{ }
//if (Convert.ToInt64(_mailId.Split('.')[0]) <= maxUID)
// return mails;
try
{
if (CheckMailExists(user, _mailId)) //如果存在
{
continue;
}
}
catch
{
;
}
#region 读取邮件
POP3_ClientMessage ms = messages[i];
if (ms != null)
{
List<Person> p_to = new List<Person>(); //收件人列表
List<Person> p_copyTo = new List<Person>();//抄送人列表
Person p_from = new Person();//发送人
List<Attachment> list_att = new List<Attachment>();//附件信息
#region 基本信息
//有新邮件就+1
Mail_Message mime_message = new Mail_Message();
try
{
byte[] messageBytes = ms.MessageToByte();
mime_message = Mail_Message.ParseFromByte(messageBytes);
}
catch
{
continue;
}
mailNum++;
try
{
_subject = mime_message.Subject.Trim() == string.Empty ? "No Subject" : mime_message.Subject;
}
catch (Exception ex)
{
_subject = "No Subject";
}
p_from.Address = mime_message.From == null ? "sender is null" : mime_message.From[0].Address;
try
{
string name = "";
if (string.IsNullOrEmpty(mime_message.From[0].DisplayName))
{
int index = mime_message.From[0].Address.IndexOf("@");
name = mime_message.From[0].Address.Substring(0, index);
}
else
{
name = mime_message.From[0].DisplayName;
}
p_from.Name = name;
}
catch (Exception fe)
{
p_from.Name = "SomeOne";
}
try
{
Mail_t_AddressList to = mime_message.To;
if (to.Count > 0 && to != null)
{
for (int ii = 0; ii < to.Mailboxes.Length; ii++)
{
string t_name = "";
if (string.IsNullOrEmpty(to.Mailboxes[ii].DisplayName))
{
int index = to.Mailboxes[ii].Address.IndexOf("@");
t_name = to.Mailboxes[ii].Address.Substring(0, index);
}
else
{
t_name = to.Mailboxes[ii].DisplayName;
}
Person per = new Person
{
Address = to.Mailboxes[ii].Address,
Name = t_name
};
p_to.Add(per);
}
}
}
catch (Exception e)
{
;
}
try
{
Mail_t_AddressList copyTo = mime_message.Cc; //获取的抄送人信息
if (copyTo.Count > 0 && copyTo != null)
{
for (int ii = 0; ii < copyTo.Mailboxes.Length; ii++)
{
string t_name = "";
if (string.IsNullOrEmpty(copyTo.Mailboxes[ii].DisplayName))
{
int index = copyTo.Mailboxes[ii].Address.IndexOf("@");
t_name = copyTo.Mailboxes[ii].Address.Substring(0, index);
}
else
{
t_name = copyTo.Mailboxes[ii].DisplayName;
}
Person per1 = new Person
{
Address = copyTo.Mailboxes[ii].Address,
Name = t_name
};
p_copyTo.Add(per1);
}
}
}
catch (Exception e)
{
;
}
try
{
_receiveDate = mime_message.Date.ToString("yyyy-MM-dd HH:mm:ss");
}
catch
{
Mail_h_Received[] r = mime_message.Received;
_receiveDate = r[0].Time.ToString("yyyy-MM-dd HH:mm:ss") ;
}
_body = mime_message.BodyText;
try
{
if (!string.IsNullOrEmpty(mime_message.BodyHtmlText))
{
_body = mime_message.BodyHtmlText;
}
}
catch
{
_body = mime_message.BodyText; ;//Response.Write("<script>alert('HTMLBODY');</script>");//屏蔽编码出现错误的问题,错误在BodyText存在而BodyHtmlText不存在的时候,访问BodyHtmlText会出现
}
#endregion
#region 附件信息
MIME_Entity[] attachments = mime_message.GetAttachments(true, true);
foreach (MIME_Entity entity in attachments)
{
Attachment m_att = new Attachment();
string cid;
int eIndex;
if (entity.ContentDisposition != null) //不是内嵌附件
{
cid = entity.ContentID;
string _aName = entity.ContentDisposition.Param_FileName;//区别物理名和逻辑
m_att.A_ID = System.Guid.NewGuid().ToString();
if (string.IsNullOrEmpty(_aName))
{
// _aName = entity.ContentDisposition.Parameters.Owner.ValueToString();
_aName = entity.ContentDescription.ToString();
}
m_att.Name = _aName;
//_attName = DateTime.Now.ToString("yyyyMMddhhmmssfff") + m_att.A_ID;
string type = entity.ContentType.ValueToString();
if (!string.IsNullOrEmpty(m_att.Name))
{
string path = Path.Combine(baseAttPath, m_att.A_ID + "_" + m_att.Name);
m_att.Path = path;
try
{
MIME_b_SinglepartBase byteObj = (MIME_b_SinglepartBase)entity.Body;
Stream decodedDataStream = byteObj.GetDataStream();
using (FileStream fs = new FileStream(serverPath+ path, FileMode.Create))
{
try
{
LumiSoft.Net.Net_Utils.StreamCopy(decodedDataStream, fs, 4000);
}
catch (Exception e)
{
;
}
}
}
catch (Exception e)
{
;
}
}
m_att.IsInline = entity.ContentDisposition.DispositionType == MIME_DispositionTypes.Inline;
}
else //内嵌附件
{
cid = entity.ContentID;
m_att.A_ID = System.Guid.NewGuid().ToString();
m_att.Name = entity.ContentType.Parameters["name"];
try
{
eIndex = m_att.Name.LastIndexOf(".");//有些图片没有后缀名,直接添加一个后缀
if (eIndex == -1)
m_att.Name += ".png";
}
catch (Exception e)
{
m_att.Name = System.Guid.NewGuid().ToString() + ".png";
}
string path = Path.Combine(baseAttPath, m_att.A_ID + "_" + m_att.Name);
m_att.Path = path;
string enString = entity.ToString();
int a = enString.LastIndexOf(">");
string base64string = enString.Substring(a + 5);
byte[] bt = Convert.FromBase64String(base64string);
File.WriteAllBytes(serverPath+m_att.Path, bt);
m_att.IsInline = true;
}
m_att.ContentID = entity.ContentID;
try
{
if (cid != null || cid.Trim() != string.Empty)
_body = _body.Replace("cid:" + cid.Substring(1, cid.Length - 2), m_att.Path);
}
catch (Exception e)
{
;
}
list_att.Add(m_att);
}
#endregion
//Body内容存储为一个文件
string _bodyFileName = System.Guid.NewGuid().ToString() + ".html";
try
{
File.WriteAllText(serverPath+ baseBodyPath + _bodyFileName, _body,Encoding.GetEncoding("utf-8"));
// File.w
}
catch
{
;
}
Mail_Item mi = new Mail_Item
{
Mail_Id = _mailId,
Mail_From = p_from,
Mail_To = p_to,
Mail_CopyTo = p_copyTo,
Mail_Subject = _subject,
Mail_Body = baseBodyPath + _bodyFileName,
Mail_Attachment = list_att,
Mail_Date = _receiveDate,
IsRead = false,
IsDeleted = false
};
mails.Add(mi);
#endregion
}
}
}
catch (Exception e)
{
;
}
pop.Disconnect();
return mails;
}
}
在接收邮件中不得不提的是邮件内嵌图片的接收,内嵌图片不像普通附件那样,它的entity.ContentDisposition=null,所以得另行讨论,见代码。还有一个关于附件的问题是我用hotmail给我的qq邮箱发的附件,它的entity.ContentDisposition.Param_FileName为null,所以我做了如下处理
string _aName = entity.ContentDisposition.Param_FileName;//区别物理名和逻辑
m_att.A_ID = System.Guid.NewGuid().ToString();
if (string.IsNullOrEmpty(_aName))
{
// _aName = entity.ContentDisposition.Parameters.Owner.ValueToString();
_aName = entity.ContentDescription.ToString();
}
自此基本的邮件接收就没问题了。
以下是我写的邮件系统截图: