asp.net 发送邮件代码

详解Asp.Net定时发送邮件方法

用.net发送邮件,总结起来有以下那么三种:
(1)做一个winform 来定时发邮件。然后通过windows计划任务,设置为指定时间,每次自动运行,运行完毕后自动关闭。
(2)用sqlserver 数据库实现发邮件,用sqlserver实现发邮件的存储过程,然后制定一个作业,制定时间运行。
(3)在 Global.asax 文件里编程。事件:Application_Start。利用Time类编程。比如服务器1秒钟执行一次判断。

在编程之前,先介绍一下 Global.asax文件里的几个方法。
  protected void Application_Start(Object sender, EventArgs e)
  {
  //Application_start方法:请求 ASP.NET 应用程序中第一个资源(如页)时调用。在应用程序的生命周期期间仅调用一次
  }
  protected void Application_End(Object sender, EventArgs e)
  {
  //Application_end方法:在卸载应用程序之前对每个应用程序生命周期调用一次。
  }

下面是具体的做法:
  代码
  protected void Application_Start(Object sender, EventArgs e)
  {
  Timer t = new Timer(60000);//设计时间间隔,如果一个小时执行一次就改为3600000 ,这里一分钟调用一次
  t.Elapsed = new ElapsedEventHandler(t_Elapsed);
  t.AutoReset = true;
  t.Enabled = true;
  }
  private void t_Elapsed(object sender, ElapsedEventArgs e)
  {
  if (GetEmailContent.GetMailContent().Length == 0)
  {
  return;//如果没有通过三审的订单要发送,则返回不发送邮件
  }

欢迎进入.NET社区论坛,与200万技术人员互动交流 >>进入
  int sendTime_Hour = Convert.ToInt32(ConfigurationManager.AppSettings["SendTime"].ToString());// 假如是下午17:00分发送
  int now_Hour = Convert.ToInt32(DateTime.Now.Hour.ToString());
  int now_Minute = Convert.ToInt32(DateTime.Now.Minute.ToString());
  int absolute = 1;//差距值,单位为分钟
  if (((now_Hour == sendTime_Hour - 1) && (now_Minute >= 60 - absolute)) || ((now_Hour == sendTime_Hour) && (now_Minute <= absolute))) //即在如果时间判断是落在16:59分至17:01分之间,那么就会调用下面的邮件发送方法
  {
  string subject = string.Format("CO Approve Report({0})", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
  string host = ConfigurationManager.AppSettings["MailHost"];
  string from = ConfigurationManager.AppSettings["MailFrom"];
  string to = ConfigurationManager.AppSettings["MailTo"];
  string user = ConfigurationManager.AppSettings["MailUser"];
  string password = ConfigurationManager.AppSettings["MailPassword"];
  string content = GetEmailContent.GetMailContent();
  try
  {
  OrderMail.Send(host, user, password, to, from, subject, content, null);//发送邮件的方法,改为你自己的邮件发送方法
  }
  catch (Exception ex)
  {
  throw new Exception(ex.Message);
  }
  }
  }
  如果一定要确精到分,可以设置相距时间为秒级,以及设置定时器的时间间隔为秒级,比如一秒调用一次t_Elapsed,但必须符合的一件条件是:定时器的时间间隔<2*absolute,absolute为差距值,见上面黄色背景的定义,具体多少以客户的要求为准,不满足这个条件的话不能实现在规定的时间段内调用邮件发送的方法。

  好,代码编写完毕,测试没问题,下班再设置晚上9点收到邮件(理论值应是8点59至9点1分之间收到),当天发现没收到邮件,问题来了!为什么在上班的测试没问题,但下班后9点没收到邮件?网上查了一下,发觉自己还有个问题没考虑到:Application对象是有生命周期的,当网页没人访问或闲置过久,应用程序池会调用Application_End方法回收applicatioin里的对象资源,导致定时器无法工作。

  解决方法:在IIS6.0以上版本设置IIS应用程序池的回收时间,默认好像是20分钟,可设置长一些,但不要太长,否则有可能出现网站假死的现象。当晚再测试,可以正式发送邮件!起码到现在已经用了两三个月,都能正常定时发送邮件。IIS5.0没有应用程序池,可以在C:/WINDOWS /Microsoft.NET/Framework/v2.0.50727/CONFIG/ machine.config里面设置,具体设置可以参照:http://www.zhiweinet.com/jiaocheng/2008-07 /1145.htm

  还有,对于Applicatioin_Start方法,有很多人都会产生一个误解: Application_Start是第一个人访问网站时加载的,只会调用一次,以后都不会调用;Application_Start是第一个人访问网站时加载的,这个没错,前提是在它的生命周期内,有以下几个原因也会导致应用程序池重新启动, 即Application_Start可以再次被调用:

  1)添加、修改或删除应用程序的 Bin 文件夹中的程序集。
  2)添加、修改或删除 App_GlobalResources 或 App_LocalResources 文件夹中的本地化资源。
  3)添加、修改或删除应用程序的 Global.asax 文件。
  4)添加、修改或删除 App_Code 目录中的源代码文件。
  5)添加、修改或删除配置文件配置。
  6)添加、修改或删除 App_WebReferences 目录中的 Web 服务引用。
  7)添加、修改或删除应用程序的 Web.config 文件。
  附应用程序生命周期概述:http://www.cnblogs.com/adsiz/archive/2008/01/17 /1042746.html

  附.NET垃圾回收机制 :http://blog.csdn.net/lerit/archive/2009/08/16/4451287.aspx
  附SqlServer发送邮件解决方法:http://www.cnblogs.com/yjmyzz/archive/2008/09/04 /1284229.html
  在正常情况下Application_Start只调用一次,这样就不会实例化无数个定时器而占用服务器的资源 ,还有个问题是定时器的时间间隔如果精确到秒级的话是否会占用很多的内存,吃内存是肯定会的,所以要根据具体的情况设置应用程序池的回收时间和加大定时器设定的时间间隔。

  上面定时发送邮件的解决方法只是我个人的做法,可供参考,不见得是最好的方法。QQ邮箱与163邮箱都可以实现发送邮件的功能,大家可否讨论下他们是怎样实现的。

摘自红色黑客联盟(www.7747.net) 原文:http://www.7747.net/kf/201009/73942.html

附:

说到发送邮件发送,先提一下SMTP(呵呵,高手就跳过这一段吧!)。 SMTP的全称是“Simple Mail Transfer Protocol”,即简单邮件传输协议。它是一组用于从源地址到目的地址传输邮件的规范,通过它来控制邮件的中转方式。SMTP 协议属于 TCP/IP 协议簇,它帮助每台计算机在发送或中转信件时找到下一个目的地。SMTP 服务器就是遵循 SMTP 协议的发送邮件服务器。
再简单介绍一下名称空间(NameSpace)System.Web.Mail类库里所提供的邮件发送的对象、属性和方法
(1)它有三个类:SmtpMail、MailMessage和MailAttachment。这三个对象本文的示例程序代码中都应用到了!
1. MailMessage ,提供属性和方法来创建一个邮件消息对象。(Provides properties and methods for constructing an e-mail message.)
2. MailAttachments – 提供属性和方法来创建一个邮件附件对象。(Provides properties and methods for constructing an e-mail attachment.)
3. SmtpMail – 提供属性和方法通过使用windows 2000 CDOSYS 的消息组件的联合数据对象来发送邮件消息)。(Provides properties and methods for sending messages using the Collaboration Data Objects for Windows 2000 (CDOSYS) message component)
(2)各个类的属性。
1.先简单介绍SmtpMail的属性: SmtpServer -- SMTP的地址。
2.主要来介绍MailMessage对象的属性
From -- 发送邮件的地址
To -- 接受邮件的地址
Subject -- 邮件的标题
Priority -- 邮件的优先级(有效值为High,Low,Normal)
Attachments -- 返回一个集合,代表附件
Bcc -- 密送地址
Cc -- 抄送地址
Body -- 获取或是设置电子邮件消息的内容
BodyFormat -- 获取或是设置MailFormat的枚举值,此值指定消息体邮件的格式(Html格式、Text格式)
Bodyencoding -- 指定消息的编码方式编码(主要有Base64,UUencode)
其他几个不重要的省略。 随便提到密送和抄送的区别:密送就是你群发邮件时收邮件的人无法看到你发给了多少人以及他们的邮件地址,抄送就是群发邮件时收邮件的人则可以看到你发给了多少人以及他们的邮件地址。
(3)SmtpMail类的Send方法,它的目的就是发送邮件,有两个重载方法。
1. SmtpMail.Send("发送邮件的地址","接受邮件的地址","邮件的标题","邮件消息的内容") 这个方法很简单,不适合发送带附件的邮件。
2. SmtpMail.Send(MailMessage) 此方法复杂、灵活,适合发送附件,而且可以设置MailMessage对象的各种属性值。 如果我们用ASP.NET写一个邮件发送的程序,那么首先应该如何得到SMTP。有两种方法:第一种方法调用目前知名的邮件服务提供商的SMTP,比如新浪、搜狐、网易的免费电子邮箱的SMTP;第二种方法是自己装一个SMTP虚拟服务器,这个在安装IIS时一起装上去的(安装过程就省略了:-) )。
一、在ASP.NET利用知名的邮件服务提供商的SMTP来发送邮件
首先需要去他们的邮件站点上注册免费邮箱,因为你要使用邮件服务提供商的SMTP,他们需要对身份进行验证,这样可以避免产生大量的垃圾邮件。假设我们在新浪的邮件站点(mail.sina.com.cn)上注册了一个免费电子邮件,用户名是mysina,密码是chenjie.该帐号为虚构的,请使用自己注册的用户名称和密码代替。我们在新浪的邮件站点获知它的SMTP地址是:smtp.sina.com.cn。我们需要向 [email protected](我的邮箱地址)发送邮件。 那么利用ASP.NET(C#)发送邮件的核心代码如下:
//核心代码开始
using System.Web.Mail;
MailMessage objMailMessage;
MailAttachment objMailAttachment;
// 创建一个附件对象
objMailAttachment = new MailAttachment( "d://test.txt" );//发送邮件的附件
// 创建邮件消息
objMailMessage = new MailMessage();
objMailMessage.From = " [email protected]";//源邮件地址
objMailMessage.To = " [email protected]";//目的邮件地址,也就是发给我哈
objMailMessage.Subject = "邮件发送标题:你好";//发送邮件的标题
objMailMessage.Body = "邮件发送标内容:测试一下是否发送成功!";//发送邮件的内容
objMailMessage.Attachments.Add( objMailAttachment );//将附件附加到邮件消息对象中
//接着利用sina的SMTP来发送邮件,需要使用Microsoft .NET Framework SDK v1.1和它以上的版本
//基本权限
objMailMessage.Fields.Add(" http://schemas.microsoft.com/cdo/configuration/smtpauthenticate", "1");
//用户名
objMailMessage.Fields.Add(" http://schemas.microsoft.com/cdo/configuration/sendusername", "mysina") ;
//密码
objMailMessage.Fields.Add(" http://schemas.microsoft.com/cdo/configuration/sendpassword", "chenjie");
/如果没有上述三行代码,则出现如下错误提示:服务器拒绝了一个或多个收件人地址。服务器响应为:554 :Client host rejected: Access denied
//SMTP地址
SmtpMail.SmtpServer = "smtp.sina.com.cn";
//开始发送邮件
SmtpMail.Send( objMailMessage );
//核心代码结束
二、在ASP.NET利用本机的SMTP虚拟服务器的SMTP来发送邮件
首先说一下SMTP配置。
(1)右键点击“SMTP虚拟服务器”选择“属性”->在“常规”选项卡中设置“IP地址(P)”,我设置的是192.168.1.100。
(2)选择“访问”选项卡,点击“中继”,选上“仅以下列表”(默认是被选上的),点击“添加”,在“单台计算机”中加入192.168.1.100。
提示,如果没有完成(2),则会出现大家常见的一种错误提示:服务器拒绝了一个或多个收件人地址。服务器响应为: 550 5.7.1 Unable to relay for [email protected] (友情提示一下:错误中的邮件地址有所不同) 然后开始核心代码,其实和方法(一)的差不多。与(一)的主要区别在于:1.SMTP的不同,2.objMailMessage.From中本方法可以随便填写,但是(一)中别随便填写那么利用ASP.NET(C#)发送邮件的核心代码如下:
/核心代码开始
using System.Web.Mail;
MailMessage objMailMessage;
MailAttachment objMailAttachment;
// 创建一个附件对象
objMailAttachment = new MailAttachment( "d://test.txt" );//发送邮件的附件
// 创建邮件消息
objMailMessage = new MailMessage();
objMailMessage.From = " [email protected]";//源邮件地址
objMailMessage.To = " [email protected]";//目的邮件地址,也就是发给我哈
objMailMessage.Subject = "邮件发送标题:你好";//发送邮件的标题
objMailMessage.Body = "邮件发送标内容:测试一下是否发送成功!";//发送邮件的内容
objMailMessage.Attachments.Add( objMailAttachment );//将附件附加到邮件消息对象中
//SMTP地址
SmtpMail.SmtpServer = "192.168.1.100";
//开始发送邮件
SmtpMail.Send( objMailMessage );
以上两种方法介绍到这里。最简单的利用上面方法是在页面添加一个服务器按钮,把除引用的语句放到按钮单击事件中去。当然,别忘记了引用的语句放在最上面。
方法一的测试是完全正确,没有任何问题,但是方法二却导致邮件无法正确收到( ***@sina.com),或者收到后也被放到垃圾邮件中去了(发往 [email protected])。

附2:

正确配置和使用SQL mail

使用SQL Mail收发和自动处理邮件中的扩展存储过程简介

SQL SERVER提供了通过EXCHANGE或OUTLOOK收发邮件的扩展存储过程,下面将这几个过程简单的介绍一下。

一、启动SQL Mail

xp_startmail
@user,@password

@user和@password都是可选的

也可打开Enterprise Manager中的Support Services,在SQL Mail上单击右键打开右键菜单,然后按Start来启动

二、停止SQL Mail

xp_stopmail

也可用上述方法中的菜单里的Stop来停止

三、发送邮件

xp_sendmail {
[@recipients =] 'recipients [;...n]'}
[,[@message =] 'message>
[,[@query =]
'query>
[,[@attachments =] attachments]
[,[@copy_recipients =] 'copy_recipients [;...n]'
[,[@blind_copy_recipients =] 'blind_copy_recipients [;...n]'
[,[@subject =] 'subject>
[,[@type =]
'type>
[,[@attach_results =] 'attach_value>
[,[@no_output =]
'output_value>
[,[@no_header =] 'header_value>
[,[@width =] width]
[,[@separator =]
'separator>
[,[@echo_error =] 'echo_value>
[,[@set_user =]
'user>
[,[@dbuse =] 'database>

其中@recipients是必需的

参数说明:

参数 说明
@recipients 收件人,中间用逗号分开
@message 要发送的信息
@query 确定执行并依附邮件的有效查询,除触发器中的插入表及删除表外,此查询能引用任何对象
@attachments 附件
@copy_recipients 抄送
@blind_copy_recipients 密送
@subject 标题
@attach_results 指定查询结果做为附件发送
@no_header 不发送查询结果的列名
@set_user 查询联接的用户名,默认为Guset
@dbuse 查询所用的数据库,默认为缺省数据库

四、阅读邮件收件箱中的邮件

xp_readmail [[@msg_id =]
'message_number> [, [@type =] 'type' [OUTPUT]]
[,[@peek =] 'peek>
[,[@suppress_attach =]
'suppress_attach>
[,[@originator =] 'sender' OUTPUT]
[,[@subject =] 'subject' OUTPUT]
[,[@message =] 'message' OUTPUT]
[,[@recipients =] 'recipients [;...n]' OUTPUT]
[,[@cc_list =] 'copy_recipients [;...n]' OUTPUT]
[,[@bcc_list =] 'blind_copy_recipients [;...n]' OUTPUT]
[,[@date_received =] 'date' OUTPUT]
[,[@unread =] 'unread_value' OUTPUT]
[,[@attachments =] 'attachments [;...n]' OUTPUT])
[,[@skip_bytes =] bytes_to_skip OUTPUT]
[,[@msg_length =] length_in_bytes OUTPUT]
[,[@originator_address =] 'sender_address' OUTPUT]]

参数说明:

参数 说明
@originator 发件人
@subject 主题
@message 信息
@recipients 收件人
@skip_tytes 读取邮件信息时跳过的字节数,用于顺序获取邮件信息段。
@msg_length 确定所有信息的长度,通常与@skip_bytes一起处理长信息

五、顺序处理下一个邮件

xp_findnextmsg
[[@msg_id =] 'message_number' [OUTPUT]]
[,[@type =] type]
[,[@unread_only =] 'unread_value> )

六、删除邮件

xp_deletemail {
'message_number'}

如果不指定邮件编号则删除收件箱中的所有邮件

七、自动处理邮件

sp_processmail [[@subject =]
'subject>
[,[@filetype =] 'filetype>
[,[@separator =]
'separator>
[,[@set_user =] 'user>
[,[@dbuse =]
'dbname>






>用户在网上注册后,系统将随机产生的密码发送到用户登记的Email
>用户在论坛的帖子有回复时将内容发送到用户的Email
因为上述过程都是在存储过程中完成的,所以避免了前台程序对参数的传输处理,也不需要再用第三方的组件完成,感觉比较方便。

1.为了使用SQL mail,首先你的服务器上得有SMTP服务,我没有安装win2000 server自带的SMTP,而是用imail6.04的SMTP,感觉比较稳定,功能也比较强。
2.安装一个邮件系统,我安装了outLook 2000,我发现在配置邮件profile时,如果
不安装outLook而是用别的第三方程序,win2k中文server版在控制面板中就找不到“邮件”一项.
3.安装完outlook后再刷新控制面板,就会找到“邮件”一项,双击进行邮件的配置,为配置文件起一个名字(假设为myProfile),以便以后SQL mail使用,在该配置文件中设置各项属性。
4.启动outlook(设置为用myProfile作为默认的配置文件),测试进行收发邮件,确认outlook工作正常。
5.用当前的域帐户启动SQL server,在企业管理器的支持服务中,点击SQL mail的属性,可以看到在配置文件选择中,出现了刚才定义的myProfile配置文件(你也可以定义多个profile),选择这个配置文件进行测试,SQL将返回成功开始和结束一个MAPI会话的信息,如果出现错误或是没有找到邮件配置文件,那一定是你启动SQL server用的帐号有问题
6.现在你就可以在查询分析器中用XP_sendmail这个扩展存储过程发送SQL mail了,格式如下:
xp_sendmail {
[@recipients =] 'recipients [;...n]'}
[,][@message =] 'message>
[,][@query =]
'query>
[,][@attachments =] attachments]
[,][@copy_recipients =] 'copy_recipients [;...n]'
[,][@blind_copy_recipients =] 'blind_copy_recipients [;...n]'
[,][@subject =] 'subject>
[,[@type =]
'type>
[,][@attach_results =] 'attach_value>
[,][@no_output =]
'output_value>
[,][@no_header =] 'header_value>
[,][@width =] width]
[,][@separator =]
'separator>
[,][@echo_error =] 'echo_value>
[,][@set_user =]
'user>
[,][@dbuse =] 'database>

其中@recipients是必需的

参数说明:

参数 说明
@recipients 收件人,中间用逗号分开
@message 要发送的信息
@query 确定执行并依附邮件的有效查询,除触发器中的插入表及删除表外,此查询能引用任何对象
@attachments 附件
@copy_recipients 抄送
@blind_copy_recipients 密送
@subject 标题
@attach_results 指定查询结果做为附件发送
@no_header 不发送查询结果的列名
@set_user 查询联接的用户名,默认为Guset
@dbuse 查询所用的数据库,默认为缺省数据库


7.不过,如果是在web应用中使用SQL mail,还有一些问题要解决:首先,就是应用程序中连接数据库的帐号,我在网站程序中的数据库连接是使用UDL文件,帐号为DbGuest,这是一个普通帐户,所以还必须在master库的扩展存储过程找到XP_sendmail,并在其属性中增加DbGuest这个用户,并选择EXEC权限。
好了,现在设置完毕,运行网站程序,测试用户注册,几乎没有什么延迟,我测试用的邮箱中就收到了这封SQL mail发出的Email:
"谢谢你的注册,建议你首次登录后修改密码"


你可能感兴趣的:(asp.net)