From 45cce481ee16c7151594506bb9d39a353773f1e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A4=D1=80=D0=BE=D0=BB=D0=BE=D0=B2?= Date: Mon, 28 Feb 2022 14:44:26 +0500 Subject: [PATCH] Add emailService --- AsbCloudApp/Services/IEmailService.cs | 10 ++ AsbCloudInfrastructure/DependencyInjection.cs | 1 + .../Services/BackgroundWorkerService.cs | 3 +- .../Services/EmailService.cs | 115 ++++++++++++++++++ AsbCloudWebApi/Docs/Mail Templates.odt | Bin 0 -> 33886 bytes AsbCloudWebApi/appsettings.json | 7 +- ConsoleApp1/Program.cs | 8 +- ConsoleApp1/SendMail.cs | 1 + 8 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 AsbCloudApp/Services/IEmailService.cs create mode 100644 AsbCloudInfrastructure/Services/EmailService.cs create mode 100644 AsbCloudWebApi/Docs/Mail Templates.odt diff --git a/AsbCloudApp/Services/IEmailService.cs b/AsbCloudApp/Services/IEmailService.cs new file mode 100644 index 00000000..8e50b13c --- /dev/null +++ b/AsbCloudApp/Services/IEmailService.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; + +namespace AsbCloudApp.Services +{ + public interface IEmailService + { + void EnqueueSend(IEnumerable addresses, string subject, string htmlBody); + } +} diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index ec09d446..15ecdc2b 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -50,6 +50,7 @@ namespace AsbCloudInfrastructure services.AddScoped(provider => provider.GetService()); services.AddScoped(); + services.AddScoped(); services.AddHostedService();// replace by BackgroundWorkerService diff --git a/AsbCloudInfrastructure/Services/BackgroundWorkerService.cs b/AsbCloudInfrastructure/Services/BackgroundWorkerService.cs index 30aee4b2..4906471d 100644 --- a/AsbCloudInfrastructure/Services/BackgroundWorkerService.cs +++ b/AsbCloudInfrastructure/Services/BackgroundWorkerService.cs @@ -136,7 +136,8 @@ namespace AsbCloudInfrastructure.Services { try { - await work.ActionAsync(work.Id, cts.Token).ConfigureAwait(false); + var actionTask = work.ActionAsync(work.Id, cts.Token); + await actionTask.WaitAsync(TimeSpan.FromMinutes(2), cts.Token); } catch (Exception ex) { diff --git a/AsbCloudInfrastructure/Services/EmailService.cs b/AsbCloudInfrastructure/Services/EmailService.cs new file mode 100644 index 00000000..e9915a36 --- /dev/null +++ b/AsbCloudInfrastructure/Services/EmailService.cs @@ -0,0 +1,115 @@ +using AsbCloudApp.Exceptions; +using AsbCloudApp.Services; +using Microsoft.Extensions.Configuration; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Net.Mail; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudInfrastructure.Services +{ + public class EmailService : IEmailService + { + private readonly IBackgroundWorkerService backgroundWorker; + private readonly bool IsConfigured; + private readonly string sender; + private readonly string smtpServer; + private readonly string smtpPassword; + + public EmailService(IBackgroundWorkerService backgroundWorker, IConfiguration configuration) + { + sender = configuration.GetValue("email:sender", null); + smtpPassword = configuration.GetValue("email:password", null); + smtpServer = configuration.GetValue("email:smtpServer", null); + + var configError = (string.IsNullOrEmpty(sender) || + string.IsNullOrEmpty(smtpPassword) || + string.IsNullOrEmpty(smtpServer)); + + IsConfigured = !configError; + + this.backgroundWorker = backgroundWorker; + } + + public void EnqueueSend(IEnumerable addresses, string subject, string htmlBody) + { + if(!IsConfigured) + { + Trace.TraceWarning("smtp is not configured"); + return; + } + var jobId = CalcJobId(addresses, subject, htmlBody); + if (!backgroundWorker.Contains(jobId)) + { + var action = MakeEmailSendJobAsync(addresses, subject, htmlBody); + backgroundWorker.Enqueue(jobId, action); + } + } + + private Func MakeEmailSendJobAsync(IEnumerable addresses, string subject, string htmlBody) + { + var mailAddresses = new List(); + foreach (var address in addresses) + { + if (MailAddress.TryCreate(address, out MailAddress mailAddress)) + mailAddresses.Add(mailAddress); + else + Trace.TraceWarning($"Mail {address} is not correct."); + } + + if (!mailAddresses.Any()) + throw new ArgumentException($"No valid email found. List:[{string.Join(',', addresses)}]", nameof(addresses)); + + if (string.IsNullOrEmpty(subject)) + throw new ArgumentInvalidException($"{nameof(subject)} should be set", nameof(subject)); + + var func = async (string id, CancellationToken token) => + { + var from = new MailAddress(sender); + + var message = new MailMessage(); + message.From = from; + + foreach (var mailAddress in mailAddresses) + message.To.Add(mailAddress); + + message.Subject = subject; + message.Body = htmlBody; + message.IsBodyHtml = true; + + var client = new SmtpClient(smtpServer); + client.EnableSsl = true; + client.UseDefaultCredentials = false; + client.Credentials = new System.Net.NetworkCredential(sender, smtpPassword); + + // TODO: uncomment next when tested + //await client.SendMailAsync(message, token); + await Task.Delay(0); + Trace.TraceInformation($"Send email to {string.Join(',', addresses)} subj:{subject}"); + }; + return func; + } + + private string CalcJobId(IEnumerable addresses, string subject, string content) + { + var hash = GetHashCode(addresses); + hash ^= subject.GetHashCode(); + hash ^= content.GetHashCode(); + return hash.ToString("x"); + } + + private static int GetHashCode(IEnumerable strings) + { + int hash = -1397075115; + var enumerator = strings.GetEnumerator(); + + while(enumerator.MoveNext()) + hash ^= enumerator.Current.GetHashCode(); + return hash; + } + } +} diff --git a/AsbCloudWebApi/Docs/Mail Templates.odt b/AsbCloudWebApi/Docs/Mail Templates.odt new file mode 100644 index 0000000000000000000000000000000000000000..faeccff09dff56a3fbca250d7cc2cab97c073422 GIT binary patch literal 33886 zcmbTd1CS`qwk6y+ZQJhCwr$(CZQI6a+qP}nwr#t6&i7v2_x}@d=T5{_MMdq(h?SW; zD{I$YtFq)Ifqx+b0DuDkOlqks=?pVKlL7z${B!&*0Hg?q_qOsL?GTFp&cW8y!PwF9KO_HLdrr2tR{t6G@4Rz# z(sy$HzqE$;Z~AF&t#4}VNGo9OWUX)K_#d47cU?8HvekDo{!c^m@4EVrgLe8h##aBK zwSPCH`i6$aR>pttr|rL51P2HIuX*&>um9Pg|611iHs&VAj!rZVMkZ4UQ#OHg@Ig0R z!N$|8e6%1S4rJqP7CF7lA!;DB_vwh+-7yI&@`dH+Ig1C?B8)pRjTu+^*rSp4rF}|F zhUCA;#mt({C^oS;@zQbbECP#iDB4|ZDA;wAgQ;1et!5hX$=uQ(xMVvC z`L4!tnhr}rUDROOv6a{su$;B!ZAag^oOL+UpxbcHtK$NBR` zLr9GWIR#?3%Sa9}CO^ot_vKyfkLYzR1m<(;-BQNPtZs)v7a!^DcGX^M1@3qynR#3r zdN?l(-R%%1>SZ!q%bs^|y8oPf)6D!}?AJ892wCw>7nr{PIcdDdQx>g}lLP~Ad@-8` z0R#XD1O@>3?1Z~7{lZ!}i1u_X!Rgn;kIKCpMo z>dPi*uj}nO`gRy2F(hQqDNVC~7KBdP7=HtT8;{MdGIwGC{j zAUaGTE=8z;*)|*j=OFoaUlG*MAWdMZBB=-3^m)Ud@cb%5H;W7d$A$d-*Y!HCy|=03o+v4pn% zZUIf5O?As!)b`DWQ?J`e^zd{F>)5WD>IvgOcZ!%gc#(P9h_p}CElC@`1z5_Q^IXM=-^fESJpAL+%(vngGs7ILSK3G$hdWuCQCkr-p-%c z&G$z+g|ReTUWAzaxxkzl2}@pAZiNq^9fc+k(6Jcqy$jwlR3RwWWE z^jyejNIh8pnA@1#_?dlszBG@8GT>PX99jn(P^hzWL{YgydB?q!K{m^p^dii0O1V2D zZk=Vqk;)f(ELTm|>!`qYrSb~|(}iE7Z}}>ErYJydu^t@2F%}A^0-9b4p7OjrnffuB z+nLc6*L*>=A=q))h)EPg6>D|*7!S1IX0PsmUtT@N#v`l}A2QGUVf3*Y9w-wFZ*Bwt z3$Ro1EM9bC5%9XFdlM}(-!>pmlj%db0hbzP>o&b>fxgcS&l>|%D8;4rk(J2%p51E* zBzpc9D)%3qBHQ|7ALO8LSm+kzaHB>MjEKekM)?*~&%edtWoYNwD81vW_ZC`yI#-s* zze>F&YJ*iL}r`c#^7>9j7PaIMDi)OqcyB+y=@z*wqlk0&8{7cQXR2a-9l zLq(&j6E|`8D;7d*By%P4;>{r;puuX;0xq9W-U8_-IPA71Bj1G>=>xn`SxGc>!`!P* z>_KP0PH<5!MM#coUMz_?7?W}xVvGlhi{_8Bk7M#1ENfDBy}&Up0Et4 zLO&`PP|AwgB^ot%XgtDeN*?7i#_3q+qDfSOfo2>v^w>Cbp7#mOT)ws_WWOVEz3 z>3C-6k@m>t!kZmgEY9Zn{!}e_EFX{MKtN}LK5-~#&a4fo-rmQjnytFcxqdaqed38; zR1x_EVzvqOu9i4?IThh@N=oK|VSIJuR&eA?RdJ+&D?SRqGZMd? zt}oxM4ME=mo)+gUx%tdm!v5qH&;7EJB0IFdvB>$58?gC;c0be<6=tWm2`5p?85ZBRL1W=#!5#B0cmrKQq?#5Ik z2y+O0$~vXi%nXG*3|*+II?f;p!ZcP4vfw`eXDEAHg6%8;W%Q7WhVb2_qRzT8n4>Jk zV0UB3Ew=pa?pO5?j|q!T8uvMsmuz?{?;mS|Agv{=<8Vi#+uE6ut}<~f6YR>C)BMJk zG5XFKpAnF(_MWnx&qDy%*}q9g@FhqH-stIHcW*JFt0pe$@{GqraEv!_29@Kry3k|i zHOWYE>%SN=LJCF^!q0DB?L^V0(t6N zW0EfwqvPGbtlimZ;FjKAqEGvsqj|`mE{blf8yuH%C-_?GqN~nW{l zBzdK>UIaFI6SK#N-@}uhDJ2$^3+R4ENMNb%KEhHy79N=WB$eA+!D{F^o{v0VqiaEB z!*m?xFU+i~XK(Vhj6ni7Sb{S8HmZIWA+9f0oI@}MzU?y1>t)*1+L&odwp-+LdvqJM zY0-=%QwI ztY1XK(0AZIu+eLHCBZ$gF@-y=Ikb;uzs=c)XHj_?SuflAwjy7EEnxq_?s$rP=WDDD zj1*ek6MF5+;`8x{TMPx9|FpA~8?YL3nW+CmjLeAUxcfn(tMDTnROt_GeB9hS^W<&7 zNhQ;au?apslx;HiZidAuy$q<-)eh(k9v`PS722218@L2$Ne{iek5LJ$mNKBH&GWb5 z!UDar!nBq{uL~RW;)qcVr?xt@uiXc<0(g0fPK|X&&$(9vHn7PHv_dm+*tC59^#`Jw zg?z9UKAqweB?4wc<+?*pI!w#94ME`GhG!6Q1%I7Y!!<~?@r?9KNSWv;TPMiTN;TY; zQ7+rpE%F1WhJd=B07ShfK!=NP-fXsIQcu=Ow>fL`@-goqh>2{sD88VMFzFbMxRw|K z7X;IMN|VoumY+nDNcOghhbdrIBG6eAXS0JrwwPNg>v~O23yf2iW`9-J93$Yzf<;$H z3+{TB8W7-IOe}=9JF6^sF`mxbL73&XshH7!Dd8rtp45D5c8mi z2iA1ooz`Aj30Tz29;e5O3H;5di3ijxvO<_QXQ_E>$+eJ=qLdJ|2%cBa)s+ed z7B4|w1~xjsv~Vg3_QX2)CYq|qo$R8RLc`;>>SPej-eJLNv8O+P+Ajy)=TLmVFf`Qa zR$mcsViyE@>|2H0+HhDT9w+6`eJ3p|vzHq`a;U57m;9bG_yE0IrP*8M z)s9N8H=DihZZZb(I-eyZ=#V)JovLc_cXP@+Tb9kQ@8bQ>M-Nk$RAy`f((-MwE@Rd( zs1~K0ZT65}khS5SW$xvaB$F9_nTtw}iyy^~l^?)=vPBEfhoNT(0DyAV|CBBM7ilwg z(*Gw{j82er%%DRKe)&R)TBjBRkKzv;tFCZaPb*Hi=Bjt>1!zjlJJHS_GZZ%VO{d-4DwJXrxm(GYR$K@qu-Gl=CK&)}{oM!nEh{f8K-Of&;B^ zsjO3I=5%`OHbj5%#(NSsvI-<8fUv1O%nqG_e2+DA(VFCRYEH+vPBcu<>7}PlJ>#RL zUZtEER$K6ZyzjYYe{R}IWxg1qLy+7?mc0n}F;Dt-v~6xBgXB^{Q;JBsm~O@)C#P$) z8#}PW9zq9k%&mZtm20}ZHeN2rCPhVU#S61r-w7bpY+PKqQdKqE*O8-jL?4;~*4)4haQMI-?RnJ}p zWr8*_te`#D+uLAc+ZGWQ%0FC4z=W-J{m^x9o|)f;TytIi1l^-AGf%h2RTKxnKPudI zAkXDl)Qq!z(2z?%y#F&vpz|U9wE}hdNf+=S@vGqaEiYIuwc(kwkw2kSrc+&*A@bO6 z%)Y`!l~|j30&Ak2*rE|0Ub{3GScifUQ8iyY`nnJpM=W@DKNLG=rDmmK@A`di^t3Fq%UQpoL=|cR?X92rBy3Ac`Y>dDS!rJYRUkdUIe!BL|~@Z z+B_A#fbVp?sRaXhVQz`q5*7AZ3OckqDl0jVVXMEo}Y{jFZM9BOt_{1(G@ zhEdIJ9%JC}yZ&3h3M zq3xxAQx4jr^hz`z{~^J(T4!(VqbCOlPw=$@{F-g8Lps^=S zchILAM0PesTu#hL*vkxoRy@1?TQ`CkL zkUjKW^sNCQb|T{Pbmfq=`b2&YQNmhj>mcs@(2Y6OXZN@kEN;3z7raUoh`})#3PN@1 znW)aHwH^;p*C`oMC#m!c34#lWYwk7r-L1ClpCE2fW{m3!7at+%ZebZiFf9Y*P;`;LLn{#N$y;>}dggP-xt zl!f2R&~|Y1GdDrgK^6!k46WA0*?L@}nM(rY2bx0rJ!Fgs=Oj6Sa@2=@Me>A+7LkiE z0Fq752B1xtqM279G2C$>Z^~@bqt?7ChI!pKlm~3750DzAa?Ep3*w4bOEiPq}up}`={^<|nv(6*ZE8WGC`(5GF_cGy%(iTt$aV3nE zXn>w@(yoI(SYdl0kWR#{7FW#0GZ~9^Zw~|X$hyiOv128&F2afN({kTEydDvpr2nK3 z7GlB=%#C|z13v0NjHuHfAsd2}>IYO;?i11~DQMVC4T;_8 z-GT^h|u38wY_s#bRu({$N!1C5t2$5&>E|#_9J+M_(_t&2pM366%^Ro8?m2` z`c@L;dV8~1$tZ%z2*OSw42&T^Cb7!$;CviX9Y`FUjLON8e&d=G6S6^u zg9!_EY^AvsI;w*cJrmxxlFnvJ@&xshF0J`$8*@HhnC~xhcK!r&*mg3AnGO^d%~)prBB-=Rba(e0$hyN$9j5qdtB7UiY-P^0_HD^zD$S&$c6 zIKg5^ICd>97EwK>2k>x_FQEfJX@5D^I5GWBiJj#2Fv{{)oDkCNH3kHXV8#|K!sl6> zoZ90}K%__q-h@cS3Ra(KLg{%o$}2<}{i~ z%%$Dh(@RZGmK`C=9NR>gDdM4;P)vS{jLiM*#0}zYe=9g}J}rw>9_rI*|Mgb_1q08} z`)(it0|0oY|4+FV)Zdq@p{FOWUyx$76%}s;a{&{Bp zMr4?-t2`);LSsVY3Pj`^>Uz21D=5Mppumt;=(V7f&sFI7CH4h_F~E;#a=!XKMkkvS zFKBl<5e`>0Z+a<*Z7Vrrq9fVZVk_U&l~$9 zS5s9vTXbN+RV6MTCbkR;Frt@fA;3K#=+>)Sapz>LmPiw)=@C_H+JYEmE-PowQ*{=v zhV2B_DV2gXXOoo$+&qK_U?dl-z?x`aB(*%4lrhZ(BgOR6sirIT!&@FWBlE$_QkH5d zSkWq3IvZG#X^FFk>Sh7@Ea!;Pl%Bpe99W+(q&N<62 z*XNVv_=EBY*iXIsI8lvrb>5O|rZ|y}ySR6IQ#>EHCcGTW+gJ>dovf4ey0)rysllX! zb92k9>Uy6pTM8q^N54E&Tvn@u!U`-g66Rto=qV-b6BG0LRA10IF1m}@%TWk!sEKdL zJ!qjtpXGjKAEqjxg3Xy^!Gn+lDhtLoh44FIq#^+yh6Ei})!;@cOAd%e$b>i>G7^8e z5uhm)#4z!6*(B@rNeaYa7(j?CI`g6jEHReQOWPYoVj3w-V7n3(6f8s|o3fJrO!z$t)(YL=rd)-R$EAC|0yf{sKxbbVnfK$SEz3prg+3Z1~L| zZHhnF&sCgV+RlYRgBtYoWZN#tL{jIi+khE+a_9}bV(T<{(}CKig(s>IUgrt0RX)54 z$Zj^vc?NvA@GnfxKTY^vRvl+X(W^c^F*8C^cTaSc@~Qc+kCBcsY=B!UUH9rUZc+ zUYIwkmoSP`#;1H&To&b{j4Ii=!MnLZKn;&6)IO6z)3S_U_F@cHF|V(rfEzef-W#JWDw$aza_k&O8sEWxFfFg@ zh*pcMpMqB~4|UafjwXyv-XhY}y9rHfbZ8h^Yf{rPR0k)kCXA1lQ5YRBB2wGD+a@== z4NPowH5hwR_AM*b#%C3VJHCNi{XI($1qutU`AFAQD}6@Uoopep`F%<3UNk~KDo>Jj3uJ*} zhJL|xpep1B2}5n*&xSf24B#~QvZ^8_)u&OED`QYH1y~G5-}Yru5iu>gbTsMIAt*Ej z3Aei{fd~R$;n#_$?wMS26(jBi-?gf(M7xwM9R4YA6hGR1N_!eV1WyZxYA`Gt7u}EH zprb}9!4pZpjW>_g?u=GWFVj$A)kQ(1Dv4eyF=M$?iO(-e>I+s5TS15R$bgJ>s~7;R zjLF<9u`VjHLPn3Dw-eKVlu)8LEB8uI7Km?8+7=arf*TQvB^ptH&VU>)s8kp&v@ljC zktT;8AcpDUtW!42i0W>mjpyF?+XzpOr#S+*dR094>tTh&_Mf*SD@G>Ms4@W0s``=_ z7VQ9sC< zyqP{ySdDFxQd;aCFM`MBO+dLOx_xfGmyp*IM_^yo#bK&Iq_Qn>Wzuh&PdC(M_4aF> zY)4VE;`Ck~nw(>(>&)WuQa9P6V2a}*ElnlbHmc3)cS>>`R3~XxtTiPNMM3`!0vn;U z>q?mH>$tqDKB?-^7K08*4*xf_5(qrt6C4)xl-gxe}YeUBN+rD;OOPaK;%3by9 zI>znTXmlC_%TpJGN;hKlsQg%7LUxpme*`0Q# zZj7F@f_>gplQ#p3YUtTqBjPcqnvK_v0xqx#{qTJqT=qRgEhgU*GydPuEBqQScj=_B z=tjS5@Dg&iD@NIG*cU?Oor%Q_65MYf(BL#ZBUc$2<{4fXLlAg7L0FPBUzuG^yB0!r z#)Or%P1O}3dtwIPe{;BwfJfj!ZB01(Z8ZW9ZsQlkBE^vS2Yya@3vdH%9s+)HIppL? zS3_m5#GnvyKQ(J@w4Zzs$yreoi|~GSc!pHR9WYKR_O*w~8|<*UJRIQr6z_j8WFfK~ z;|=U9KAsH4OF)S0LsMKD`QTyWwDJzG$;c~MlS#0k$i4MrIc`Rrm(L`O-c;a6_<*H|nyYd;;CVm`R3z5~{n5L;QP zCZ&4%4g}cP&mk7?+2kZM<>fd>=0h(fSDFn3^ga635UTIqq~kq(ab3rcXlg_k^li>Z zM!zxLi1|UYJ!G7MaGil-Jn#hX$hG`N_@V0a2uo7N zf(FvFLoa+1HPE(?VsiOhh5CU&L`;XmW{+?wk-G+fTO=Ct=Y$T@kb=s-?oVe_6HNt% zj(w3N`{6$QEFiw6o_16Pe ze_OtV8gJQJ@U~M?kmHxQ*63dSQZSPAD<-(Gh~2cr7c3-_FBoTI_|B89uhOXO)uo4F z`rYX}8s*0=6HA}V4$M7c$`724s_^l~s1@p!lMbU>>fMv5caz#7Yn^{2t$%u<@i4=j zZf90Y%#N8uw506bKvKL`+)TPpzOmv@SKN#2#*H^u+*PiRm84MthFW|T&7`T&X2KN% zOiR213mlKvm(7m}LnT^NFroHH1T00E+T`rQLHHS_{>BjFv||3^iU3B`kl6tpda^UP5kWtuv48Dy` zoIQgbbn`YVf*l?ZZEdV=J2|X8omZ2q0p+^aD}mVuVLpFpWUK$6hk(>V#+J?-sk+!yxVl)SEh^FXF%j zQH|%MfZnP$o#Us2J6kER7(4=lA9g#?60GsLmpFcKumZ+|o9@g0109xKeKQzKjGYP zk(wXNy%#3-M*=)(248zqM^DpJsCgpiJq;O+OVlfPHvZB9sU=;1M~F#0`8}o-4Cki-+4N1UAG-ycCx_-|MI#~oP&3B)CY=wwpj`?0- z2g1%qWqfYj~SMr9y*lCd(TUm|Mfo+@& z2=V}m1*+ji#OK)u`Dw+5*p#u!S;1bDG|BR!@V*2cE84-9MZ(HjyZ9aOIx>IMfXr{_ z#mUhOHM3!YIy;%qX5pDSJlCKt(7Ra$k)3`t_|F$_D(Lbg+f3_1_8oAghoa|1%@SpMk9v6 zW<;VhL1x5;BqP9NCV*ilLnR|2`Ax-4LC?xWNz6*c z%0^Gg!_AFC$&bw_hEFR%&MHj7qsYP~%)~86#jnCCAjT}B&L(ZhqhKLGjV8u~!$(aj z%KTfBhf{%vLXL-$)(u9CeYY9%)%$$**nb6H$gR^Mk}=5 z+CSMdFv=w))#p!+MM#ZhM59$gyL)tjPkgC!V!L(fkXuH-ZSJ^7!KioHtiP37sH0Y> zvq`9zQ@pqNA0LNUKbyz^&t!j_v{2`~D7UhBpXli5kf@~a`1Itc;JDa?^tiCpl+=LO z+|ZP=(9Gu4tir6^teD)&sJ!O%{Ib-NmdwVc;^fextmKBQu!f93`Pq5Jd68v#87=wI zt);2mwb>=bB}EmDRkf96_3e!nMGe)pZFQv`9UXyLeIbRzAyxBHjmwGEX%b6vgN>Al<81AEoIQx*Md?R{e{Bda~LJ7r@BRkNq9Q~MqB zXI<;JeO0NWjhVeQB_pk+L!C|YU1bA3y_3DwBmM1*eU-~2Eh}@~`%|r_^WFV@{e45@ z!=uB4W0T`U{i7qJQ{#ivQ&YneOOvw`WAp2aQ$uqz^Xv0t3kwVLiyO;pON(op8%uK= z%bQzki|gy_Lo>T$t0$vd4@;YeTl=fyyH}%ok8As9YbTGJk6%YCqX!#{``c@0+w%{b zqX%32*Zb3F2kQ@elaD8>-w&H7C#T0(_m}sV=g;r=S0`^z7xxbjcTaDB_s5T~_outJ zm)EcN$M5fN*$iI~003nTaUp&sxAm(pC@n?R_S;xn3K`9rGw=1ZYdAVP3( zi-2@+erY)*f>Mb8SCjA;^FKATy_SkvZ#^6C1a!xsV$y0G28cY-^5M|+hTZAPa!hKC zFQ?A-7$|`~(kXD~<82Hkt8+{EO#y$aenB6IeAQi8VJdpsxZ2RQgrD6k$COHXEz2ZH z>JFY`W|ity7dBvhMa6_7IIk1~l%vq)_X9{5=_E4d=YPb`Rf{x5pD~3@BxP&)n>zp{ zW{gj5L}At_jPsXFCT2`@GyyhcA;ioX*c4!#!8b+6Y}(ntCxMR_bxZM@QZh4JNFTXW z?v$Jf1TwD_ft*^HYEi5dmpwQzL|+fch{P{Nm4X<`x6lMlAKvmc(68tcjb=3xM$@!U zj;%JS-3bd=L!(!EM8ffzn_4#t8s3F7@ew56ChO<=!!F3Ju1SN*!CmI-^PW!+y-BF>y#_IT6Hec+Y&|&a;`IDi4)1TEO_)%XK`z zD(7z(!O0-Up5dU9UNOWj0?jJegWrjk^8cP4%HH?uD{2YX=;>xsgHPNhcb(5y$<+o` z;Q`|=FRJMq8fnZN3UZKpI|TgQX&OMtvbs-sbcV2io?e;mUG+f~hwNM(x~g&Sb~g1b@mrw>(6s};%RcjR6<7Xe?;;;H zOI7tFtZYt`3xR*jz>h)ZK-hHN%!S?D-zJeWe8zZ@O+ivJo!&6zjWCyI4T)oI!Xp@0 zFBa+xw@f$wz3)btJ>d)S(NUnsX`jfL7uV}(`<9M=V?2siXV;nkNU$Om9K5Uvl{ z$0a^N=2ypuAgMav%o>kuYfh3}_u@>0UBDFxDkaZYy-sAHuyhtUzxj*3N4=_mu)yq0 z{ni&E=Nd1;BV?C?Z!KIIXN+VXEa4X(zz4<`H|{B#S~G7xUKz|YUuz3o&zr0Vh*Izu zfb$>jn2ysE8BijNVJ`UV6e023SCF0-*>eQKEFtxqGke?_+?yX&49|R*eF0jc=<6~t zZh)^8CqNhW>3Gx5)Cod_{eJjGA@FlsUW-Ns$<^so)4)-k-q_kYK+@TFU+gvT(eNt~ z%PzF4wXaIi$9MKy$yVZKIFCEuywKl;GZ4-N3*-(%q@t7B>j;e8=AzG6rQH)^10uM1 zX3D6KM8_?KI6Ca5EbVO$BRWrS{c}0n$7bkcifVN*=>Zr`$oB2T%fgTn^X`4kL>G^2 zQbKdTHSV{wWn*IW- zovh}q_~*5+H;o}X7nhr31gzHWcy}mxx1HQ#$2jPHtn`rhoZN3NorFoGQl|&T@rDru zu##E&9w|kib^GuW?RYwW%CoU&#c4zb?#R>_xNV}Asy}-4c$VX{l7;x2^fGgfQN*YLf`Gp|K z_bnH;#5UkI8m=IZ&6*^MLS)B&0%b+wcEh|yByH%_@_3uUTK9F^oK>1}#}(>nKy-IS z-ti}J{c%v4p!MY0WSm+DZ)oR(D6@{*WBGAWQNtG_R6de*vIvu*G)DkG9n&iOyKnQ9 z)7}Ksd1Uf5lpyk5|B+Upmc?QkMm2;XKg51HnbJhzyiQZzv8i;ml6@{#ghPShA;O%| za!7aTbq<==1MsFbi9z-ZD|Wi4^7uR`!-p;Cm5V~82EM=-GPKl-zKzApI}`m2xl!Rw zvy{Wl07QZXc+(LpsK)cvx?Cp8=NcTyT^O0xbQkSHFOfE%$?HoI-FZ1`pmdN~^>sUy zAEsLhW?%|o5&R+=E>@mgFK^NAChJx}i7YT)-ZJWTA~dHnKCq)EDRRrT>5qBP#R0%| zdbAF>1-Q=}vXM510QLAgD!}=@aj-@LUlm`Lk4%(E0SCx%+2U<`n`1s6YJurw=ibRY zl>Ge)iqT?EOuFL)vrVhJI>ZsDz*&u0ssOi)ez=w;ug?NBtAKUHbc@_|N=+B(PYa|) z?NbC^HtrJo6G1tq@?S<#(hH>;qQg(bJq$kUFaiCd-2#};8wKW@h{-b9XA6k&q_HTl zXyta#vbjG;?v1e+F#+22M+wSqrzen0VXibL@TIIVaPeaP3H*s@>-XG@vD{6-1Uqwi z%@^K$MJRO5h~GpKkLqQ ztCd_NtE^@^@>l6k9a%B`JA&_{@;WKm1D2A-I|}cY=_8OPd(wGC%tCIN5oFVp$AawM zz$vAUD1L!giCh7@^3NbM|D%BZ+c!fHCX6Q6(5D;Kd$S6YYQfXRux#}C?G*3q56k!) zLpt*8uX{-2+AYrLo)6O_*3U;6iYoB4v9S4#>&SJ9Dyj5u#hR#hGbgRH$4=`x_xsYA z(*egPgz|HSG`^t6wuX6uHF?H3Ip64*$ef}8yZ%hB39YTnHbzsLlwJnk<#G7NNuiLf zb@jgm0wI0es`s<+8K%7qmK1_g=_riw-!mmL)REO`W~nXTCZ(qcZiKc*#kN;O0I_2i zCUdrKZd5Rz5R8U6{%Pg_8KwivJCm6h4RD`#4akCW_p_C%?yDT8$CY3(2K|*!$!#8L znE@6WxT#MTr*$A)Hue%bY=qk!6JBeROKSBs!wpmdUyJOG)XvheoQ5LH<>2Qzp}X^9 zQ0bvGthV$49PgWQri!kaZ}(kO2v|l?&KpGp-a+sFv6udTxZ(d5%~A*~{LfHQYd!;l z-I_JcS{Yz;r8pO^E!ce_dZjGl1$XAESti`aWoS6zy6S_DHR{X7cd z0&N-39ilP%#iim~lyqn785Xn?Tbo3aphBG~t2B&%Ij0SCsiz)FZJL?!iywJl_J<#p zqgwa*RxpJR#%7oRy6JLAX6Pv zvB}7$hwJq2;_&1NngvD(#s;V5v>1Dqrar3{;F0h5xTmHzaR{a$6g+5QDA0bF=te>x zBom(yc^dyJ6c$daiK)N`uS_QE*=c3&k`?APV%1VaQ7QeBRI<{13}(1--*9@Or@y@0 zS6(HXLb;yp5>?Xss_?iRQ#Y)q9dTz|U9Xl4r~HKr`~CFNn@1=n>D>yVoRFSU&|G-$ z)DYlqrMBl`_DW#lUKj|emZ6R(Chr&IR3RUpUt~;1?JH^VOakY#F~~PO+b@DA(J*Yj z_>f`1H}{H9oLC7^3ecVJ0JMC`zUy)sFwTrpYg(GGKjSmt|J>4=4V+@66nd~N%jrxK ziS@9dk~>lZO=9=xHg2$nLs&{zM#gnDloA34r8{PMiXTU(x2WDF_k|Xj56IQt? zeIc!r`Z)RXw!irkT2q6~WlPTmC#zbev1)v|*w2`?8d+iYm`Qj7ITs$`{Fjd;b9(=J z_C$3EYq{Pf96Xf5DG z3zsin^YTN1?n6g`;yt2Gc51>xYvg$I@3gWhayZZn}5rb~=X zo9@%n;7we8@1Brlf!03@ZrU7*mJ;N&6m4~z0>kv>_b2-qM%b0X`3gw^YjU@GWh*(B zKxiEO!Nww)Q@fftNt{^HL%C;LVi~dLdGsIVps5PB$r@P8F%H2h=`Llvawyq^zlsXU zl?PUfhk>G}SFBK-H0;QwX_7<&?BXIUsh;vnBI=_rSj(k?D~nafP~1Blvf^NeQ_==F z(kY*T=BbZouZ+F71(NGx%i%5>mo)%-nnBmg@w+e46HD8n0)xL!^_qw%0Gg}y;dG~# zmf$$fFD`hhKU#hCW*JX~M)W6Ja$%&S%Sto?;Nh zVnB(RM4z9tn#P{nB1z{q2ITIazX8sXlb5>VuxBYph90RSy_N27YV&0+j8pw;!rHg* zl1&hI7JT^7b$faxt%vb0Q-Heji}vJ6TyTEy&mqQs@07S8l3=E%fmy%+ZU@sL&VFa+ z2AB?QE@7u@*o)mMAnRaYsNgaMUrI^E2FaQLsa174CM^4()l*F8*Np*|SiJ)owJg0B zC}xEP-V9dcsZ}nz80&@`rgOOM0PY)H-d<@XH`44K##WJi z3iz%oIr_JfF`SW?fkW6a?Y+I#t`0D7Pte#8mrDrcUW;xZiaEdzcRm?Fqm}cx8$MQB zOnFmg>_BQzc%(dPTQ1>S3XV9z2Q85=-eqQdK}=+zd(u^*%O5*Ka=^dG9n`4U2jkXB?7Wi}R(Xla=PS}e?LG`EA20qyeeW%}z)EmhTb_-l&vgV!~ zS?bv~*)xN^2O7d|G~M@?dBI$R75#PfmI0B$NWaxCKWGZFy^vhsuH7r@ZK7>wVzz9R zm2R{SG`Z{2KZtrf45V@3@KhJwRXo2PK53VhW(usXX@6Eb)?2n((nUoDhg@>F{Ed`m zTqEH6M-kICBP$gnF&{YN@4p9ZsbcjLC1VGTk9p#|&wS1RZzgwvz1}@Y!5`8OdgDQ9 zYgofy97|K-WbyAvS-f54JwcaSw`^iRq8O66!hWDL>G6_Y6%S?p za+?C*R11J#kz9upSX(6m$zpE@Ik%Y zb;@dG=y8>Wy`7KMB+fETv3Ij5ZGE<9yUE-{q^z$LWNpAz&^&8|Gys&T7qe%i)V)FQ zxy1sw4ABE@`w1d1`fH;Mie1JQHh*Uhvt$!@WiIxEcsU3k+q`B*W8f_oA}ZREy?1-d z(*qbGx1kJ-gDXJX&gn7cS;O5d-Ok<4r$_o4rcl<});a5{qZkd+`9cvOH2H;wKPE#U z>?#3yDnlfsH=ifob^hBN?7&?o&|1 ziZO?jd%=L z*<`sidT&PPD*zd%+Sk0?vS0q@i%8N?N_UyPzi<|F(0ZNhlZj(sYxiIvZA92#S%=r_ z7jq+)t)76_*}W8ri#E4MYqgJ88agj)w&HALsIYf`c+#0kCte9ar+W(JQ@5wb$AqubrsN`1`sf?C5wt`fSBPA)q&NKuZ>FON<>HE6un67nZeA`yad{uEX9#@Eq6gzXU)CF95x@2JX z=7ai0=a(MT!e})kT23)pD}8%;T?fY9dD!CLzlk)z;REraxB`@x_6avsf()B!Bwx7c ze~~6MbMI@k&C%`frf|liPH$>)>Z+;Da?`%%9{SP+z5AKac}Mk0B~cq3=>50kPv1|l=?n#r*(2``D`@uaR}gl*X^Oo4t&gJmXc9B3ocG?pa4hnahW>v_%k}nc#Z<0|;^9`0`B#7t`ueVq@)(l5t^^H! z{AgbPfWtJPLT~zgB?LZf_z@T_U6y?Gbu;wrpjdjxFmut2IjmTjxgTUL4{lJ28}P2x z_-K52oI3z~7v;Y_|K5=UFk8WdsRr@L9C7$;C6x98z z?$AX2w@wlC|4A1AKl2c=;Q1x{^oq2U2ISn2he<(FP8)NP&H$Sk(xa|;paPie4#Ek3 z#0Rir!ibjlc-HwMz$wA8vBNu&{6O2KtEV{1vfcr+rZj-0L-B7^O=VJN&)8bKqyv#^ z4~GqD>A=>O$tbkEZ{^^c!c7?{x2(q!MiLX-`K1tTar+mq<+*6g5x&IQ_6WUkihH+? zc_ot4vbJ#aYgYUSn<7@3Ai8w+2YbM^-f0cSAUb*pf|=hVf6M|D##C6g=>FS98)iO4 zrm8Fo$-+rN9ckX+>Y86d&N`g@;1UPd*Au3EniRkj* ziYzv?QiIbP1GxzRM6O>mxY3 z`G;1HTwk!D`e`5}roX@JAV$Wb-6@vO_I$680lksrx*$BMEutK%{F%yw5;g}lo z9#RO)=3AdFTa$EK#EPSF73{@-0b7DylYB!Gg&D$U&Tp_{nu`}?FLp7f50LkkKQ+kT zh9UC&1mW*OdCGw;y()rj9}3g~5E2^D^pc}0pyB%g8m2j*m!~W@MZ~h!rR@^B#d)61Bo5!ZhnG&gAnIevTRwM%vOXYP z%3}HS*t8+TvCDnMiKKUw*Ki!p6C(y#; z39^(=$!yFt)#`T*^Rv*=V6dEF&09Gl4by97jN@FeNVoU-lu!NHBobA?viPONUs?8_ zZz+Voo>~x@En8eSvPN5ocy+%Qy!qu!(^J!nNro2(7wJfbH53&Eaee<+X>S1)SCe)N z6Wk@ZhY(0`cb8zn-6goYyC=94+yXT2?(Uk#-J!AI(Ae$Fd^7LN-0!>h{_C$^y}G*B zspnKzpHqF#uKn!&!jkACqL@ghv=t=${;xHd|AHqUZVTKzjq1a51u=j|8K=j-UM;u9 z;}cU^GzE@!nTC58L$b3FEHWMYqn-pnr%3X%LfJE~-Vb^i!K(?(b8t_MnH47VjB4LN z=)3X)U@8Xa_nkj2(!vH(^%)nNd16HmeTeoEgQD;|dyg(d_MPYe2UY<5rY*J2B6&u9W2-Bvqav&|N zU8{#Oe*tflQ>psh@8=wnM>_Rk3mK8Mu_lR(xH~?bG7(kzLx3hV?B`D=itxw&FWx^X zU(z$|&6{17mR*&^s;OjhKBv{a2M-o7eFP%1-iUE^M=N~)VMo%gP#8E2)O}^_X9MrWjgSPVU*a6s1>f3E#L_H zu}_wRqwz;g1rQYR^)h`tIjzBA!)A4x##c)fWE#wi*%5&Ma-}_7w2oUa1AFOQtypEQ za$`J$(tlVy?ci&LqJ|L51c51=MuzeLZ7Q3#Amkew;1;oY@Ua@rTd-F93r&cZHu5ll zp-DG%UJ5IEnplXVROqL&;=m~9Xn@iV(gy)6Zavb@$HtHOK3i@6sN6Kcqj^M%lJ5aI zKL$~F&VENLY~cw-9E$0M<+qQSs@lgC0W9ZMiXy4!DAVa<6q|ZzfYl7(a1H*5;+&Eeuq}vIUc%Sb101Ao z#Y{R;%jIXKTCjCbK7%r7*PI?31=4b!A($vKQ?@j2nryaACp60Dum&r{j*=>k0VM63 z_rq2Sy#ZdUU*Xda;syCNUct9xW|ioi6m7hZqv=G}p4SEiIhPsJE?Zo_I4|DQqd*|6 z(sxE1aun3YBx@_H_V_%cpzm;vX0$LvVhFRimy$2Vgyv!&n|{zT zh_wk^jMdX$|9acCqm?2Gn94id4+oU8nLTm76}wrtoYEx{vU3qs^IhWEmo(^0v@x^4 zY!P=oml1r-l6~emWD6&Q11d*wcV{YsUfM`M2kZ zU>=0o&e9N?Sz@g(P5oU&f%^+|u-YTYb(p-kV# zJKY*z`_SUN+5;x?C&E%xZzU0+*&fJ9%=hzDjMX{0FZ{;q5Z{Xpr^bmL^Et;smzsU$ z^$2Okc-lFsw0C!{Q|H~+7%QJDd!JucKr^rdeY;``xn>wy+o2}~L+4Fv+&8l{7w6-+ zeB8Z$=FxezX3!ITAB?FB|Ert+PqVRHXpIpfn;!Rm{eu|sV9%p8hLR=EWihqtH;?ms zB~*ipjr`r|=pB`z!6?SSiZS$sZAAvC*5J7s?x?Z%0imXEJEY2nmsNMa820`PkAj8HorBG*X6`;pJ`=fxKX@|pVf;Xt&((ee zJ`pLl<@jQIt+NJi$^D9%gK=%}c0Wf5Rw!M6=4vrEvgO^_R*9ld8!}i$+7-dtsMm%s zLLB5e(Bj&-MGS5x07YpAko&`2122P5O8Ru}Il{S%Uk}ji9^^rdy zUnuC4g&eqJR4$!qQ9fy{Zk4BcUD!<&r7qFm{q5F#@gm+d&6BE^+XhqiZGA9d05B&shM z5!Sgh(aFg9xQ{NJ?ACW~efj&r@S=8;3}_+Ed9gEeEp^$c{A5+(&d%87u~(j=)q|(& zR4txv-);g3KTL(N!`h)AT~L@FYGezG!&wn!b#D}+-zpP%N9Sz3;$G-<*%AyoPdS=< zTnR2=Nz`ot$hYl$~WQXqmn^*B?p&V8RBz)J`u{jyY}sj;;VNdct}x@@+c??{PP( zFCxCgw$_Xv(XzFuy2Pn_jUC06jek0<-|A%zFB?CZjV;08%b0*3g-I>dJ*8E33eALP zppx5b&IbH~E?|jGN*hzE=~F=nK_M(G)-*;;JqnT;RFyBAmbr_crQ5G<$-{DOQMtY4 zN=hsD5{VrZDQN6c{B)fgY~TOJWC@UrpC$%lR%w@yPL6HI#=4}~1Ddh`NbV7XJnE`q5b7`pzu&*SVVKmd%(SL$vUI+| zC%)07y{0p~m{EH{(gQmnpsO#n{n${hz%gC2sJu#>9d1xUbuL|0u(*hneGJR=Rm zpuEv!3|t^BH?62yvipL|7!gZDOp0e;?k%MD=2AP$KZ$VF z03&nfG5_xx?*d$ z<7hwe%1lLupl2HiByObR1{+p<6^+ljlfh+7@2K5n2Q{SK1mc)9nRR$GJI|@JRpjF4 zeqRcE8oHOtOWlyuj_r%n#?m`s5j0WmPLU<#u-Wj1Qa@j5knl*X@MxShU)|z1Ty7&K zUAa3&(1jLaLst)|3(`}uU2HJNY>V-?@mPPQuB{RBz{X|q(e7)b{%Q2sZRPjaeFZWC zAZ|Gn*W`7-hY`f*i2;4i7UsmcO#-24X9tgePmN(%Q`D(l2bPZFVyCS}!;MUMQu;62 ztQW1D`OQS?w%6=2&}0aFhpdz}XJ1t}3V)Jkq+R?yz8|z34OrYSf$5b7$ogmnR(B4k z^^2tN4t2Q%i!3cB4$lryT4tzS9?t+&M6Jo3dQslhC1*cctQ4Ss`{GiWo`m(Il>1B3&GsQxxG*ITS*y6VbZ5erF+eG z9izAYJ$CJCea~iF;b`EZAb4K?lrvSB?WcgLzjX%qbI6l`At#|j?cJA>WZ zV3PU4bIRc6dlc$gppUpv{VGcLX%&4#8ThyJ8wI%LQFr#V3qX($K?Gej3i}+qY5_fv zLlTidSK;x`#rakq{1}XMCx#C zN8v}WAn=o7Qz3M%@k)x8GVB`vNFn0H2Ebfq7H8bJFQPL%jQnd#K`L}h#D$-j&$q-{ z_|RGxwhs;tzg_>d?8*s}bX{={Oez;K8D}C>j~bv^SLj>U_mKlvKN+>=Kk#@wiU{_E zGwh~3F_`g}ZU8_Z0aGZh+*k!}M?yJ8P%pz5rsQ&pIUBWyteKH;U)8*XtOJ{)Otd~g(4~KJ`ydz+5{QN&=ev&l zOXiV+{5G73+-~pR$bS$X(Lcz4|6T>1(}I+A?%>*~a&wiifCkiWV4`%JBh7zc63!XK zXk$>$QG#paY|`cmU>Er}{pY5b?LsCh>nvqYTh>~7R;i1+bolZaFSPj77=5wItX=Yh zS`sGhuGx6WB!GGu62PDufDZoGQS0Pcv#MEpoR}G@U{c&=GoXjFs43K5krSI=ev*?Y zbH4r8)A_*4>|X2`2Q93j#Rkf%z`?+kc{dB$!cRiw8=%j~64!xpfI`M=40k+oD819D z97`wKw%9zoJal-1GF|o0&W*~98nhrbnzUNGwWL{l7%Ss$!#N!vC>cKM0#c$#g`aPb z_u?*?aalX-GSG8Xsw2Gu)w30s1hVRb$;v`SBWr?#1C)S4wREb8;l5dnAJ>X^Ip7jr zf4rsdJ111iGfI8<{ptZl`={3nWL+}Aw(Fkn+bkV@+duX8j0DS^3f55Fonc5lwEh*uaG5YZ#b zoG0;FD$z|d!k}OQ8Q?$duy@472flB_3HNB?PW}N$t9r(Fg0`s>$oZ&!rv=Zj9*xZn z@U|^!nl`n#wirUCBq7bGir%Pu0T4G;h}a^Oe(7N7R7R({pZ;|BTj2U!tN}29;1$WO z1yrL%E0+V}zt$}ln!~Ab8rl@1g@;>w8ra&Iu^g6>Z1Lv+B?{yvc9d%zzPW9lK92`e zm5}f1n8@CKnVv#=p8X!1^!%>+*~XxYnZjccDanf@=F8S=8YcLSCWfFmMwI8fRi>KF z^Yc`2@KB+CNlr4D2b15>F&DdGXJ2#P+A-JUs2{eJ%HvtezL{y4>CpM8@1sXx;?rTF zSghj82|`e6=uGZ33LyNs+b`gSRI-8p69NJ!_Yqtd0+?Irt=H#sX~Rbf5B~mJk6Z)8 zHYG{`H7}Z$r6O3PKoB3R;ovRnx?jps^-Q#E)^~+$A0_af!B>rca%P{qpgFP<6TkR% zZinlB_Zs{RW#OkMr%XJ~~5v zPV0AbPw;R zuC5Op#~4giZWN(s+_L}(-5#$pAMZd?vha=OZ|tk2&M`U@{&Z*Z40RNTJ7}Kf+b+)q zrM3Z{DWnB~P)flrxjiia|LaX`cFaA!ev={b+&lf8AVvE;`A~{ZZ#Rpz8BZ-*%(M&BmDc2G%yKIO-$b17nd_N^ z74zA<5^uj8-vL#NB$7iee@AXzwI_^wV3&eO>eJXt*fk%GSGOB!eD5X{4FmyW0*7+X#uf#oMWTcLQWSAxqm}-uQ7>9{ z%1K+H00qSj=VVrAFWT}BhG$N3=dCG)@TgdQ!@8ySsoLMJs+bF82h{jQpGO-A9l7xG zmv%z|yGJ<@#*76q@<;|vv~P!=(lRru(0eSLT$b0cfJ`dK&URUAQG8CwHw}$lEA0+b zSx%8E;Orl65FVlIYhdRII47Tro+%dOzca5C#-Mt`36kdzgw4<44WW)B#*@vHAi<2B z2N0`Mq$}K63xH1yZ3|7V2`g#bBQ4%1>YUL=%!2s9kpN!FTzf$JW>=@WipTBTc>ts}0CE-64=kIr*3^5U~g4suj~{=5-F2PI|nfQyvS04y4Y`FfN;)f*rRNc4&m%-+amz3MY$xw%+;$pr39ArMSG{mO4meLV^QzN@x`$$ zbG|tg0`m2-RpU_uqH9ZIy*hAbxvrBP{Zw8PsJJ51(#+gG6!6n^N#0IQ1 zwW6EKZNl0aaCi~4Rs+a?u?YotCe;55d@O%BFZRNH6O)Euxg`1WPUG!5p zMrH)tw>}(3tBe5wC5CXSkN~ZkLZYKFwt|a-LR{mnEn_0%87Ow?FhSI&- ze7mtYi;%Diz#@rOjFD=l=@gIQ_|z2Bhl4j{SCP{9Hpo=QVA4sL8Tf!_IA9S61v4|+he!e)!EjmhbS0ZHFLFdjJ>(T?yfq~|K$U%htUBD zwmA3Dx8}YBAomjV+9wiD0OXXLPtr zY<$OL3IOyH>nt(PsRLt1unZZ7Vz<9qa_L#hSCS}ch_gmg>e0q8harat6L2F8`$2Cz zNK&S|lD;<`;I-6EF!A<%5n(I!AJIv&9`b}7q88BceXvAC<9uuJzk|HtDIMPkB%@ix zRO;xRmH{dykRNYYvG*2xc!-nM1Q4dLK*EPIO_xzr3_4ozhXO2?a&(`!quOo)Pr|4+(@4*?QPsWwk_fb+eO*^4LX)Uw0l=SO4mB zjzqZ+&74YflUI6mVrqTECA@bZrg7v#&fOPOGDr>dM2@k_ayL@q8~1kus)5zL-FaT= zPxM>^o`tZJ!=9()`NukMPAcE*_<0a78TP`A!}QM1-arv%uwH#-kL*2^mRJYlUvB&E z>A0ISV!RG}Ui~I^tkg*4UQB4x@~vW0sbeo`6mMWJ@cQB>ant&=pM2GUSu z2qK*`pWR%1(<9X5cwLFPpG?dOTp3R@h2y~}zv@{w^62B|iS_;puqjJlZ>14n;>=an zRNnBvm$EwUqpYGv>x&0Y$OFweTYSXUpR2UvP16I{$yo658njj~K02IibcRX73)=hn zZQNqK@NW)M^cbP3@~y+3pln;5Rg}eDQMAz_d*sn$;Ju$>u>KvV{jg!_BC5rolibMT zs;6IrUwhpDIc4E!{^_EbKq4(GRV}%~ug1#c$cGFy_;*j8eURfhQKOyfaEsT?n?<`9 z>?f>-#^sYf9n9or;;H;FcORR@E?rn7xSm^$6=TiOVe|fnW92)W4>L4Q?2{sS?=Y6U;i9_hm z-vu9+?1r7XcB2}8&PXaJdVpCpO8>@{xYW+ccuH=fno4+uEbex3E`fs8D2F|Rvq>|} z&(GZDfR+tE80A~9Ot1V_WzdavQ^vqkv|(>QGOlsb*D<%FC5~(k2rP7)u?`*z z%;xf?;O-3Oi(x0|0=$X7d*;hUP zlYM9u#B7J?HLG#_6G(DB)a&+Q9J~UI=KOtu8+ag>_c@a&m41?`I46gWu+OKPy|>rj zjTbqr8{}!yArgkEJ%9pzTV+0e zSv=kUkYheP1m-`4ViLSyn%i{s=5FF&K%vf~Rvqp8IYBq?aH(s{BD>68)>O5@Vuj*5 z=kfEl(=EK~Ii$}%;gKK2ebk@b)-Cmtj(L2DN_8=eadm}{dDA&M8li`EXK|Cx)UPgy z(b=p`EtiB&6_lEB~#>XQ+l_%O-`6fmv6V;~5IF8N1 z_e3Go=<or)x5IbIN zq=`<~Olc-TJt6f}KfFC5%LJ$AK2Fpj$*#<)p>mYSkRC+oxpc!4q!DrxqlSk8XGYRudqG@ z*KYJtG>Fc}4fI!*A)JJMMJx5pdyqw)4`3JjzLivWyOvhwzvr^nC6c_Wn=?(+lt*>y zXfO+Yb@%`Mo#NufP*g2}Vmjnmxo58b<-@;s;MmZN=m}-T!JNIwK@ao#>{cL;2@(XXh zWU$BqP0X!=%)YzufP=~6QS0zKD7C$7D97hjZ|l+ncZ;CyeVdWqT+agby~BGE-$?*Q z$weW;@g>2TI}3lOD5-yDPK5`lefJU0a!6xla+)g(Dy4x{Wk7JozHdFO{Xj+8TjTxE z-Y+~s;LMM4xbN1d8W?74@3@9Kn%6_JA&2rSqgL{X+`5%dw{qFAy1ka=Ftg2wq$h+Z z*f&Y1ms7c(?$7+n!XId}BB^LlZp!jhGPblaNr^rDnf>-Dl>f>8?Y|7w-w?Xo7v!3~ z-MDFG^Vg*xU;ZB$VwVyOPdh6P+aiWtp#VL&wP<`s{W!JrC(c~ETE5Ou0E`y_3ph)Z zZ}Bt}?M4}yjiOBewtHE?m-JR&r-@5eR+*>DWh4i&1CPRwJ3zK6QwY= zvF>XFq~Rq#eKtHlX^_s!l&g(I|2Vt(IkfeJx`x^Wp_;GF>-5%b2ErM4VgTAmRcC~x zBYA&Z>3KM{`RTL^HDYz3nW|EMS9|Km?uNOTZ2(AAr?9{IpuJZaJmQ>Tgu=S!zXpM?OrSt0O9cvb?2Wm zS~wP{P6ve5-3PHx8xbY-?7+P-ZdqWo(z&w?fiA0A-K535R-FDye<9NS$*PaGiwj@I zvu#ZJ3$f=it=uhLaLN`I432gf@!CKlgfP{?_|Z@FG5Os>uPq!uJ5CsB%GO)`B|TwE z()u5i4SpbF`UH!?n6{^bjLDS_4~o(cfeelTfcx4 z;L{etm>fkEv2`fS(#=N+lO6|uLv;MAxCYdGY?NH8fGy`KK1gzl1$@@Sy}<)U6|JH% zu)oR|bmDaIJMjVfM2#>&Dfr0+Ot-ofIftybgm4`I-|)h=Ob*5>M$KO#DanlCNJIjO z^* zkm>2AZo*UJPw^-Kyzekst0k5$8wHr){<2|*L&fge586D z0tHdd*fN;cG z+7)#?_es7$Qsp84ydQiInis><&Zhy4?yL~=51VLhY~zI%VBut?v1!k$UB+Zgm`d^7 zZY{bE8{Rh=8p&DLjA+4RjS!1rlf(`!ZrZOd5=B89Y%f65$}G_bF*xQeM|kA#P234<1xnkiD7c} z%-E$%xt!)ESF+Y}>ChDo(S^^cI%$)8{1+))oS2xo`5g#QL^!)xcvm zA^Th3e7AnpGdfB6Yyj>wA%dhT9HUrW_`VahMNI(OzO02I4w_YU^zk2XoG7`LDDI$$ z2@MaH>O=)5x=%yg>Z?hPn!VjEj{6y%*_WCr2HfztXgQS9ubiK%L(d7(F=&2t%~lA@pjYdxpqr%iO(@%uYYIO1Y`874v6g1BMZ28dPFvKU^u(ucV6UbX64ObalC_CCF^Fh@MIj(8QZ_Hy>knG}qDImk z?GDW^tps88k$ThJNFj166x-cJ%zU!sM9}(GvUK8lc+ud10e*zJ5?Fxd=PV!$Z0C!J zHEBL8GRus?ejVdxUx)usyxM(RwmfJwd|#*JTmT_1CR>-#i^__?ykRvcDKfGu*UWPh zH;IK3qqa+OZEK=e4Y>Vu2w;ao@%x%R%O$^OAdiiRBfwdKw|NHl^%|K4ywQFPSliA# z2szGvTaY6^BbzS_sn+U?7jO(f*Ed^swvb zATIE5!?}Ukyd%Ktjr#<=$CgYbE=L1ngd{`f+Zish4p6OVmftalf9UUFWQdXn(!awVzy!6NnELzRIf z58h6SCrHu2TVpQqj`B=ZcmJACNW}MBsVD>x;_61RP*wTDwoowQ`(Z16xy=qnlX$>f z@k^q;7rd*Hf8 zWy4m#`9Qv9fW}urw#`Qoq3BiEz)Qfd@A4Ax!evKlx+tnIV$_3U z)&Hi(BD&QGH=oc{FqG)*@8I)HXG0CX-7Y4F9A-lG15T2ETjaNkb`%I#_!-jbM zJP^8)YrK*GYGlE^cj|YcRt6Zkey&k$DG!EZF~Y_z8vShH{7lIM-sgqFExhMnIlbWD zunCy%Em5G9G*zIDJtx(eK>>Mtas9HJoUfh z*g~C^Y^(hoH`!tQ8bMXUOfY^yfxAM84p zip;@3DTb=)s*i}zDpOT9zDqltER)P$_A9tSmg?|#Dm#Yy&ilmH-m_laSOfDQEP-I! zB%Y_%bXzY5QN2or3S3tidmdXRwK>fuK{>I4NtH?lM7oZzcEx0az&OFElRDiZMXOm) z>MtmO zZCm=Q=IcLXo7GbI$fZK(o%UJXr^2FHOw}v19CLE;%{&@v&5an0eyq3Q@J^VohrxKe z_T*9vzras+>IoGr0}(K7y*7fQZ`|+70ja@qn~^0&7t@=aNuCelcR0n@ z!um;j7(vTuhjd{SU>eWtOsECo?83BQsJ+P&T#fH+qw0FSvwdJuBel{R$Dwj5ewySq4SbWE*E#r=NeRq+o$-h4A zs+<#z7lUA9&9}Rr>s62Wx#H`kXOcC^Y6to4DVf=Xy?%lcsd~FmC@^gPFh zkV8neHQ5HIQ6x_}fhV=0>^5#Sb9OLu3?Aae_^ijvPH@BadvT;Uh$qrbmCIl4CL|I6 zcPJa#1WiJ*NdN`~rs1gXDh**pG0%p5So<=*k!s14CGLVT7dDA3XALUc^E2`6H|<9O zl5){gs^1YOa!hJld}SX<y>evD6!0TK!bwySn42sJ0Fu-2az z+ua|#V@|PG?oK}caOXxRcn!Nm3&yR6-y>2ATCDaa5NJPib`4TdyzbO|A__@tP7Omp zM%Gs0^coPaG&QZ27iwH>t)*rSY}b6UdY_mZn-@J{iJDZ-m4|G4tfNl!*_7onhAX3~ zr0)K2WFPA#SmN58NjTH*Mr%bR(o2W3jX!M-QzWV53cuzj=~xMyPDty%t)k~Z9AP(K zVoy^oTD4)Eqg5hI3Yg_0hVk517McYprE9CThyd3iG$6G7;5MZdunP?BuLO5RG^D%& z2(~R2Kijh8qbWcW9w3e_6pLP z=M7K#=zhiL+je)-dW|PFMyOuTqJ~)E4~MDF$kU`|X{D7kba8aU#^thw8U+otm$ZD# z=4*3)>5!b9Y_Fc3kac)acj+&0KElICOLxr30Rgqa91HJ8%Xyj(qy7eJf37+eOLZ_dM}DQ?Ae(ua%F=1%fV} ztAn$hJ$@ZK#QKHKMPOsk#SmTvk;;m~v)+8SGw)x3%`De3OpqwTC^t-m(bR8J)|e{x)pUmxF+fDa3!3d<2a|A`}O&|PB_I{ zxS|5J3=>*jXNq-Hh8o?FS_^}x@z@2$C#4*nOLRV5U94jIVzuw1F|4?avXtw6p<<_) zZZ;S^=r&b|JyuiI7Y~6PCq!2-b7vgneMBQii*I(mh+z%EcoHw>)v3}LR^Yagp}loe zBKk6W7?R@ow7k&t)9k>sm7+~MYOJzA=L&`o7(sEEKONhRO=KhSMu1-zq4unV`5ZtIu1M0XKj9jm@QjngqOz)ET zI^Of|;nKc)f%Qr_m2h)*vt50(bdi>MYXEK=1Trj|3g(mfYqz@_eDTxKZpWxS#!xpE z3fCPe#=qKJ#OTdf@%&}Dck51P*tS!_@muoz3cvv*d*ok-va%02&EqgyW!6z*sqsRy z;X>m@|FP~uW+4>t@f*`z_t|n?7qr*y&brxL&yIE)jvMJ~WOxGa5}|%b`*ve-?eQ<% zV5G`}L6v2^dzHpbq}tQ8As)xc&KevZH*Q`X55fl>7QgSwj07M7d$jVc+tbJ9^s4XL=kwUy$Hfa{r;!gIjVxSB>=IKP;M-w(h} zX`xl6S5C2=XtuD!3c$#{p~@?_M@6H_etO3Zm5ltUnaI=Apt48B{Prx|e-lakhzZe> z8zPC2|F$LO+ZDvmDQ?b#o!8a4vPoAmb{~%uw4u^+Z48nwR)R6JqB;ERN{oX1 zaT@lmrrnLE06wa#tLYwyrpodL#OA4HP%lhP&i%Y~gkn&;9MxqOBvxV|TlJVZq^@=I z5HiYze&@#FX!M7>_D`yfZw%nM zmGz+Mnk16xb|CiaS)n+?psX->x(T~sJHIJT&<9DWNf6F~xn}c4gMz=yrli5cT3)C#|q*kH31d-pTqgKh*$X@qSxSF2S5kg+Qgex<7i) zvT=W+sR{#tnL}A}F2v6$q}h176`xFu#*+SdyfrBZlG!@2J2ZW)o&TL!dd1?$Mg!TL zSF@Kney+VW!|g2d&S|J*3Oq`;IYxuk&Ta~Hcg!c>H6;pB7)f9dj!0|e8(3D z&5Sd(qKpI9dY=hsS?UiI{;N5gy0KN$!j{&)C}Z4?!MuXm&Lv+(ryI*Z6n^omw&JH6 zgAgk5dD1aPU*%DbFN9~|)N}Dt@-C~ZW%KbZaVs268?Mp_5I>3{1;K{L_em0W&IWhk>lb!U%B0+Qs z(wAH56(n@|Tm(&A#-Nv*8@|?_LD7_+^zOFIL^)lR>I%VC#&1QjPn?Z37CX<4aT_x{ zj#ia|6xJYP+idJ{mX;2~aDxK)T~r4V)Jp0>SZb|er9fGb!}~kW(D{;B z@aQDodbq%=reDTHj@Q=&e@bFsb5slpUZz4g(cQQCXX)Hccx}I@pLT;XW>oBXzW+0? z{Ds|2e68j}a~F?fheqY-vwjdnBq_CWf^7t!$vTSBC%Lv^T&MIWRThbqJTd*{;m=y- z7@9p6D>%)4#%#RZ<$C^|*J+D7YG)zAX??diNQDHG2rz09od4#fSKTmwW7*xrj!v-1@7Vfp2^eo;_ zi#$XGZ!bnSM8uml7s zZ%PTZn5I^RSHfA=b#OA5_8la03v2YZqO+l)(bNE=9{IDc3N%8X5 zHX@UV1(t24b_^Emim8_lop94jKbFf}EPga+9CN}RD$X69L28~$mKKJE_BU~Z*uNseYlPamlt}+sK)fUbsX#0k}yf{ItwZr zc4Q4+f)_8lsLUQOzmV;Ngyp?Z_QV=_?K4Fvbp$&@OYut#Yz0UJ^$MVmi~mPL zTD4w*lo4VNNCo>xLi!Cf4ipa5KSZSU2U$@+LWcU!^N(NTzZY9eTT>TL2h;y-^{-p~ zF_HhP$U&-N_I75L=B^MgcuRXbXI3T$dk0qsTT?q%h@aBG@BOcKf0wZS>wV~d6X#Ee zuSS3D<^Sg>f2`^MDs7PJ|JEBPdvhmKXXpQ0q(73{f0Y|Z^*|*5N`hV>W`Cnau)Qta|IF`0X=BCa}qLwbUMh?#Z$3gn{ua^7Y1T(X-H*zuk zKM(c4f3^AlCd!`yaxk(pwfR5x=HGuZbm;$mh>VPlO>Ime$CLeEJwil8gc{e?QmwzU zn1zGvI~by7{>S0+uObDB^v{XI$;9j*hs{4){;P@VA93`*N;o8zvx}#V>EC=Z|Fhk{ zx^4dZDbs)k+2em1uKs7Mf3*?&_kQ+c{JSsbf42Nr1^7QUV}BJ2{C_hY`$xlnoZJ5? z5dT-hT&n+BF8&`;{xMAdI(z(?l>aJDe*eQ1t@s5F{?BGukcTN`(%JF<^X`8E-oi|p literal 0 HcmV?d00001 diff --git a/AsbCloudWebApi/appsettings.json b/AsbCloudWebApi/appsettings.json index 9e02897a..b82232b2 100644 --- a/AsbCloudWebApi/appsettings.json +++ b/AsbCloudWebApi/appsettings.json @@ -13,7 +13,12 @@ "LocalConnection": "Host=localhost;Database=postgres;Username=postgres;Password=q;Persist Security Info=True" }, "AllowedHosts": "*", - "Urls": "http://0.0.0.0:5000",//;https://0.0.0.0:5001" //, + "email": { + "smtpServer": "smtp.timeweb.ru", + "sender": "bot@autodrilling.ru", + "password": "xHhgwZ4D" + }, + "Urls": "http://0.0.0.0:5000" //;https://0.0.0.0:5001" //, // See https man: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel/endpoints?view=aspnetcore-6.0 //"Kestrel": { // "Endpoints": { diff --git a/ConsoleApp1/Program.cs b/ConsoleApp1/Program.cs index 1f653d09..48a4eb54 100644 --- a/ConsoleApp1/Program.cs +++ b/ConsoleApp1/Program.cs @@ -8,6 +8,7 @@ using AsbCloudDb; using Google.Apis.Drive.v3.Data; using Microsoft.EntityFrameworkCore; using System.Net.Mail; +using System.Text.RegularExpressions; namespace ConsoleApp1 { @@ -18,9 +19,14 @@ namespace ConsoleApp1 class Program { + + static void Main(/*string[] args*/) { - SendMail.Main(); + var regex = new Regex(@"<[a-zA-Z0-9]+.*>.*<[a-zA-Z]+/*>"); + var testHtml = "aa

AAA

asdasd"; + var t = regex.IsMatch(testHtml); + //SendMail.Main(); //DbDemoDataService.AddDemoData(); //.GetAwaiter().GetResult(); diff --git a/ConsoleApp1/SendMail.cs b/ConsoleApp1/SendMail.cs index d3607bb7..f72b659c 100644 --- a/ConsoleApp1/SendMail.cs +++ b/ConsoleApp1/SendMail.cs @@ -14,6 +14,7 @@ namespace ConsoleApp1 MailAddress to = new MailAddress("ng.frolov@autodrilling.ru"); MailAddress from = new MailAddress("bot@autodrilling.ru"); MailMessage message = new MailMessage(from, to); + message.Subject = "Using the new SMTP client."; message.Body = "

this is a test text

"; message.IsBodyHtml = true;