.NET实现定时发送邮件代码(两种方式)

下面是“.NET实现定时发送邮件代码”攻略的详细讲解。

一、前言

邮件是现代人与人之间联系的重要方式之一,而定时发送邮件则可以让我们更加优雅的处理邮件,不用担心自己在某些时间段错过了发送重要邮件的时机。本文将演示两种.NET中定时发送邮件代码的实现方式,供参考。

二、第一种方式:使用System.Threading.Timer类

2.1 实现原理

使用System.Threading.Timer类,在指定的时间间隔内执行指定的代码,我们可以在定时器的回调函数中调用.Net自带的SMTP类库实现发送邮件的操作。

2.2 操作步骤

具体来说,下面是这种方式的操作步骤:

  1. 首先,我们需要创建一个回调函数,该函数接收一个object类型的参数用于定时回调时传入数据,返回void(不需要有返回值),在回调函数中我们可以执行发送邮件的代码。

举个例子,下面是一个简单的回调函数,在定时时间到达的时候输出一段文本:

private static void SendEmail(object state)
{
    Console.WriteLine("定时任务 - 发送邮件");
}
  1. 接下来,我们需要设置定时器,即在程序启动时启动一个定时器,使之在指定的时间间隔后回调我们的回调函数,并执行发送邮件的操作。

我们可以在Console应用或者Web应用的启动函数中放置启动定时器的代码:

using System.Threading;

class Program
{
    private static Timer timer;

    static void Main(string[] args)
    {
        timer = new Timer(SendEmail, null, 0, 10000);  // 设置定时器,在10s后启动一次,每10s执行一次
    }
}

在上述代码中,我们创建了一个名为timer的静态变量来存储我们的定时器实例,然后在Main函数中初始化该实例,并指定定时器的回调函数为SendEmail,以及指定callback参数为null,因为我们的回调函数不需要传入额外的数据。

此外,在定时器实例的构造函数中,我们还指定了两个时间延迟参数,第一个参数表示初始化后多少秒之后启动定时器,这里我们设置为0,表示程序启动后即刻启动。第二个参数表示定时器多久后执行一次回调函数,以毫秒为单位,这里我们设置为10000,表示每10s执行一次回调函数。

  1. 最后,在我们的回调函数SendEmail中,我们可以调用.Net自带的SMTP类库实现发送邮件的操作。
private static void SendEmail(object state)
{
    var msg = new MailMessage();
    msg.From = new MailAddress("from@example.com", "From Example");
    msg.To.Add(new MailAddress("to@example.com"));
    msg.Subject = "Test Email";
    msg.Body = "This is a test email.";

    var client = new SmtpClient("smtp.example.com", 25);
    client.EnableSsl = true;
    client.DeliveryMethod = SmtpDeliveryMethod.Network;
    client.UseDefaultCredentials = false;
    client.Credentials = new NetworkCredential("from@example.com", "password");
    client.Send(msg);

    Console.WriteLine("定时任务 - 发送邮件");
}

在上述代码中,我们创建了一个MailMessage实例,指定了发件人、收件人、主题和内容等信息。然后我们创建了一个SmtpClient实例,指定了SMTP服务器的地址和端口,以及SMTP认证的邮箱和密码等信息。最后调用client对象的Send方法发送邮件。

2.3 示例说明

下面是一个完整的示例代码,该代码演示了在网站启动时设置一个定时器,在每隔10s后执行SendEmail函数,该函数实现了发送一封测试邮件的操作:

using System;
using System.Net;
using System.Net.Mail;
using System.Threading;

namespace EmailSender
{
    class Program
    {
        private static Timer timer;

        static void Main(string[] args)
        {
            Console.WriteLine("Email Sender - Service Started...");

            // 启动定时器
            timer = new Timer(SendEmail, null, 0, 10000);

            Console.ReadLine();
        }

        private static void SendEmail(object state)
        {
            var msg = new MailMessage();
            msg.From = new MailAddress("from@example.com", "From Example");
            msg.To.Add(new MailAddress("to@example.com"));
            msg.Subject = "Test Email";
            msg.Body = "This is a test email.";

            var client = new SmtpClient("smtp.example.com", 25);
            client.EnableSsl = true;
            client.DeliveryMethod = SmtpDeliveryMethod.Network;
            client.UseDefaultCredentials = false;
            client.Credentials = new NetworkCredential("from@example.com", "password");
            client.Send(msg);

            Console.WriteLine("定时任务 - 发送邮件");
        }
    }
}

需要注意的是,上述代码中的SMTP服务器地址、发件人邮箱、发件人密码、收件人邮箱等都需要根据自己的情况进行修改。

三、第二种方式:使用Quartz.NET框架

3.1 实现原理

Quartz.NET是一个成熟的开源任务调度框架,可以满足比System.Threading.Timer更多样化的定时任务需求,且支持多种类型的任务调度,比如Cron表达式等。

使用Quartz.NET框架,我们可以编写一个任务类并在其中实现发送邮件的逻辑,然后在Quartz.NET的配置文件中指定我们的任务类和其执行时间。

3.2 操作步骤

具体来说,下面是这种方式的操作步骤:

  1. 首先,我们需要引入Quartz.NET框架,可以通过NuGet包管理器进行安装。

  2. 接下来,我们创建一个继承自IJob接口的任务类,并实现Execute方法,在其中编写发送邮件的逻辑。需要注意,该方法应该是一个无返回值的异步方法(async void),这是为了让Quartz.NET框架正确地管理任务状态。

这里再举一个例子,发送邮件的逻辑与之前相同,但是我们需要将其封装到一个可复用的任务类中:

using System.Net;
using System.Net.Mail;
using Quartz;

namespace EmailSender
{
    public class EmailJob : IJob
    {
        public async Task Execute(IJobExecutionContext context)
        {
            var msg = new MailMessage();
            msg.From = new MailAddress("from@example.com", "From Example");
            msg.To.Add(new MailAddress("to@example.com"));
            msg.Subject = "Test Email";
            msg.Body = "This is a test email.";

            var client = new SmtpClient("smtp.example.com", 25);
            client.EnableSsl = true;
            client.DeliveryMethod = SmtpDeliveryMethod.Network;
            client.UseDefaultCredentials = false;
            client.Credentials = new NetworkCredential("from@example.com", "password");
            await client.SendMailAsync(msg);
        }
    }
}

在上述代码中,我们定义了一个名为EmailJob的任务类,并实现了IJob接口的Execute方法,在其中编写发送邮件的逻辑。

  1. 然后,在我们的程序启动函数中,我们需要通过Quartz.NET的配置文件(通常为App.config或Web.config)来指定我们的任务类和其执行时间。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="quartz"
             type="Quartz.Impl.StdSchedulerFactory, Quartz" />
  </configSections>

  <quartz>
    <add key="quartz.scheduler.instanceName" value="ExampleScheduler" />
    <add key="quartz.threadPool.type" value="Quartz.Simpl.SimpleThreadPool, Quartz" />
    <add key="quartz.threadPool.threadCount" value="3" />
    <add key="quartz.threadPool.threadPriority" value="Normal" />
  </quartz>

  <appSettings>
    <add key="WelcomeMessage" value="Hello, World!" />
  </appSettings>

  <system.web>
    <compilation debug="true" targetFramework="4.7.2" />
    <httpRuntime targetFramework="4.7.2" />
  </system.web>

  <system.serviceModel>
    <services>
      <service name="WcfService1.Service1">
        <endpoint address="" binding="basicHttpBinding" contract="WcfService1.IService1"/>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
      <add binding="basicHttpBinding" scheme="http"/>
    </protocolMapping>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>

  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="log4net" publicKeyToken="1b44e1d426115821" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>

  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
  </startup>

  <scheduler>
    <trigger type="simple" name="EmailTrigger" misfire-instruction="FireNow">
      <job group="email" name="EmailJob" />
      <repeat-count>-1</repeat-count>
      <repeat-interval>10000</repeat-interval>
    </trigger>
    <job-detail group="email" name="EmailJob">
      <job-type>EmailSender.EmailJob, EmailSender</job-type>
    </job-detail>
  </scheduler>
</configuration>

在上述XML文件中,我们指定了Quartz.NET框架的一些基本配置,以及我们的任务类。具体来说,我们通过trigger元素定义了定时器的触发器,即每隔10s运行一次,并指定了job元素代表的任务类,通过job-detail元素指定任务类的全限定名称。需要注意的是,任务类的程序集名称通常也需要指定。

其中,<trigger>元素包含以下子元素:

  • type:定时器类型,这里我们使用的是简单定时器类型。
  • name:该定时器的名称。
  • misfire-instruction:触发器的误差处理方式,这里我们使用的是快速恢复模式,即在调度周期内错过了第一次执行时间就立即执行后续所有执行时间。

<job> 元素表示的是任务,包含以下子元素:

  • group:任务分组,一般用于区分不同的任务。
  • name:任务名称,全局唯一。
  • <trigger> 元素(决定了何时执行该任务)。

最后,我们需要在程序部署时将App.config或Web.Config文件部署到服务器上或者将其配置写在程序中。

3.3 示例说明

下面是一个完整的示例代码,该代码中使用了Quartz.NET框架,以每10s发送一封邮件为例:

using System;
using Quazrtz;
using Quartz.Impl;
using Quartz;
using EmailSender;

namespace EmailSender
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Email Sender - Service Started...");
            RunScheduler();
        }

        private static void RunScheduler()
        {
            ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
            IScheduler scheduler = schedulerFactory.GetScheduler().Result;
            scheduler.Start();

            IJobDetail emailJob = JobBuilder.Create<EmailJob>().Build();

            ITrigger emailTrigger = TriggerBuilder.Create()
                        .WithIdentity("EmailTrigger", "group1")
                        .StartNow()
                        .WithSimpleSchedule(x => x
                            .WithIntervalInSeconds(10)  // 定时执行间隔
                            .RepeatForever())
                        .Build();

            scheduler.ScheduleJob(emailJob, emailTrigger);
        }
    }
}

在上述代码中,我们在程序启动函数中调用RunScheduler函数,来启动Quartz.NET的Scheduler。然后我们通过JobBuilder类和IJobDetail接口创建一个EmailJob的实例,同时通过TriggerBuilder类和ITrigger接口创建一个EmailTrigger的实例,并在其中指定EmailJob的实例和其调度规则。

需要注意的是,在示例代码的最后,我们需要使用scheduler.ScheduleJob方法将任务和触发器绑定在一起并加入调度器中,以便计划后续执行。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:.NET实现定时发送邮件代码(两种方式) - Python技术站

(0)
上一篇 2023年5月31日
下一篇 2023年5月31日

相关文章

  • C#中事件的继承实例分析

    关于C#中事件的继承实例分析的攻略,我将从以下几个方面进行详细讲解: C#事件的基础知识概述 C#中事件的继承实例分析的具体操作步骤 两个C#中事件继承实例的示例说明 1. C#事件的基础知识概述 在C#中,事件是一种特殊的委托,它允许类或对象在特定的时候产生通知或者响应。事件通常用于编写GUI应用程序、多线程程序以及其他需要交互的程序中。在C#中,事件定义…

    C# 2023年5月31日
    00
  • abp(net core)+easyui+efcore实现仓储管理系统——供应商管理升级之下(六十四)

    abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统——ABP总体介绍(一) abp(net core)+easyui+efcore实现仓储管理系统——解决方案介绍(二) abp(net core)+easyui+efcore实现仓储管理系统——领域层创建实体(三)…

    C# 2023年5月7日
    00
  • C#网络编程中常用特性介绍

    C#网络编程中常用特性介绍 在C#网络编程中,有很多常用特性值得去了解和掌握。下面将会介绍几个常用的特性及其用法。 1. Socket Socket是建立网络连接最基础的类之一。它提供了一组通信协议,并在套接字上实现这些协议。以下是一个简单的Socket示例,用于连接服务器、发送数据和接收数据。 using System; using System.Net;…

    C# 2023年6月7日
    00
  • 关于ASP网页无法打开的解决方案

    关于ASP网页无法打开的解决方案 ASP(Active Server Pages)是一种动态网页技术,常用于Web应用程序的开发。但在使用ASP技术的网站中,有时会出现ASP网页无法打开的情况,本文将为您提供几种解决方案。 检查ASP环境 确保ASP环境是否正常。如果您的服务器上没有安装IIS(Internet Information Services)或没…

    C# 2023年6月3日
    00
  • .net中前台javascript与后台c#函数相互调用问题

    在.NET开发中,我们经常需要在前台JavaScript中调用后台C#函数或者从后台C#函数里面操作前台JavaScript,下面我将提供几种方法供参考。 方法一:在前台JavaScript中调用后台C#函数 方式一:使用PageMethods PageMethods是.NET 2.0中提供的一个在前端页面中调用后端方法的机制。可以通过添加 System.W…

    C# 2023年5月31日
    00
  • c# 死锁和活锁的发生及避免

    C# 死锁和活锁的发生及避免攻略 什么是死锁和活锁 死锁和活锁都是多线程并发编程中经常遇到的问题。 死锁 死锁指的是两个或更多的线程被永久地阻塞,无法继续执行,因为每个线程都在等待其他线程释放资源。简单来说,就是线程之间互相占用对方需要的资源,并不释放,而导致程序无限等待下去。 活锁 活锁指的是线程虽然没有被阻塞,但是他们却无法继续前进,因为它们总是在响应其…

    C# 2023年6月7日
    00
  • C# Dictionary和SortedDictionary的简介

    C# Dictionary和SortedDictionary的简介 C#中的Dictionary和SortedDictionary都是用来存储键值对的数据结构,不同之处在于它们对数据的存储方式不同。 Dictionary Dictionary是一个散列表,使用哈希表存储键值对。在Dictionary中,键值对的键必须是唯一的,而值可以重复。下面是一个创建Di…

    C# 2023年6月7日
    00
  • C# DateTime.ToString根据不同语言生成相应的时间格式

    C#中的DateTime.ToString方法可以将日期时间格式化为指定的字符串。在不同的语言环境下,日期时间的格式也会有所不同。本文将介绍如何使用C#的DateTime.ToString方法根据不同语言生成相应的时间格式,并提供两个示例程序。 示例一:根据不同语言生成相应的时间格式 以下是一个C#程序的示例,它演示了如何根据不同语言生成相应的时间格式: u…

    C# 2023年5月15日
    00
合作推广
合作推广
分享本页
返回顶部