2020-12-28
hotmail 和 gmail 参考 :
如果 send 的时候出现 error 比如类似 :
The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.57 SMTP; Client was not authenticated t
o send anonymous mail during MAIL FROM [SG2P153CA0043.APCP153.PROD.OUTLOOK.COM]
那多半是下面几个问题
gmail 一般上需要去 account bypass, 或者搞一个 app password 之类的. 超麻烦.
https://www.aspsnippets.com/Articles/GMAIL-Error-The-SMTP-server-requires-a-secure-connection-or-the-client-was-not-authenticated.aspx
hotmail 好一点,要确保 email active (binding contact number), 而且不可以有 two factory 设置.
还有就是 ssl 一定要 enable 咯, port 587, UseDefaultCredentials = false
live.com 的 smtp 是 smtp.live.com
hotmail 的是 smtp.office365.com
gmail 的是 smtp.gmail.com
遇到 error 如果是 account 的问题, google 和微软是会发 email 告诉你的. 所以我们要确保 password 对, host, port 对.
refer :
https://dotnetcoretutorials.com/2017/08/20/sending-email-net-core-2-0/
https://ppolyzos.com/2016/09/09/asp-net-core-render-view-to-string/
https://github.com/aspnet/Entropy/blob/dev/samples/Mvc.RenderViewToString/RazorViewToStringRenderer.cs ( 这个很干净, 没有依赖 http request )
直接看代码
要使用 Razor 模板需要提供这 2 个 服务
public void ConfigureServices(IServiceCollection services) { services.AddSingleton<ICompositeViewEngine, CompositeViewEngine>(); services.AddSingleton<IActionContextAccessor, ActionContextAccessor>(); }
Controller 注入相关服务
public class EmailController : Controller { public EmailController( IOptionsSnapshot<Configuration.Email> emailOptionsAccessor, ICompositeViewEngine compositeViewEngine, IActionContextAccessor actionContextAccessor ) { emailConfig = emailOptionsAccessor.Value; this.compositeViewEngine = compositeViewEngine; actionContext = actionContextAccessor.ActionContext; } private Configuration.Email emailConfig { get; set; } private ICompositeViewEngine compositeViewEngine { get; set; } private ActionContext actionContext { get; set; } }
最后呢
SmtpClient client = new SmtpClient { EnableSsl = emailConfig.enableSsl, Port = emailConfig.port, Host = emailConfig.host, UseDefaultCredentials = false, Credentials = new NetworkCredential(emailConfig.username, emailConfig.password) }; string body; using (StringWriter sw = new StringWriter()) { EmailTemplateViewmodel model = new EmailTemplateViewmodel { value = "dada" }; ViewData.Model = model; ViewEngineResult viewResult = compositeViewEngine.GetView( null, "~/Email/EmailTemplate.cshtml", false ); ViewContext viewContext = new ViewContext(actionContext, viewResult.View, ViewData, TempData, sw, new HtmlHelperOptions()); await viewResult.View.RenderAsync(viewContext); body = sw.GetStringBuilder().ToString(); } MailMessage mailMessage = new MailMessage { From = new MailAddress(emailConfig.from, emailConfig.displayName), Subject = "subject", Body = body, IsBodyHtml = true }; mailMessage.To.Add("hengkeat87@gmail.com"); await client.SendMailAsync(mailMessage);
上面的依赖当前的请求
如果要不依赖请求的
注入
IServiceProvider serviceProvider,
ITempDataProvider tempDataProvider
private async Task<string> GenerateBodyFromTemplateAsync(string templatePath, object model) { string body; using (StringWriter sw = new StringWriter()) { // 这里渲染模板是不包含任何 http 请求的东西的, 所以模板里请不要使用 http 的东西哦 var httpContext = new DefaultHttpContext(); httpContext.RequestServices = ServiceProvider; var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); var viewData = new ViewDataDictionary(metadataProvider: new EmptyModelMetadataProvider(), modelState: new ModelStateDictionary()); viewData.Model = model; var data = new TempDataDictionary(actionContext.HttpContext, TempDataProvider); var viewResult = CompositeViewEngine.GetView(null, templatePath, false); var viewContext = new ViewContext(actionContext, viewResult.View, viewData, data, sw, new HtmlHelperOptions()); await viewResult.View.RenderAsync(viewContext); body = sw.GetStringBuilder().ToString(); } return body; }