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 @   兴杰  阅读(675)  评论(0编辑  收藏  举报
编辑推荐:
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
点击右上角即可分享
微信分享提示