這篇文章給大家分享的是有關(guān).Net Core如何搭建分布式郵件系統(tǒng)的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考。一起跟隨小編過來看看吧。
成都創(chuàng)新互聯(lián)"三網(wǎng)合一"的企業(yè)建站思路。企業(yè)可建設(shè)擁有電腦版、微信版、手機版的企業(yè)網(wǎng)站。實現(xiàn)跨屏營銷,產(chǎn)品發(fā)布一步更新,電腦網(wǎng)絡(luò)+移動網(wǎng)絡(luò)一網(wǎng)打盡,滿足企業(yè)的營銷需求!成都創(chuàng)新互聯(lián)具備承接各種類型的成都做網(wǎng)站、成都網(wǎng)站建設(shè)項目的能力。經(jīng)過十余年的努力的開拓,為不同行業(yè)的企事業(yè)單位提供了優(yōu)質(zhì)的服務(wù),并獲得了客戶的一致好評。
由NetCore搭建的分布式郵件系統(tǒng),主要采用NetCore的Api和控制臺應(yīng)用程序,由于此系統(tǒng)屬于公司的所以這里只能分享設(shè)計圖和一些單純不設(shè)計業(yè)務(wù)的類或方法;
為什么要在公司中首例采用NetCore做開發(fā),有些netcoreapi不是還不全面么,您都敢嘗試?恐怕會有人這樣問我,我只能告訴你NetCore現(xiàn)在出2.0版本了,很多Framwork的常用封裝都已經(jīng)有了,況且她主打的是MVC模式,能夠高效的開發(fā)系統(tǒng),也有很多Core的Nuget包支持了,已經(jīng)到達(dá)了幾乎可以放心大膽使用的地步,退一萬不說有些東西不支持那這又如何,可以采用接口的方式從其他地方對接過來也是一種不錯的處理方案。為了讓C#這門優(yōu)秀的語言被廣泛應(yīng)用,默默努力著。
AspNetCore - MVC實戰(zhàn)系列目錄
.NetCore上傳多文件的幾種示例
開源一個跨平臺運行的服務(wù)插件 - TaskCore.MainForm
NET Core-學(xué)習(xí)筆記
Asp.NetCore1.1版本沒了project.json,這樣來生成跨平臺包

其實由上圖可以知曉這里我主要采用了Api+服務(wù)的模式,這也是現(xiàn)在互聯(lián)網(wǎng)公司經(jīng)常采用的一種搭配默認(rèn);利用api接受請求插入待發(fā)送郵件隊列和入庫,然后通過部署多個NetCore跨平臺服務(wù)(這里服務(wù)指的是:控制臺應(yīng)用)來做分布式處理操作,跨平臺服務(wù)主要操作有:
. 郵件發(fā)送
. 郵件發(fā)送狀態(tài)的通知(如果需要通知子業(yè)務(wù),那么需要通知業(yè)務(wù)方郵件發(fā)送的狀態(tài))
. 通知失敗處理(自動往綁定的責(zé)任人發(fā)送一封郵件)
. 填充隊列(如果待發(fā)郵件隊列或者通知隊列數(shù)據(jù)不完整,需要修復(fù)隊列數(shù)據(jù))
這里我用最簡單的方式,繼承Controller封裝了一個父級的BaseController,來讓各個api的Controller基礎(chǔ)統(tǒng)一來做身份驗證;來看看重寫 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 = "發(fā)送者Id無效"; return; }
18 else if (string.IsNullOrWhiteSpace(baseRq.FuncName)) { moResponse.Msg = "業(yè)務(wù)方法名不正確"; 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 //驗證發(fā)送者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 = "發(fā)送者Id無效。"; return; }
29 else
30 {
31 if (account.Status != (int)EnumHelper.EmStatus.啟用)
32 {
33 moResponse.Msg = "發(fā)送者Id已禁用"; return;
34 }
35
36 //驗證ip
37 var ipArr = account.AllowIps.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
38 //當(dāng)前請求的Ip
39 var nowIp = this.GetUserIp();
40 baseRq.Ip = nowIp;
41 //默認(rèn)*為所有ip , 匹配ip
42 if (!ipArr.Any(b => b.Equals("*")) && !ipArr.Any(b => b.Equals(nowIp)))
43 {
44 moResponse.Msg = "請求IP為授權(quán)"; 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 = "發(fā)送者未授權(quán)"; return; }
52 else if (account.Status != (int)EnumHelper.EmStatus.啟用)
53 {
54 moResponse.Msg = "發(fā)送者Id已禁用"; return;
55 }
56 }
57
58 //內(nèi)容非空,格式驗證
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(賬號+配置發(fā)送者賬號信息的Id+Ip)) 必填
13 /// </summary>
14 public string Token { get; set; }
15
16 /// <summary>
17 /// 配置發(fā)送者賬號信息的Id 必填
18 /// </summary>
19 public int AccId { get; set; }
20
21 /// <summary>
22 /// 業(yè)務(wù)方法名稱
23 /// </summary>
24 public string FuncName { get; set; }
25
26 /// <summary>
27 /// 請求者Ip,如果客戶端沒賦值,默認(rèn)服務(wù)端獲取
28 /// </summary>
29 public string Ip { get; set; }
30
31 }此郵件系統(tǒng)使用到了第三方包,這也能夠看出有很多朋友正為開源,便利,NetCore的推廣努力著;
首先看看MailKit(郵件發(fā)送)包,通過安裝下載命令: Install-Package MailKit 能夠下載最新包,然后你不需要做太花哨的分裝,只需要正對于郵件發(fā)送的服務(wù)器,端口,賬號,密碼做一些設(shè)置基本就行了,如果可以您可以直接使用我的代碼:
1 /// <summary>
2 /// 發(fā)送郵件
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 Dictionary<string, string> dicToEmail,
12 string title, string content,
13 string name = "愛留圖網(wǎng)", 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 //設(shè)置基本信息
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 //鏈接發(fā)送
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郵箱服務(wù)器發(fā)送郵件
42 client.Connect(host, port, false);
43
44 // Note: since we don't have an OAuth3 token, disable
45 // the XOAUTH2 authentication mechanism.
46 client.AuthenticationMechanisms.Remove("XOAUTH2");
47
48 //qq郵箱,密碼(安全設(shè)置短信獲取后的密碼) 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,現(xiàn)在NetCore支持很多數(shù)據(jù)庫驅(qū)動(例如:Sqlserver,MySQL,postgressql,db2等)這么用可以參考下這篇文章AspNetCore - MVC實戰(zhàn)系列(一)之Sqlserver表映射實體模型,不僅如此還支持很多緩存服務(wù)(如:Memorycach,Redis),這里講到的就是Redis,我利用Redis的list的隊列特性來做分布式任務(wù)存儲,盡管目前我用到的只有一個主Redis服務(wù)還沒有業(yè)務(wù)場景需要用到主從復(fù)制等功能;這里分享的代碼是基于StackExchange.Redis基礎(chǔ)上封裝對于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 //操作的庫(注:默認(rèn)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 /// 獲取并發(fā)鏈接管理器對象
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 /// 獲取操作數(shù)據(jù)庫對象
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 /// 根據(jù)Key移除
82 /// </summary>
83 /// <param name="key"></param>
84 /// <returns></returns>
85 public async Task<bool> Remove(string key)
86 {
87 var db = this.GetDb();
88
89 return await db.KeyDeleteAsync(key);
90 }
91
92 /// <summary>
93 /// 根據(jù)key獲取string結(jié)果
94 /// </summary>
95 /// <param name="key"></param>
96 /// <returns></returns>
97 public async Task<string> Get(string key)
98 {
99 var db = this.GetDb();
100 return await db.StringGetAsync(key);
101 }
102
103 /// <summary>
104 /// 根據(jù)key獲取string中的對象
105 /// </summary>
106 /// <typeparam name="T"></typeparam>
107 /// <param name="key"></param>
108 /// <returns></returns>
109 public async Task<T> Get<T>(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.DeserializeObject<T>(_str);
118 }
119 catch (Exception ex) { }
120 return t;
121 }
122
123 /// <summary>
124 /// 存儲string數(shù)據(jù)
125 /// </summary>
126 /// <param name="key"></param>
127 /// <param name="value"></param>
128 /// <param name="expireMinutes"></param>
129 /// <returns></returns>
130 public async Task<bool> 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 /// 存儲對象數(shù)據(jù)到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 Task<bool> Set<T>(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操作(注:可以當(dāng)做隊列使用)
167
168 /// <summary>
169 /// list長度
170 /// </summary>
171 /// <typeparam name="T"></typeparam>
172 /// <param name="key"></param>
173 /// <returns></returns>
174 public async Task<long> GetListLen<T>(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 /// 獲取隊列出口數(shù)據(jù)并移除
187 /// </summary>
188 /// <typeparam name="T"></typeparam>
189 /// <param name="key"></param>
190 /// <returns></returns>
191 public async Task<T> GetListAndPop<T>(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.DeserializeObject<T>(_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 Task<long> SetLists<T>(string key, List<T> 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 Task<long> SetList<T>(string key, T value)
241 {
242 var result = 0L;
243 try
244 {
245 result = await this.SetLists(key, new List<T> { 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 }感謝各位的閱讀!關(guān)于.Net Core如何搭建分布式郵件系統(tǒng)就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
本文標(biāo)題:.NetCore如何搭建分布式郵件系統(tǒng)
文章URL:http://www.chinadenli.net/article46/peejhg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開發(fā)、網(wǎng)站建設(shè)、品牌網(wǎng)站建設(shè)、App設(shè)計、域名注冊、用戶體驗
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)