asp.net基于windows服务实现定时发送邮件的方法
程序员文章站
2023-12-21 11:14:46
本文实例讲述了asp.net基于windows服务实现定时发送邮件的方法。分享给大家供大家参考,具体如下:
//定义组件
private system.time...
本文实例讲述了asp.net基于windows服务实现定时发送邮件的方法。分享给大家供大家参考,具体如下:
//定义组件 private system.timers.timer time; public int nowhour; public int minutes; public string sendtime; public thread th; public string isopen;//是否启用定时发送 public string strtoeuser; public static int index = -1; public static arraylist mulitaddress; //服务开始 protected override void onstart(string[] args) { time = new system.timers.timer(); time.enabled = true; time.autoreset = true; //定时执行方法 time.elapsed+=new system.timers.elapsedeventhandler(time_elapsed); useremail touser =new useremail(); mulitaddress = getmailadressname(); // loghelper.savenote("当前索引的值" + index.tostring()); thread.sleep(2000); time.start(); } public class loghelper { public static void savenote(string note) { filestream stream = new filestream(getlogdirectory("common") + datetime.now.tostring("yyyy-mm-dd") + ".txt", filemode.append, fileaccess.write, fileshare.delete | fileshare.readwrite); streamwriter writer = new streamwriter(stream, encoding.utf8); writer.writeline("================================================================"); writer.writeline(string.format("note:/t{0}", note)); writer.writeline(string.format("datetime:/t{0}/r/n/r/n",datetime.now.tostring())); stream.flush(); writer.close(); stream.close(); stream.dispose(); writer.dispose(); } public static void savenote(string note, string txtname) { filestream stream = new filestream(getlogdirectory(txtname) + datetime.now.tostring("yyyy-mm-dd") + ".txt", filemode.append, fileaccess.write, fileshare.delete | fileshare.readwrite); streamwriter writer = new streamwriter(stream, encoding.getencoding("gb2312")); writer.writeline("================================================================"); writer.writeline(string.format("note:/t{0}", note)); writer.writeline(string.format("datetime:/t{0}/r/n/r/n", datetime.now.tostring("yyyymmddhhmmss"))); stream.flush(); writer.close(); stream.close(); stream.dispose(); writer.dispose(); } public static void saveexception(exception e) { saveexception(e, string.empty); } public static void saveexception(exception e, string memo) { filestream stream = new filestream(getlogdirectory("common") + datetime.now.tostring("yyyy-mm-dd") + ".txt", filemode.append, fileaccess.write, fileshare.delete | fileshare.readwrite); streamwriter writer = new streamwriter(stream); writer.writeline("================================================================"); writer.writeline(string.format("memo:/t{0}", memo)); writer.writeline(string.format("datetime:/t{0}", datetime.now.toshorttimestring())); writer.writeline(string.format("message:/t{0}", e.message)); writer.writeline(string.format("stacktrace:/r/n----------/r/n{0}/r/n----------/r/n/r/n/r/n", e.stacktrace)); stream.flush(); writer.close(); stream.close(); stream.dispose(); writer.dispose(); } public static string getlogdirectory(string category) { string basedirectory = string.empty; if ((httpcontext.current != null) && (httpcontext.current.server != null)) { basedirectory = httpcontext.current.server.mappath("~"); } else { basedirectory = appdomain.currentdomain.basedirectory; } if ((basedirectory[basedirectory.length - 1] != '/') && (basedirectory[basedirectory.length - 1] != '//')) { basedirectory = basedirectory + @"/"; } basedirectory = string.format(@"{0}log/{1}/", basedirectory, category); if (!directory.exists(basedirectory)) { directory.createdirectory(basedirectory); } return basedirectory; } } void time_elapsed(object sender, system.timers.elapsedeventargs e) { try { if (mulitaddress != null) { loghelper.savenote("进入time_elapsed"); //获取定时发送时间 sendtime = convert.tostring(getconfigvalue("sendtime")); loghelper.savenote("sendtime" + sendtime); //是否开启定时发送功能 isopen = getconfigvalue("isopen"); int sleeptime = convert.toint32(getconfigvalue("sleeptime")); int stoptime = convert.toint32(getconfigvalue("stoptime")); //loghelper.savenote("数组长度" + mulitaddress.count); // loghelper.savenote("是否开启定时发送功能" + isopen + "定时时间" + sendtime + "定时小时数:" + convert.toint32(sendtime.split(new char[] { ':' })[0]) + "定时分钟数:" + convert.toint32(sendtime.split(new char[] { ':' })[1])); if (isopen == "true") { //现在时间 小时 nowhour = convert.toint32(datetime.now.hour.tostring());//10 //现在分钟 minutes = convert.toint32(datetime.now.minute.tostring());//5 //获取发送小时 int sendhour = convert.toint32(sendtime.split(new char[] { ':' })[0]); //获取发送的分钟 int sendminute = convert.toint32(sendtime.split(new char[] { ':' })[1]); loghelper.savenote("进入定时发送邮件服务! 定时小时为:" + sendhour.tostring() + "定时分钟为:" + sendminute.tostring() + "现在小时为:" + nowhour.tostring() + "现在定时的分钟为:" + minutes.tostring()); loghelper.savenote("当前索引的值" + index.tostring()); if (nowhour == stoptime) { loghelper.savenote("停止时间点到了 邮件停止发送 !!!"); index = -1; } else { //如果和当前的时间 小时相等 则定时发送邮件 if ((convert.todatetime(datetime.now.toshorttimestring()) >= convert.todatetime(sendtime)) && index < mulitaddress.count) { index++; if (index < mulitaddress.count) { sendemail(((useremail)mulitaddress[index])); } else { loghelper.savenote("发送完毕 当前的索引值为" + index.tostring()); } } } } else { //loghelper.savenote("当前索引的值" + index.tostring()); index++; if (index < mulitaddress.count) { sendemail(((useremail)mulitaddress[index])); } else { loghelper.savenote("发送完毕 时间停止"); time.enabled = false; time.stop(); } } thread.sleep(sleeptime); } else loghelper.savenote("mulitaddress=null"); } catch (exception ex) { loghelper.savenote(ex.tostring()); } } public arraylist getmailadressname() { arraylist list = new arraylist(); string strsql = "select b.mailaddress, a.mailtemplate,a.title from tg_product as a inner join tg_mailorder as b on a.ccode=b.ccode where a.createtime=(select max(createtime) from tg_product)"; sqldatareader dr = sqlhelper.executereader(commandtype.text, strsql, null); if (dr.hasrows) { while (dr.read()) { useremail email = new useremail(); email.mailaddres = dr["mailaddress"].tostring(); email.title = dr["title"].tostring(); email.contents = dr["mailtemplate"].tostring(); list.add(email); } } return list; } /// <summary> /// 定义用户邮件 标题 内容 email地址 /// </summary> public class useremail { private string title; private string contents; public string contents { get { return contents; } set { contents = value; } } private string mailaddres; public string mailaddres { get { return mailaddres; } set { mailaddres = value; } } public string title { get{return title;} set { title = value; } } } #region 发送邮件 /// <summary> /// 发送邮件 /// </summary> public void sendemail(useremail user) { try { loghelper.savenote("进入sendemail!!!"); //邮件服务器 string smtpserver = getconfigvalue("smtpserver"); //发件人的邮箱名称 string emailusername = getconfigvalue("emailusername"); //发件人的邮箱密码 string emailuserpwd = getconfigvalue("emailuserpwd"); //邮箱地址 string emailfrom = getconfigvalue("emailfrom"); int port = convert.toint32(getconfigvalue("serverport")); bool f = true; //是否经过ssl加密 string isssl = getconfigvalue("ssl"); if (isssl == "true") { f = true; } else { f = false; } loghelper.savenote("发件人的邮箱名称" + emailusername + "邮件地址(emailfrom)" + emailfrom + "收件人" + user.mailaddres); sendemailtouser(smtpserver, port, f, user.mailaddres, null, emailusername, emailuserpwd, emailfrom, user.title,user.contents); loghelper.savenote("send mail success"); } //获取异常信息 catch (exception error) { //写入异常信息 using (streamwriter sw = new streamwriter("f://mailerrorlog.txt", true, system.text.encoding.utf8)) { sw.writeline(datetime.now.tostring() + ":"); sw.writeline("exception 异常信息如下................."); sw.writeline(error.tostring()); sw.writeline("---------------------------------------------"); sw.close(); } } } #endregion #region 利用.net自带类(smtpclient) 发送邮件 /// <summary> /// 利用.net自带类(smtpclient) 发送邮件 /// </summary> /// <param name="stmpserver">邮件服务器</param> /// <param name="username">用户名(邮箱名称)</param> /// <param name="pwd">密码</param> /// <param name="f">是否经过ssl加密</param> /// <param name="port">邮件服务器端口(没有加密 一般都是25)</param> /// <param name="strfrom">发件人</param> /// <param name="strto">收件人</param> /// <param name="subject">主题</param> /// <param name="body">内容</param> /// <param name="mulitaddress">发送多人 收件人的邮箱地址以逗号隔开</param> /// <param name="attachmentname">发送的附件名称 没有附件则为null or ""</param> public void sendemailtouser(string stmpserver,int port,bool f, string mulitaddress, string attachmentname, string username, string pwd, string strfrom, string subject, string body) { string errorlog = getconfigvalue("errorlog"); smtpclient smtp = new smtpclient(); //发送邮件的方式 smtp.deliverymethod = smtpdeliverymethod.network; //指定邮件服务器 smtp.host = stmpserver; //gmail qq stmp ssl加密使用的端口 smtp.port = port; smtp.enablessl = f; ;//true 经过ssl加密 //验证发件人的身份 用户名(邮件地址和密码) smtp.credentials = new system.net.networkcredential(username, pwd); //初始化信息(来自 接收人) mailmessage _mailmessage = new mailmessage(); //_mailmessage.to = strto; //发送多个人 接收人邮件地址以,隔开 _mailmessage.from = new mailaddress(strfrom); _mailmessage.to.add(mulitaddress); //如果发送失败,smtp 服务器将发送 失败邮件通知 _mailmessage.deliverynotificationoptions = deliverynotificationoptions.onfailure; //优先级 _mailmessage.priority = mailpriority.high; //发送主题 _mailmessage.subject = subject; //有附件则添加附件 if (!string.isnullorempty(attachmentname)) { system.net.mail.attachment attch = new system.net.mail.attachment(attachmentname); _mailmessage.attachments.add(attch); } //邮件主题编码 _mailmessage.subjectencoding = system.text.encoding.utf8; //指定发送的格式 (html) _mailmessage.isbodyhtml = true; //指定发送邮件的编码 _mailmessage.bodyencoding = system.text.encoding.utf8; //指定邮件内容 _mailmessage.body = body; //发送邮件 try { smtp.send(_mailmessage); } catch (exception ex) { using (streamwriter writer = new streamwriter(errorlog+"://mailerrorlog.txt", true, system.text.encoding.utf8)) { writer.writeline("---------------------------------------------"); writer.writeline("sendemail方法发送邮件错误日志................"); writer.writeline(ex.tostring()); writer.flush(); writer.close(); } } } #endregion #region 获取邮件配置节点的值 /// <summary> /// 加载相应配置文件 并按节点名称获取对应的值 /// </summary> /// <param name="target">当前节点的名称</param> /// <returns>返回当前节点名称所对应的值</returns> public string getconfigvalue(string target) { string configpath=system.windows.forms.application.startuppath.tostring() + "/email.config"; return getconfigvalue(configpath, target); } /// <summary> /// 根据节点名称获取配置文件对应的值(邮件配置信息) /// </summary> /// <param name="configpath">配置文件路径</param> /// <param name="target">要获取配置节点的名称</param> /// <returns>返回当前节点名称所对应的值</returns> public string getconfigvalue(string configpath, string target) { xmldocument doc = new xmldocument(); //加载文件路径s doc.load(configpath); //获取当前节点的根节点 xmlelement root = doc.documentelement; //获取当前节点下所有匹配子节点元素 xmlnodelist xmlnode = root.getelementsbytagname(target); //返回值 return xmlnode[0].innerxml; } #endregion //服务结束 protected override void onstop() { time.enabled = false; }
email.config如下:
<?xml version="1.0" encoding="utf-8"?> <emailconfig> <!--邮件服务器地址 gmail stmp.gmail.com--> <smtpserver>*****</smtpserver> <!--邮箱用户名 --> <emailusername>***</emailusername> <!--邮箱密码--> <emailuserpwd>****</emailuserpwd> <!--邮箱地址--> <emailfrom>*****</emailfrom> <!--是否启用定时发送邮件功能--> <isopen>true</isopen> <!--前提下isopen为true 定在每天某个时间点发送邮件--> <sendtime>8:53</sendtime> <!--是否经过ssl加密--> <ssl>false</ssl> <!--gmail smtp ssl加密 (gmail:587) 服务器端口(没有加密(ssl 配置为false) 一般都是25 (163,qq))--> <serverport>25</serverport> <!--线程睡眠时间--> <sleeptime>1000</sleeptime> <!--定停发送时间--> <stoptime>0</stoptime> <!--发送邮件错误日志路径 盘根目录--> <errorlog>e</errorlog> <!--定义数据库连接字符串--> <connstr></connstr> </emailconfig>
sqlhelper如下:
#region 数据库操作类的封装 public abstract class sqlhelper { //database connection strings public static readonly string connectionstringlocaltransaction = connstr; // hashtable to store cached parameters private static hashtable parmcache = hashtable.synchronized(new hashtable()); /*返回数据库连接*/ public static sqlconnection getconnection() { sqlconnection c = new sqlconnection(connectionstringlocaltransaction); return c; } /// <summary> /// execute a sqlcommand that returns a resultset against the database specified in the connection string /// using the provided parameters. /// </summary> /// <remarks> /// e.g.: /// sqldatareader r = executereader(connstring, commandtype.storedprocedure, "publishorders", new sqlparameter("@prodid", 24)); /// </remarks> /// <param name="connectionstring">a valid connection string for a sqlconnection</param> /// <param name="commandtype">the commandtype (stored procedure, text, etc.)</param> /// <param name="commandtext">the stored procedure name or t-sql command</param> /// <param name="commandparameters">an array of sqlparamters used to execute the command</param> /// <returns>a sqldatareader containing the results</returns> public static sqldatareader executereader(string connectionstring, commandtype cmdtype, string cmdtext, params sqlparameter[] commandparameters) { sqlcommand cmd = new sqlcommand(); sqlconnection conn = new sqlconnection(connectionstring); // we use a try/catch here because if the method throws an exception we want to // close the connection throw code, because no datareader will exist, hence the // commandbehaviour.closeconnection will not work try { preparecommand(cmd, conn, null, cmdtype, cmdtext, commandparameters); sqldatareader rdr = cmd.executereader(commandbehavior.closeconnection); cmd.parameters.clear(); return rdr; } catch { conn.close(); throw; } } public static dataset returndataset(commandtype cmdtype, string cmdtext, params sqlparameter[] commandparameters) { sqlcommand cmd = new sqlcommand(); sqlconnection conn = new sqlconnection(connectionstringlocaltransaction); // we use a try/catch here because if the method throws an exception we want to // close the connection throw code, because no datareader will exist, hence the // commandbehaviour.closeconnection will not work try { preparecommand(cmd, conn, null, cmdtype, cmdtext, commandparameters); dataset ds = new dataset(); sqldataadapter sda = new sqldataadapter(cmd); sda.fill(ds); return ds; } catch { conn.close(); throw; } } /// <summary> /// execute a sqlcommand that returns a resultset against the database specified in the connection string /// using the provided parameters. /// </summary> /// <remarks> /// e.g.: /// sqldatareader r = executereader(sqlconnection, commandtype.storedprocedure, "publishorders", new sqlparameter("@prodid", 24)); /// </remarks> /// <param name="connectionstring">a valid connection string for a sqlconnection</param> /// <param name="commandtype">the commandtype (stored procedure, text, etc.)</param> /// <param name="commandtext">the stored procedure name or t-sql command</param> /// <param name="commandparameters">an array of sqlparamters used to execute the command</param> /// <returns>a sqldatareader containing the results</returns> public static sqldatareader executereader(sqlconnection conn, commandtype cmdtype, string cmdtext, params sqlparameter[] commandparameters) { sqlcommand cmd = new sqlcommand(); // we use a try/catch here because if the method throws an exception we want to // close the connection throw code, because no datareader will exist, hence the // commandbehaviour.closeconnection will not work try { preparecommand(cmd, conn, null, cmdtype, cmdtext, commandparameters); sqldatareader rdr = cmd.executereader(commandbehavior.closeconnection); cmd.parameters.clear(); return rdr; } catch { conn.close(); throw; } } /// <summary> /// execute a sqlcommand that returns a resultset against the database specified in the connection string /// using the provided parameters. /// </summary> /// <remarks> /// e.g.: /// sqldatareader r = executereader(connstring, commandtype.storedprocedure, "publishorders", new sqlparameter("@prodid", 24)); /// </remarks> /// <param name="connectionstring">a valid connection string for a sqlconnection</param> /// <param name="commandtype">the commandtype (stored procedure, text, etc.)</param> /// <param name="commandtext">the stored procedure name or t-sql command</param> /// <param name="commandparameters">an array of sqlparamters used to execute the command</param> /// <returns>a sqldatareader containing the results</returns> public static sqldatareader executereader(commandtype cmdtype, string cmdtext, params sqlparameter[] commandparameters) { sqlcommand cmd = new sqlcommand(); sqlconnection conn = new sqlconnection(connectionstringlocaltransaction); // we use a try/catch here because if the method throws an exception we want to // close the connection throw code, because no datareader will exist, hence the // commandbehaviour.closeconnection will not work try { preparecommand(cmd, conn, null, cmdtype, cmdtext, commandparameters); sqldatareader rdr = cmd.executereader(commandbehavior.closeconnection); cmd.parameters.clear(); return rdr; } catch { conn.close(); throw; } } /// <summary> /// add parameter array to the cache /// </summary> /// <param name="cachekey">key to the parameter cache</param> /// <param name="cmdparms">an array of sqlparamters to be cached</param> public static void cacheparameters(string cachekey, params sqlparameter[] commandparameters) { parmcache[cachekey] = commandparameters; } /// <summary> /// retrieve cached parameters /// </summary> /// <param name="cachekey">key used to lookup parameters</param> /// <returns>cached sqlparamters array</returns> public static sqlparameter[] getcachedparameters(string cachekey) { sqlparameter[] cachedparms = (sqlparameter[])parmcache[cachekey]; if (cachedparms == null) return null; sqlparameter[] clonedparms = new sqlparameter[cachedparms.length]; for (int i = 0, j = cachedparms.length; i < j; i++) clonedparms[i] = (sqlparameter)((icloneable)cachedparms[i]).clone(); return clonedparms; } /// <summary> /// prepare a command for execution /// </summary> /// <param name="cmd">sqlcommand object</param> /// <param name="conn">sqlconnection object</param> /// <param name="trans">sqltransaction object</param> /// <param name="cmdtype">cmd type e.g. stored procedure or text</param> /// <param name="cmdtext">command text, e.g. select * from products</param> /// <param name="cmdparms">sqlparameters to use in the command</param> private static void preparecommand(sqlcommand cmd, sqlconnection conn, sqltransaction trans, commandtype cmdtype, string cmdtext, sqlparameter[] cmdparms) { if (conn.state != connectionstate.open) conn.open(); cmd.connection = conn; cmd.commandtext = cmdtext; if (trans != null) cmd.transaction = trans; cmd.commandtype = cmdtype; if (cmdparms != null) { foreach (sqlparameter parm in cmdparms) cmd.parameters.add(parm); } } /// <summary> /// 传入输入参数 /// </summary> /// <param name="paramname">存储过程名称</param> /// <param name="dbtype">参数类型</param></param> /// <param name="size">参数大小</param> /// <param name="value">参数值</param> /// <returns>新的 parameter 对象</returns> public static sqlparameter makeinparam(string paramname, sqldbtype dbtype, int size, object value) { return makeparam(paramname, dbtype, size, parameterdirection.input, value); } public void makeinparam(ref string oldstring, string paramname, sqldbtype dbtype, int size, object value) { oldstring = oldstring.replace(paramname, (string)value); } /// <summary> /// 传入返回值参数 /// </summary> /// <param name="paramname">存储过程名称</param> /// <param name="dbtype">参数类型</param> /// <param name="size">参数大小</param> /// <returns>新的 parameter 对象</returns> public static sqlparameter makeoutparam(string paramname, sqldbtype dbtype, int size) { return makeparam(paramname, dbtype, size, parameterdirection.output, null); } /// <summary> /// 传入返回值参数 /// </summary> /// <param name="paramname">存储过程名称</param> /// <param name="dbtype">参数类型</param> /// <param name="size">参数大小</param> /// <returns>新的 parameter 对象</returns> public static sqlparameter makereturnparam(string paramname, sqldbtype dbtype, int size) { return makeparam(paramname, dbtype, size, parameterdirection.returnvalue, null); } /// <summary> /// 生成存储过程参数 /// </summary> /// <param name="paramname">存储过程名称</param> /// <param name="dbtype">参数类型</param> /// <param name="size">参数大小</param> /// <param name="direction">参数方向</param> /// <param name="value">参数值</param> /// <returns>新的 parameter 对象</returns> public static sqlparameter makeparam(string paramname, sqldbtype dbtype, int32 size, parameterdirection direction, object value) { sqlparameter param; if (size > 0) param = new sqlparameter(paramname, dbtype, size); else param = new sqlparameter(paramname, dbtype); param.direction = direction; if (!(direction == parameterdirection.output && value == null)) param.value = value; return param; } /// <summary> /// 创建 sqlcommand 对象实例(用来返回一个整数值) /// </summary> /// <param name="storedprocname">存储过程名</param> /// <param name="parameters">存储过程参数</param> /// <returns>sqlcommand 对象实例</returns> private static sqlcommand buildintcommand(sqlconnection connection, string storedprocname, idataparameter[] parameters) { sqlcommand command = buildquerycommand(connection, storedprocname, parameters); command.parameters.add(new sqlparameter("returnvalue", sqldbtype.int, 4, parameterdirection.returnvalue, false, 0, 0, string.empty, datarowversion.default, null)); return command; } /// <summary> /// 构建 sqlcommand 对象(用来返回一个结果集,而不是一个整数值) /// </summary> /// <param name="connection">数据库连接</param> /// <param name="storedprocname">存储过程名</param> /// <param name="parameters">存储过程参数</param> /// <returns>sqlcommand</returns> private static sqlcommand buildquerycommand(sqlconnection connection, string storedprocname, idataparameter[] parameters) { sqlcommand command = new sqlcommand(storedprocname, connection); command.commandtype = commandtype.storedprocedure; foreach (sqlparameter parameter in parameters) { command.parameters.add(parameter); } return command; } #region 执行查询语句 返回dataset /// <summary> /// 执行查询语句,返回dataset /// </summary> /// <param name="cmdtext">查询语句</param> /// <returns>dataset</returns> public static dataset getdataset(string cmdtext) { using (sqlconnection conn = new sqlconnection(connectionstringlocaltransaction)) { sqlcommand sqlcmd = new sqlcommand(cmdtext, conn); sqlcmd.commandtimeout = 1000; sqldataadapter cmd = new sqldataadapter(sqlcmd); dataset ds = new dataset(); try { conn.open(); cmd.fill(ds, "mydt"); return ds; } catch (exception ex) { conn.close(); cmd.dispose(); conn.dispose(); throw new exception(ex.message); } finally { cmd.dispose(); conn.close(); conn.dispose(); } } } #endregion } #endregion
将c:/windows/microsoft.net/framework/v2.0.50727/installutil.exe 拷贝到执行的目录bin debug文件下 然后注册windows服务
复制代码 代码如下:
installutil.exe windowservice.exe
卸载windows服务:
复制代码 代码如下:
installutil.exe -u windowservice.exe
希望本文所述对大家asp.net程序设计有所帮助。