|
|
Posted on 2007-05-28 15:29 慕容一刀 阅读(3034) 评论(19) 编辑 收藏 所属分类: ASP.NET其它知识
最近因为项目需要,研究了一下邮件的发送和接收,发现现在这方面的问题很多.虽然网上这方面的资料很多,但是真正应用起来 仍然会发现不少问题,而且很多人都抱怨书上或者网上的一些代码应用起来是失败的,并且针对附件方面的处理不太完善,针对这种情况我把最近研究所得做一个小小的总结,希望能对大家有所帮助。 首先来谈谈发送邮件的问题。
发送邮件现在应用得最多的两种情况就是利用.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服务器上的 邮件完全接收到你的本地了。
Feedback
SqlDataReader sdr;
jmail.MessageClass theMail = new MessageClass();//建立发邮件类
if(sdr.Read())
{
theMail.From ="hr33@sina.com"; //发送人邮件地址
theMail.FromName ="中国热线"; //发送人姓名
theMail.Subject = sdr["tosubject"].ToString(); // 邮件主题
theMail.MailServerUserName = "hr33dotcom@sina.com"; //身份验证的用户名
theMail.MailServerPassWord = "hr33dotcom4545"; //用户密码
string mailadd=sdr["touseradd"].ToString(); //收邮人信息
string tousername=sdr["tousername"].ToString();
//邮件内容
theMail.Body="***********";
theMail.AddRecipient(mailadd,tousername,"");
if(theMail.Send("smtp.sina.com",false)) //在这儿出错了 提示在下面
{
if(theDb.execNone("update SendMail set issend=1,sendtime='"+System.DateTime.Now+"' where touseradd='"+touseradd+"'")>0)
{
ErrorList.Add(MailList[i].ToString()+"邮件发送成功!");
}
else
{
ErrorList.Add(MailList[i].ToString()+"邮件发送成功!记录数据更新失败!");
}
}
else
{
ErrorList.Add(MailList[i].ToString()+"邮件发送失败!");
}
theMail = null;
========================================
邮件群发,发不出去`````` 帮我看看啊
if(theMail.Send("smtp.sina.com",false)) //在这儿出错了 提示在下面
未处理的“System.Runtime.InteropServices.COMException”类型的异常出现在 win_sendmail.exe 中。
其他信息: The message was undeliverable. All servers failed to receive the message
我的邮箱
colvinliu@qq.conm 多谢了啊
vs2005版System.Net.Mail.MailMessage似乎比2003的区别太大了,我试了几次还是发送失败,是不是iis配置问题?待回答.............
不是代码的问题,其实在05下用System.Web.Mail也是一样的,把03下的代码移植过去即可,如果你在03下能成功而05不行的话没理由是IIS的问题
群发肯定要有自己的邮件服务器,现在像sina这样的邮件服务商都有很严格的垃圾邮件过滤规则,每封信的时间间隔都有规定,群发肯定是不行的啦,要不这么容易让你群发,sina还能做邮件这一块吗?
正在研究,可不呵以发一份完整的代码,谢了~~
shanxinran@126.com
关注。。我也正在做这一块。不过我现在的问题是。邮件上传图片后显示出来。发送出去。 有在做这块的朋友。请发邮件给我。
zhaoxiaoyang5156@qq.com
挺好的,楼主能发份完整的代码给我学习一下吗,共勉!
jiyun@cn-site.com
我用.net发送邮件时
我发现它可以发送到新浪已经网易的vip邮箱中
但是雅虎的邮箱就接受不到信息
我也再网上查了一下
而且雅虎邮箱好像不能免费接受pop的邮件
我想请教一下有没有别的方法
可以让程序方式的邮件什么邮箱都能够接受到
谢谢勒啊
to 楼上:
这个是没有影响的,你必须弄清楚.net发邮件的原理,它仍然是通过邮件服务器来发送的,和直接在邮件服务器下发送没有区别,实际上雅虎邮箱可以收到的,我测试过多次,只是用jmail接收yahoo邮件的时候有乱码问题,因为yahoo的编码方式不一致,需要自己进行解码
求解:
jmail发送成功,但为什么收不到邮件(都是163邮箱的) ?
楼主 我现在也在做这方面的东西 有些方面还是不明白 能给我一份完整的代码看看吗?
zengzhi026@126.com谢谢 了
不需要设置主机名吗??
你去哪验证用户信息?????
我用jmail接收邮件大于50K就死机,卡在那里,也不报错?不知道什么问题,我想问一下jmail组建如何设置超时,我为什么没找到类似的方法或属性?
我到网上找了很多发邮件的代码,但是每个都报错,而且出现的错误是乱码,抛出“调用的目标发生了异常。”这个异常。
我没写过发邮件的代码,也不知道怎么修改这个错误。
哦,我用的是vs2008
|