最近因为项目需要,研究了一下邮件的发送和接收,发现现在这方面的问题很多.虽然网上这方面的资料很多,但是真正应用起来
仍然会发现不少问题,而且很多人都抱怨书上或者网上的一些代码应用起来是失败的,并且针对附件方面的处理不太完善,针对这种情况我把最近研究所得做一个小小的总结,希望能对大家有所帮助。
首先来谈谈发送邮件的问题。
发送邮件现在应用得最多的两种情况就是利用.NET自带的发送邮件和利用jmail组件来发送邮件。
.NET自带的邮件发送利用了System.Web.Mail.MailMessage这个类,这是在VS2003的情况下,在VS2005下更多的是利
用System.Net.Mail.MailMessage,下面的例子是在VS2003的情况下写的,请在应用的时候自己替换掉里面的参数。
string
SendTos
=
SendTo.Text.Trim();
//
发送人
string
CcTos
=
CcTo.Text.Trim();
//
抄送人
string
[] Receiver
=
System.Text.RegularExpressions.Regex.Split(SendTos
+
CcTos,
"
,
"
);
//
总收件人
string
FromMail
=
"
ustbwuyi1@163.com
"
;
//
发件人
string
Title
=
"
你好
"
;
//
邮件主题
string
Body
=
"
附件里重要文档,请查收!
"
;
//
邮件主体
string
ShowName
=
"
ustbwuyi
"
;
//
显示名字
if
(SendTos
!=
""
||
CcTos
!=
""
)
{
//
用户名(取发送邮箱的@前面的部分,即ustbwuyi1
string
MailUserName
=
FromMail.Substring(
0
,FromMail.IndexOf(
"
@
"
));
//
密码
string
MailPassword
=
"
ustbwuyi
"
;
System.Web.Mail.MailMessage mailmessage
=
new
MailMessage();
mailmessage.From
=
FromMail;
mailmessage.Subject
=
Title;
mailmessage.Body
=
Body;
//
添加附件
ArrayList FileNames;
//
如果存在附件
if
(FileNames.Count
>=
1
)
{
//
添加附件
string
Filename;
for
(
int
k
=
0
;k
<
FileNames.Count;k
++
)
{
Filename
=
FileNames[k].ToString();
mailmessage.Attachments.Add(
new
MailAttachment(Filename));
}
}
}
mailmessage.Fields.Add(
"
http://schemas.microsoft.com/cdo/configuration/smtpauthenticate
"
,
1
);
mailmessage.Fields.Add(
"
http://schemas.microsoft.com/cdo/configuration/sendusername
"
,MailUserName);
mailmessage.Fields.Add(
"
http://schemas.microsoft.com/cdo/configuration/sendpassword
"
,MailPassword);
//
向收件人和抄送人循环发送
for
(
int
j
=
0
;j
<
Receiver.Length;j
++
)
{
mailmessage.To
=
Receiver[j].ToString();
System.Web.Mail.SmtpMail.SmtpServer
=
"
smtp.163.com
"
;
try
{
System.Web.Mail.SmtpMail.Send(mailmessage);
}
catch
(Exception ex)
{
Response.Write(
"
<script language='javascript'>alert('邮件发送失败,请您和ustbwuyi联系(QQ:108556024)!')</script>
"
);
}
}
}
上面的例子是利用163的SMTP邮件服务器来发送邮件,当然,如果你有自己的邮件服务器更好。
其次,是利用jmail组件来发送,现在jmail组件的版本很多,在这里我个人推荐jmail4.4pro版本,因为如果你
要收邮件的话,必须用pro版本,另外,个人经过测试了其它几个版本,发现只有这个版本不会出现附件丢失的情况,其他几个版本都会出现附件丢失或者损坏的
情况,这个对txt文件来说没有影响,但是对于传送图片或者其他的一些压缩文件,会发现从pop服务器上下过来的附件有一些损坏,从而不能正常打开文件。
下面是jmail发送邮件的代码。
jmail.MessageClass MyMail
=
new
jmail.MessageClass();
string
SendTos
=
SendTo.Text.Trim();
//
发送人
string
CcTos
=
CcTo.Text.Trim();
//
抄送人
string
[] Receiver
=
System.Text.RegularExpressions.Regex.Split(SendTos
+
CcTos,
"
,
"
);
//
总收件人
string
FromMail
=
"
ustbwuyi1@163.com
"
;
//
发件人
string
Title
=
"
你好
"
;
//
邮件主题
string
Body
=
"
附件里是重要文档,请查收!
"
;
//
邮件主体
string
ShowName
=
"
ustbwuyi
"
;
//
显示名字
//
取email的@前面部分为用户名,即ustbwuyi1,当然也可以自己设置.
string
MailUserName
=
FromMail.Substring(
0
,FromMail.IndexOf(
"
@
"
));
string
MailPassword
=
"
ustbwuyi
"
;
if
(SendTos
!=
""
||
CcTos
!=
""
)
{
//
字符集
MyMail.Charset
=
"
GB2312
"
;
//
附件的编码格式
MyMail.Encoding
=
"
BASE64
"
;
/**/
///
/是否将信头编码成iso-8859-1字符集
MyMail.ISOEncodeHeaders
=
false
;
//
发送人邮件地址
MyMail.From
=
FromMail;
//
发送人姓名
MyMail.FromName
=
ShowName;
//
邮件主题
MyMail.Subject
=
Title;
//
身份验证的用户名
MyMail.MailServerUserName
=
MailUserName;
//
用户密码
MyMail.MailServerPassWord
=
MailPassword;
//
邮件内容
MyMail.Body
=
Body;
ArrayList FileNames;
//
如果存在附件
if
(FileNames.Count
>=
1
)
{
//
添加附件
string
Filename;
for
(
int
k
=
0
;k
<
FileNames.Count;k
++
)
{
Filename
=
FileNames[k].ToString();
MyMail.AddAttachment(Filename,
false
,HttpUtility.UrlDecode(Filename.Substring(Filename.LastIndexOf(
"
.
"
)
+
1
,
3
)));
}
}
try
{
//
循环发送
for
(
int
i
=
0
;i
<
Receiver.Length;i
++
)
{
MyMail.AddRecipient(Receiver[i],
""
,
""
);
MyMail.Send(
"
Mail.rshi.cn
"
,
false
);
}
}
catch
(Exception ex)
{
Response.Write(
"
<script language='javascript'>alert('邮件发送失败,请您和ustbwuyi联系(QQ:108556024)!')</script>
"
);
}
}
好了,现在我们来看看接收邮件的问题。一般来说,接收邮件主要分为两部分,一是将接收到的邮件的信息保存到数据库,如邮件的
主题,内容,发送人,发送时间等。其次是对邮件附件的处理,主要将邮件附件从POP服务器上下载下来并保存到数据库,然后将附件
信息保存到数据库,如附件的路径,附件对应的邮件编号等信息。这一点.NET自带的似乎并不太好处理,没有jmail组件处理方便,
当然关于.NET自带的我并没有深入研究,个人经过比较还是推荐jmail,当然前面说过关于jmail几个版本在这方面的差异,所以个人
还是推荐jmail4.4pro版本。下面是收邮件的代码:
public
void
ReceiveMails(
string
Username)
{
jmail.Message Msg
=
new
jmail.Message();
jmail.POP3 jpop
=
new
jmail.POP3();
jmail.Attachments atts;
jmail.Attachment att;
//
username为用户名,该方法通过用户名获取该用户的pop设置,即用户的POP用户名,密码,POP服务器地址以及端口号这四个参数,这四个参数是连接POP服务器的必用参数.
SqlDataReader dataReader
=
this
.ExtGetSetting(Username);
if
(dataReader.Read())
{
if
(dataReader[
"
PopServer
"
].ToString()
!=
""
&&
dataReader[
"
PopUsername
"
].ToString()
!=
""
)
{
//
连接POP服务器
jpop.Connect(dataReader[
"
PopUsername
"
].ToString(),dataReader[
"
PopPassword
"
].ToString(),dataReader[
"
PopServer
"
].ToString(),Int32.Parse(dataReader[
"
PopPort
"
].ToString()));
//
如果服务器上有邮件
if
(jpop.Count
>=
1
)
{
for
(
int
i
=
1
;i
<=
jpop.Count;i
++
)
{
Msg
=
jpop.Messages[i];
atts
=
Msg.Attachments;
//
取数据库中邮件信息中的最大发送时间,即最近接收到的一封邮件的时间
Database dbase
=
new
Database();
DataTable data
=
dbase.GetDataTable(
"
select max(MailSendDate) as MailSenderDate from TabMailList where MailTypeFlag='1'
"
);
//
对服务器上的邮件的发送时间和数据库最近一封邮件的时间进行比较,如果大那么证明该邮件还未被收取,是一封新邮件,这样避免重复收取邮件入库
if
(Msg.Date
>
Convert.ToDateTime(data.Rows[
0
][
0
].ToString()))
{
//
将这封新邮件的信息保存到数据库
this
.SaveExtMail(Msg,Username,dataReader[
"
Email
"
].ToString(),jpop.GetMessageUID(i));
//
获取附件上传到服务器并且将信息存入数据库
if
(atts.Count
>=
1
)
{
for
(
int
k
=
0
;k
<
atts.Count;k
++
)
{
att
=
atts[k];
//
获得附件
string
attname
=
att.Name;
try
{
Random TempNameInt
=
new
Random();
string
NewMailDirName
=
TempNameInt.Next(
100000000
).ToString();
Directory.CreateDirectory(System.Web.HttpContext.Current.Server.MapPath(
"
.
"
)
+
"
//AttachFiles//
"
+
Username
+
"
//
"
+
NewMailDirName);
string
mailPath
=
"
//AttachFiles//
"
+
Username
+
"
//
"
+
NewMailDirName
+
"
//
"
+
attname;
att.SaveToFile(System.Web.HttpContext.Current.Server.MapPath(
"
.
"
)
+
mailPath);
//
获取该封邮件在数据库的ID,以便和附件信息相对应,取邮件表中的最大ID即可
int
mailID
=
this
.GetMailID();
//
将附件信息存入数据库
this
.AttExtSend(mailID,attname,att.Size,mailPath,Msg.From);
}
catch
(Exception ex)
{
throw
new
Exception(ex.Message);
}
}
}
}
}
}
//
删除服务器上的邮件
jpop.DeleteMessages();
//
断开连接
jpop.Disconnect();
}
}
}
至于将邮件信息和附件信息如何存入数据库,就看你自己对表的设计了,我就不多说了,经过上面就可以完全将你POP服务器上的
邮件完全接收到你的本地了。