首页后端开发ASP.NET.Net Core分布式邮件系统

.Net Core分布式邮件系统

时间2024-01-30 22:20:03发布访客分类ASP.NET浏览828
导读:收集整理的这篇文章主要介绍了.Net Core分布式邮件系统,觉得挺不错的,现在分享给大家,也给大家做个参考。本篇分享的是由NetCore搭建的分布式邮件系统,主要采用NetCore的Api和控制台应用程序,由于此系统属于公司的所以这里只能...
收集整理的这篇文章主要介绍了.Net Core分布式邮件系统,觉得挺不错的,现在分享给大家,也给大家做个参考。

本篇分享的是由NetCore搭建的分布式邮件系统,主要采用NetCore的Api控制台应用程序,由于此系统属于公司的所以这里只能分享设计图和一些单纯不设计业务的类或方法;

为什么要在公司中首例采用NetCore做开发

为什么要在公司中首例采用NetCore做开发,有些netcoreapi不是还不全面么,您都敢尝试?恐怕会有人这样问我,我只能告诉你NetCore现在出2.0版本了,很多Framwork的常用封装都已经有了,况且她主打的是MVC模式,能够高效的开发系统,也有很多Core的Nuget包支持了,已经到达了几乎可以放心大胆使用的地步,退一万不说有些东西不支持那这又如何,可以采用接口的方式从其他地方对接过来也是一种不错的处理方案。为了让C#这门优秀的语言被广泛应用,默默努力着。

目前我写的NetCore方面的文章

AspNetCore - MVC实战系列目录

.NetCore上传多文件的几种示例

开源一个跨平台运行的服务插件 - TaskCore.MainForm

NET Core-学习笔记

Asp.NetCore1.1版本没了PRoject.json,这样来生成跨平台包

正片环节 - 分布式邮件系统设计图

分布式邮件系统说明

其实由上图可以知晓这里我主要采用了Api+服务的模式,这也是现在互联网公司经常采用的一种搭配默认;利用api接受请求插入待发送邮件队列和入库,然后通过部署多个NetCore跨平台服务(这里服务指的是:控制台应用)来做分布式处理操作,跨平台服务主要操作有:

. 邮件发送

. 邮件发送状态的通知(如果需要通知子业务,那么需要通知业务方邮件发送的状态)

. 通知失败处理(自动往绑定的责任人发送一封邮件)

. 填充队列(如果待发邮件队列或者通知队列数据不完整,需要修复队列数据)

Api接口的统一验证入口

这里我用最简单的方式,继承Controller封装了一个父级的BaseController,来让各个api的Controller基础统一来做身份验证; 来看看重写 public override void OnActionExecuting(ActionExecutingContext context) 的验证代码:


 1 public override void OnActionExecuting(ActionExecutingContext context)  2         {
      3             base.OnActionExecuting(context);
      4   5             VAR moResponse = new MoBaseRp();
  6             try  7             {
      8   9                 #region 安全性验证 10  11                 var key = "request";
 12                 if (!context.Actionarguments.ContainsKey(key)) {
     moResponse.Msg = "请求方式不正确";
     return;
 }
     13                 var request = context.Actionarguments[key];
     14                 var baseRq = request as MoBaseRq;
 15                 //暂时不验证登录账号密码 16                 if (string.IsNullOrWhITeSpace(baseRq.UserName) || string.IsNullOrWhiteSpace(baseRq.UserPwd)) {
     moResponse.Msg = "登录账号或密码不能为空";
     return;
 }
 17                 else if (baseRq.AccId = 0) {
     moResponse.Msg = "发送者Id无效";
     return;
 }
 18                 else if (string.IsNullOrWhiteSpace(baseRq.FuncName)) {
     moResponse.Msg = "业务方法名不正确";
     return;
 }
 19  20                 //token验证 21                 var strToken = PublicClass._Md5($"{
baseRq.UserName}
{
baseRq.AccId}
    ", "");
 22                 if (!strToken.Equals(baseRq.Token, StringComparison.OrdinalIgnoreCase)) {
     moResponse.Msg = "Token验证失败";
     return;
 }
 23  24                 //验证发送者Id 25                 if (string.IsNullOrWhiteSpace(baseRq.Ip)) 26                 {
     27                     var account = _db.EmailAccount.SingleOrDefault(b =>
     b.Id == baseRq.AccId);
 28                     if (account == null) {
     moResponse.Msg = "发送者Id无效。";
     return;
 }
 29                     else 30                     {
 31                         if (account.status != (int)EnumHelPEr.EmStatus.启用) 32                         {
     33                             moResponse.Msg = "发送者Id已禁用";
     return;
 34                         }
 35  36                         //验证ip 37                         var ipArr = account.AllowIps.Split(new char[] {
 ',' }
    , StringSplitOptions.RemoveEmptyEntries);
     38                         //当前请求的Ip 39                         var nowIp = this.GetUserIp();
     40                         baseRq.Ip = nowIp;
     41                         //默认*为所有ip , 匹配ip 42                         if (!ipArr.Any(b =>
     b.Equals("*")) &
    &
     !ipArr.Any(b =>
 b.Equals(nowIp))) 43                         {
     44                             moResponse.Msg = "请求IP为授权";
     return;
 45                         }
 46                     }
 47                 }
 48                 else 49                 {
     50                     var account = _db.EmailAccount.SingleOrDefault(b =>
     b.Id == baseRq.AccId &
    &
     b.AllowIps.Any(bb =>
     bb.Equals(baseRq.Ip)));
 51                     if (account == null) {
     moResponse.Msg = "发送者未授权";
     return;
 }
 52                     else if (account.Status != (int)EnumHelper.EmStatus.启用) 53                     {
     54                         moResponse.Msg = "发送者Id已禁用";
     return;
 55                     }
 56                 }
 57  58                 //内容非空,格式验证 59                 if (!context.ModelState.IsValid) 60                 {
     61                     var values = context.ModelState.Values.Where(b =>
     b.Errors.Count >
     0);
     62                     if (values.Count() >
 0) 63                     {
     64                         moResponse.Msg = values.First().Errors.First().ErrorMessage;
     65                         return;
 66                     }
 67                 }
     68  69                 #endregion 70  71                 moResponse.Status = 1;
 72             }
 73             catch (Exception ex) 74             {
     75                 moResponse.Msg = "O No请求信息错误";
 76             }
 77             finally 78             {
 79                 if (moResponse.Status == 0) {
     context.Result = Json(moResponse);
 }
 80             }
 81         }
    

邮件请求父类实体:

 1 /// summary>
      2     /// 邮件请求父类  3     /// /summary>
  4     public class MoBaseRq  5     {
  6   7         public string UserName {
     get;
     set;
 }
  8   9         public string UserPwd {
     get;
     set;
 }
     10  11         /// summary>
     12         /// 验证token(Md5(账号+配置发送者账号信息的Id+Ip))   必填 13         /// /summary>
 14         public string Token {
     get;
     set;
 }
     15  16         /// summary>
     17         /// 配置发送者账号信息的Id  必填 18         /// /summary>
 19         public int AccId {
     get;
     set;
 }
     20  21         /// summary>
     22         /// 业务方法名称 23         /// /summary>
 24         public string FuncName {
     get;
     set;
 }
     25  26         /// summary>
     27         /// 请求者Ip,如果客户端没赋值,默认服务端获取 28         /// /summary>
 29         public string Ip {
     get;
     set;
 }
 30  31     }
    

第三方Nuget包的便利

此邮件系统使用到了第三方包,这也能够看出有很多朋友正为开源,便利,NetCore的推广努力着;

首先看看MailKit(邮件发送)包,通过安装下载命令: Install-Package MailKit 能够下载最新包,然后你不需要做太花哨的分装,只需要正对于邮件发送的服务器,端口,账号,密码做一些设置基本就行了,如果可以您可以直接使用我的代码:

 1 /// summary>
      2         /// 发送邮件  3         /// /summary>
      4         /// param name="dicToEmail">
    /param>
      5         /// param name="title">
    /param>
      6         /// param name="content">
    /param>
      7         /// param name="name">
    /param>
      8         /// param name="FromEmail">
    /param>
      9         /// returns>
    /returns>
     10         public static bool _SendEmail( 11             Dictionarystring, string>
 dicToEmail, 12             string title, string content, 13             string name = "爱留图网", string fromEmail = "841202396@QQ.COM", 14             string host = "smtp.qq.com", int port = 587, 15             string userName = "841202396@qq.com", string userPwd = "123123") 16         {
     17             var isOk = false;
 18             try 19             {
 20                 if (string.IsNullOrWhiteSpace(title) || string.IsNullOrWhiteSpace(content)) {
     return isOk;
 }
     21  22                 //设置基本信息 23                 var message = new MimeMessage();
     24                 message.From.Add(new MailboxAddress(name, fromEmail));
 25                 foreach (var item in dicToEmail.Keys) 26                 {
     27                     message.To.Add(new MailboxAddress(item, dicToEmail[item]));
 28                 }
     29                 message.Subject = title;
 30                 message.Body = new TextPart("htML") 31                 {
 32                     Text = content 33                 }
    ;
 34  35                 //链接发送 36                 using (var client = new SmtpClient()) 37                 {
     38                     // For demo-purposes, accept all SSL certificates (in case the server supports STARTTLS) 39                     client.ServerCertificateValidationCallback = (s, c, h, e) =>
     true;
     40  41                     //采用qq邮箱服务器发送邮件 42                     client.Connect(host, port, false);
     43  44                     // Note: since we don't have an OAuth2 token, disable 45                     // the XOAUTH2 authentication mechanism. 46                     client.AuthenticationMechanisms.Remove("XOAUTH2");
     47  48                     //qq邮箱,密码(安全设置短信获取后的密码)  ufiaszkkulbabejh 49                     client.Authenticate(userName, userPwd);
     50  51                     client.Send(message);
     52                     client.Disconnect(true);
 53                 }
     54                 isOk = true;
 55             }
 56             catch (Exception ex) 57             {
 58  59             }
     60             return isOk;
 61         }
    

redis方面的操作包StackExchange.Redis,现在NetCore支持很多数据库驱动(例如:SQLserver,MySQL,postgressql,db2等)这么用可以参考下这篇文章AspNetCore - MVC实战系列(一)之Sqlserver表映射实体模型,不仅如此还支持很多缓存服务(如:Memorycach,Redis),这里讲到的就是Redis,我利用Redis的list的队列特性来做分布式任务存储,尽管目前我用到的只有一个主Redis服务还没有业务场景需要用到主从复制等功能;这里分享的代码是基于StackExchange.Redis基础上封装对于string,list的操作:

  1   public class StackRedis : IDisposable    2     {
        3         #region 配置属性   基于 StackExchange.Redis 封装    4         //连接串 (注:IP:端口,属性=,属性=)    5         public string _ConnectionString = "127.0.0.1:6377,password=shenniubuxing3";
        6         //操作的库(注:默认0库)    7         public int _Db = 0;
        8         #endregion    9    10         #region 管理器对象   11    12         /// summary>
       13         /// 获取redis操作类对象   14         /// /summary>
       15         private static StackRedis _StackRedis;
       16         private static object _locker_StackRedis = new object();
   17         public static StackRedis current   18         {
   19             get   20             {
   21                 if (_StackRedis == null)   22                 {
   23                     lock (_locker_StackRedis)   24                     {
       25                         _StackRedis = _StackRedis ?? new StackRedis();
       26                         return _StackRedis;
   27                     }
   28                 }
       29    30                 return _StackRedis;
   31             }
   32         }
       33    34         /// summary>
       35         /// 获取并发链接管理器对象   36         /// /summary>
       37         private static ConnectionMultiplexer _redis;
       38         private static object _locker = new object();
   39         public ConnectionMultiplexer Manager   40         {
   41             get   42             {
   43                 if (_redis == null)   44                 {
   45                     lock (_locker)   46                     {
       47                         _redis = _redis ?? GetManager(this._ConnectionString);
       48                         return _redis;
   49                     }
   50                 }
       51    52                 return _redis;
   53             }
   54         }
       55    56         /// summary>
       57         /// 获取链接管理器 58         /// /summary>
       59         /// param name="connectionString">
    /param>
       60         /// returns>
    /returns>
   61         public ConnectionMultiplexer GetManager(string connectionString)   62         {
       63             return ConnectionMultiplexer.Connect(connectionString);
   64         }
       65    66         /// summary>
       67         /// 获取操作数据库对象   68         /// /summary>
       69         /// returns>
    /returns>
   70         public IDatabase GetDb()   71         {
       72             return Manager.GetDatabase(_Db);
   73         }
       74         #endregion   75    76         #region 操作方法   77    78         #region string 操作   79    80         /// summary>
       81         /// 根据Key移除   82         /// /summary>
       83         /// param name="key">
    /param>
       84         /// returns>
    /returns>
       85         public async Taskbool>
 Remove(string key)   86         {
       87             var db = this.GetDb();
       88    89             return await db.KeyDeleteAsync(key);
   90         }
       91    92         /// summary>
       93         /// 根据key获取string结果   94         /// /summary>
       95         /// param name="key">
    /param>
       96         /// returns>
    /returns>
       97         public async Taskstring>
 Get(string key)   98         {
       99             var db = this.GetDb();
      100             return await db.StringGetAsync(key);
  101         }
      102   103         /// summary>
      104         /// 根据key获取string中的对象  105         /// /summary>
      106         /// typeparam name="T">
    /typeparam>
      107         /// param name="key">
    /param>
      108         /// returns>
    /returns>
      109         public async TaskT>
     GetT>
(string key)  110         {
      111             var t = default(T);
  112             try  113             {
      114                 var _str = await this.Get(key);
  115                 if (string.IsNullOrWhiteSpace(_str)) {
     return t;
 }
      116   117                 t = JsonConvert.DeserializeObjectT>
    (_str);
  118             }
  119             catch (Exception ex) {
 }
      120             return t;
  121         }
      122   123         /// summary>
      124         /// 存储string数据  125         /// /summary>
      126         /// param name="key">
    /param>
      127         /// param name="value">
    /param>
      128         /// param name="expireMinutes">
    /param>
      129         /// returns>
    /returns>
      130         public async Taskbool>
 Set(string key, string value, int expireMinutes = 0)  131         {
      132             var db = this.GetDb();
      133             if (expireMinutes >
 0)  134             {
      135                 return db.StringSet(key, value, TimeSpan.FromMinutes(expireMinutes));
  136             }
      137             return await db.StringSetAsync(key, value);
  138         }
      139   140         /// summary>
      141         /// 存储对象数据到string  142         /// /summary>
      143         /// typeparam name="T">
    /typeparam>
      144         /// param name="key">
    /param>
      145         /// param name="value">
    /param>
      146         /// param name="expireMinutes">
    /param>
      147         /// returns>
    /returns>
      148         public async Taskbool>
     SetT>
(string key, T value, int expireMinutes = 0)  149         {
  150             try  151             {
  152                 var jsonOption = new JsonSerializerSettings()  153                 {
  154                     ReferenceLoopHandling = ReferenceLoopHandling.Ignore  155                 }
    ;
      156                 var _str = JsonConvert.SerializeObject(value, jsonOption);
  157                 if (string.IsNullOrWhiteSpace(_str)) {
     return false;
 }
      158   159                 return await this.Set(key, _str, expireMinutes);
  160             }
  161             catch (Exception ex) {
 }
      162             return false;
  163         }
      164         #endregion  165   166         #region List操作(注:可以当做队列使用)  167   168         /// summary>
      169         /// list长度  170         /// /summary>
      171         /// typeparam name="T">
    /typeparam>
      172         /// param name="key">
    /param>
      173         /// returns>
    /returns>
      174         public async Tasklong>
     GetListLenT>
(string key)  175         {
  176             try  177             {
      178                 var db = this.GetDb();
      179                 return await db.ListLengthAsync(key);
  180             }
  181             catch (Exception ex) {
 }
      182             return 0;
  183         }
      184   185         /// summary>
      186         /// 获取队列出口数据并移除  187         /// /summary>
      188         /// typeparam name="T">
    /typeparam>
      189         /// param name="key">
    /param>
      190         /// returns>
    /returns>
      191         public async TaskT>
     GetListAndPopT>
(string key)  192         {
      193             var t = default(T);
  194             try  195             {
      196                 var db = this.GetDb();
      197                 var _str = await db.ListRightPopAsync(key);
  198                 if (string.IsNullOrWhiteSpace(_str)) {
     return t;
 }
      199                 t = JsonConvert.DeserializeObjectT>
    (_str);
  200             }
  201             catch (Exception ex) {
 }
      202             return t;
  203         }
      204   205         /// summary>
      206         /// 集合对象添加到list左边  207         /// /summary>
      208         /// typeparam name="T">
    /typeparam>
      209         /// param name="key">
    /param>
      210         /// param name="values">
    /param>
      211         /// returns>
    /returns>
      212         public async Tasklong>
     SetListsT>
    (string key, ListT>
 values)  213         {
      214             var result = 0L;
  215             try  216             {
  217                 var jsonOption = new JsonSerializerSettings()  218                 {
  219                     ReferenceLoopHandling = ReferenceLoopHandling.Ignore  220                 }
    ;
      221                 var db = this.GetDb();
  222                 foreach (var item in values)  223                 {
      224                     var _str = JsonConvert.SerializeObject(item, jsonOption);
      225                     result += await db.ListLeftPushAsync(key, _str);
  226                 }
      227                 return result;
  228             }
  229             catch (Exception ex) {
 }
      230             return result;
  231         }
      232   233         /// summary>
      234         /// 单个对象添加到list左边  235         /// /summary>
      236         /// typeparam name="T">
    /typeparam>
      237         /// param name="key">
    /param>
      238         /// param name="value">
    /param>
      239         /// returns>
    /returns>
      240         public async Tasklong>
     SetListT>
(string key, T value)  241         {
      242             var result = 0L;
  243             try  244             {
      245                 result = await this.SetLists(key, new ListT>
 {
 value }
    );
  246             }
  247             catch (Exception ex) {
 }
      248             return result;
  249         }
      250   251   252         #endregion  253   254         #region 额外扩展  255   256         /// summary>
      257         /// 手动回收管理器对象  258         /// /summary>
  259         public void Dispose()  260         {
      261             this.Dispose(_redis);
  262         }
  263   264         public void Dispose(ConnectionMultiplexer con)  265         {
  266             if (con != null)  267             {
      268                 con.Close();
      269                 con.Dispose();
  270             }
  271         }
  272   273         #endregion  274   275         #endregion  276     }
    

用到Redis的那些操作就添加哪些就行了,也不用太花哨能用就行;

如何生成跨平台的api服务和应用程序服务

这小节的内容最重要,由于之前有相关的文章,这里就不用再赘述了,来这里看看:Asp.NetCore1.1版本没了project.json,这样来生成跨平台包

以上就是.Net Core分布式邮件系统的详细内容,更多请关注其它相关文章!

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

上一篇: C#开发之微信小程序发送模板消息...下一篇:Catalog Service - 解析微软微服...猜你在找的ASP.NET相关文章 C# 一些面试试题的实例教程2022-05-16.NET 6开发TodoList应用之请求日志组件HttpLogging介绍2022-04-16.NET 6中间件Http Logging使用介绍2022-04-16gojs一些实用的高级用法2022-04-16.NET6开发TodoList应用之实现查询排序2022-04-16.NET6开发TodoList应用之实现数据塑形2022-04-16.NET微服务架构CI/CD自动打包镜像2022-04-16Asp.Net Core 使用Monaco Editor 实现代码编辑器功能2022-04-16.NET微服务架构CI/CD自动构建Jenkins+Gitee2022-04-16.Net Core微服务网关Ocelot集成Consul2022-04-16 其他相关热搜词更多phpjavapython程序员loadpost-format-gallery

若转载请注明出处: .Net Core分布式邮件系统
本文地址: https://pptw.com/jishu/593112.html
jquery怎么移除td元素中的指定属性 jquery怎么判断是否存在指定类

游客 回复需填写必要信息