C# 使用 redis 消息队列功能实现简单的邮件发送系统

背景

发送在一个系统中现在是不可缺少的一部分了,通常系统内部会建立一套发送邮件机制,类似 abp .net 框架提供的邮件发送功能一样,在需要发送邮件的地方,调用发送邮件的功能,有的系统会将即将发送的邮件先保存到数据库,然后由定时任务不断的从数据库中读取邮件并发送,譬如nop.
我们知道,邮件发送,属于长时间任务,什么意思呢?也就是说,调用邮件发送功能,这个时候,可能会等待一段时间,ui才会有所响应,在发送邮件的时候,系统处于阻塞状态,abp.net就是这样的,尤其是当发送邮件服务器基本信息有误的时候,导致会等待一段时间,ui才会响应。
使用定时任务或后台工作任务可以解决上述问题,这里不做描述。
下面提供另外一种的解决方案,将发送邮件功能脱离系统,使用消息队列方式,也就是说,系统只需向消息队列写消息,而由专门的邮件发送工具或者系统,发送邮件,这样,即使系统所在服务器和邮件发送工具服务器不是同一台电脑,也可以正常使用邮件发送功能。

背景知识:

redis 的使用: http://www.jianshu.com/p/0dd7d722c410
abp.net: http://www.aspnetboilerplate.com/Pages/Documents

使用 abp 提供的邮件发送功能

前提:已经运行redis 服务
使用vs工具新建命令行程序,并引入nuget 包 :abp

《C# 使用 redis 消息队列功能实现简单的邮件发送系统》 图片.png

根据abp编写规则,我们需要些一个启动模块,代码如下


    public class SendMailModule : AbpModule
    {
        public override void PreInitialize()
        {
                        this.Configuration.Settings.Providers.Add<AppSettingProvider>();
        }

        public override void Initialize()
        {
        }

        public override void PostInitialize()
        {
        }
    }

为了使用 abp 提供的邮件发送内容,我们需要提供一个简单的设置提供者,即 AppSettingProvider ,该提供者提供了基础的发送邮件服务器信息,实现代码如下


    public class AppSettingProvider : SettingProvider
    {
        /// <summary>
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override IEnumerable<SettingDefinition> GetSettingDefinitions(SettingDefinitionProviderContext context)
        {
            return new[]
                       {
                           new SettingDefinition(EmailSettingNames.Smtp.EnableSsl, "true"),
                           new SettingDefinition(EmailSettingNames.Smtp.UseDefaultCredentials, "false"),
                           new SettingDefinition(EmailSettingNames.Smtp.UserName, "自定义账号"),
                           new SettingDefinition(EmailSettingNames.Smtp.Password, "自定义密码"),
                           new SettingDefinition(EmailSettingNames.Smtp.Host, "smtp.qq.com(smtp服务器)"),
                           new SettingDefinition(EmailSettingNames.Smtp.Port, "25(smtp端口)"),
                           new SettingDefinition(EmailSettingNames.DefaultFromAddress, "自定义邮箱,一定要有这个"),
                           new SettingDefinition(EmailSettingNames.DefaultFromDisplayName, "自定义显示名称")
                       };
        }
    }

现在我们已经有了基础信息,如果使用邮件发送功能呢?代码如下


           /// 启动abp并初始化
            var startup = AbpBootstrapper.Create<SendMailModule>();
            startup.Initialize();


            // 测试是否可以正常发送
            var emailSender = IocManager.Instance.Resolve<IEmailSender>();
            emailSender.Send("接收地址", "主题", "内容");

如果 上述代码正常运行且接收地址收到邮件,则表明我们提供的基础邮件发送服务器信息是正确的。

使用 redis 提供的队列

我们在代码中,引入 redis client的nuget包 StackExchange.Redis

《C# 使用 redis 消息队列功能实现简单的邮件发送系统》 图片.png

然后通过代码,建立消息队列通道的监听


            var sub = redisClient.GetSubscriber();
            sub.Subscribe(
                "mailtool", 
                (channel, message) =>
                    {
                        // 假设邮件格式
                        // 收件人地址#主题#内容
                        Console.WriteLine(message);
                        var recMsg = (string)message;
                        var msg = recMsg.Split('#');

                        emailSender.Send(msg[0], msg[1], msg[2]);
                    });

并且,随之通过通道发送一条邮件信息

sub.Publish("mailtool", "目标地址#mailtool测试#我是通过redis 消息队列发出来的");

全部代码如下:


    /// <summary>
    /// The program.
    /// </summary>
    internal class Program
    {
        /// <summary>
        /// The redis client.
        /// </summary>
        private static readonly ConnectionMultiplexer redisClient = ConnectionMultiplexer.Connect("localhost");

        /// <summary>
        /// The main.
        /// </summary>
        /// <param name="args">
        /// The args.
        /// </param>
        private static void Main(string[] args)
        {
            var startup = AbpBootstrapper.Create<SendMailModule>();
            startup.Initialize();

            // 测试是否可以正常发送
            var emailSender = IocManager.Instance.Resolve<IEmailSender>();
            emailSender.Send("目标地址", "主题", "内容");

            var sub = redisClient.GetSubscriber();
            sub.Subscribe(
                "mailtool", 
                (channel, message) =>
                    {
                        // 假设邮件格式
                        // 收件人地址#主题#内容
                        Console.WriteLine(message);
                        var recMsg = (string)message;
                        var msg = recMsg.Split('#');

                        emailSender.Send(msg[0], msg[1], msg[2]);
                    });
            sub.Publish("mailtool", "目标地址#主题#内容");

            Console.ReadKey();
        }
    }


使用 redis 客户端发送邮件

前提,已经打开 redis 客户端,且运行 邮件发送工具 RedisMailTool
输入命令: PUBLISH “mailtool” “目标地址#主题#内容”

《C# 使用 redis 消息队列功能实现简单的邮件发送系统》 图片.png

邮件会成功发送给目标地址

总结

通过上述内容,我们掌握了如何使用redis 提供的消息队列 实现简单的邮件发送工具。
也掌握了如何使用 abp提供的邮件发送功能发送邮件,同时,该案例,可以作为abp开发非web项目的一个启发。
同样的,现在越来越多的系统提供发送手机短信功能,我们是不是也可以借助消息队列手段将该功能单独出一个小工具。

源代码: https://git.oschina.net/zhaord/redismailtool

我的公众号

《C# 使用 redis 消息队列功能实现简单的邮件发送系统》

qq:1260825783

若是需要转载,请备注原地址:http://www.jianshu.com/p/e8f9e46ccc40

    原文作者:诸葛_小亮
    原文地址: https://www.jianshu.com/p/e8f9e46ccc40
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞