Asp.net core 学习笔记 ( Smtp and Razor template 电子邮件和 Razor 模板 )

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 less secure apps, 有时候 bypass 了不可以可能是 cache 问题, 去 clear cache. 还是不可以的话可能需要搞 app password 之类的 (我没试过这个). 总之 gmail 超麻烦

hotmail 好一点,要确保 email active (binding contact number), 而且不可以有 two factory 设置.

还有就是 ssl 一定要 enable 咯, port 587, UseDefaultCredentials = false, TLS 1.2 或以上 (2022年 2 月 不支持 TLS 1.0, 1.1 了)

live.com 的 smtp 是 smtp.live.com (更新: 2022-05-21 smtp.live.com 已经废弃了, 改用 smtp.office365.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;
}

 

posted @ 2017-09-22 19:37  兴杰  阅读(672)  评论(0编辑  收藏  举报