发送邮件的小功能(.net core 版)
前言:
使用.net core 开发有一段时间了,期间从.net core 2.0 preview1 到 preview2 又到core 1.1 现在2.0正式版出来了。又把项目升级至2.0了。目前正在用2.0进行开发。期间也遇到了不少问题。在这里进行总结一下。
最近工作内容就是job的迁移工作,从Framework迁移到.net Core上。体会到了两个框架的不同之处。以及使用过程中体会到的1.1和2.0的不同 以及Framework和Core的不同。首先说一下2.0和Framework的不同吧。刚开始用的preview1 用的时候感觉差异不是特别的大。有些方法2.0的实现方式和Framework实现的方式一样。命名空间也没有变,方法名也没有变。当然了有些东西还是不一样的。或者说有些方法没有实现。后来升级到preview2后。突然感觉那里不对。后来仔细观察了一下原来是类库变了。preview1类库是netcore2.0。preview2类库是.netstandard2.0。总体来说升级影响不是特别的大。后来降到1.1 差别就出来了。很多方法1.1没有实现。或者说用别的方法给实现了。最头疼的可能就是反射的那块了。几乎每次都要getRuntimeXXX一次。很是烦人。2.0的语法就和Framework反射的语法是一致的。很是方便。现在升级到2.0反射那块没有变,依旧可以用。应该是保留了1.1的那种过度的写法。或者说保留了那种写法。
更新:2017-9-15 事实证明:反射那块不兼容,getRuntime***();2.0保持和Framework用法一样,1.1那个过渡的写法2.0已经不兼容了。
内容:
内容比较乱吧。自己想到哪里就讲到哪里吧。
我有这么一个需求:将razor视图加载之后生成的html获取出来。我用的视图引擎,加载执行,之后将执行的结果进行返回过来。
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Routing; namespace CNBlogs.Job.Web.Core.Utility
{
public interface IViewRenderService
{
Task<string> RenderToStringAsync(string viewName, object model);
}
public class ViewRenderService : IViewRenderService
{
private readonly IRazorViewEngine _razorViewEngine;
private readonly ITempDataProvider _tempDataProvider;
private readonly IServiceProvider _serviceProvider; public ViewRenderService(IRazorViewEngine razorViewEngine,
ITempDataProvider tempDataProvider,
IServiceProvider serviceProvider)
{
_razorViewEngine = razorViewEngine;
_tempDataProvider = tempDataProvider;
_serviceProvider = serviceProvider;
} public async Task<string> RenderToStringAsync(string viewName, object model)
{
var httpContext = new DefaultHttpContext { RequestServices = _serviceProvider };
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); using (var sw = new StringWriter())
{
var viewResult = _razorViewEngine.FindView(actionContext, viewName, false); if (viewResult.View == null)
{
throw new ArgumentNullException($"{viewName} does not match any available view");
} var viewDictionary = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary())
{
Model = model
}; var viewContext = new ViewContext(
actionContext,
viewResult.View,
viewDictionary,
new TempDataDictionary(actionContext.HttpContext, _tempDataProvider),
sw,
new HtmlHelperOptions()
); await viewResult.View.RenderAsync(viewContext);
return sw.ToString();
}
}
}
}
IViewRenderService
更新:2017-17-27
RazorViewEngine.FindView()方法有点小问题,无法识别绝对路径。
如果要识别绝对路径,需要用GetView()方法。用法GetView(viewAbsolutePath:string,viewAbsolutePath:string,IsMainPage:bool),具体参数没有详细研究,我目前是这么用的。
详见github 上的issue https://github.com/aspnet/Mvc/issues/4936
用法呢:当然我需要进行依赖注入。services.AddScoped<IViewRenderService, ViewRenderService>();对于ViewRenderService需要的依赖注入,其实mvc框架中这些已经注入过了。直接拿来用就可以。
我是这么用的
var userResumeAttachmentString = await _viewRenderService.RenderToStringAsync("_ResumeForEmail", resume);
说明一下: 传的第一参数是视图名称。或者视图文件所在路径也可以,第二参数是加载视图所需要的model。
说一下发邮件的问题。由于Core1.1没有system.net.mail 。发送邮件一时间成了难题。有难难题就有人解决,于是mailkit出现了,用法呢和Framework发送邮件的方式大致是一样的。
/// <summary>
///发送邮件
/// </summary>
/// <param name="receive">接收人</param>
/// <param name="sender">发送人</param>
/// <param name="subject">标题</param>
/// <param name="body">内容</param>
/// <param name="attachments">附件</param>
/// <returns></returns>
public bool SendMail(string receive, string sender, string subject, string body, byte[] attachments = null)
{
string displayName = _configuration["Mail:Name"];
string from = _configuration.GetSection("Mail").GetSection("Address").Value;
var fromMailAddress = new MailboxAddress(displayName, from);
var toMailAddress = new MailboxAddress(receive);
var mailMessage = new MimeMessage();
mailMessage.From.Add(fromMailAddress);
mailMessage.To.Add(toMailAddress);
if (!string.IsNullOrEmpty(sender))
{
var replyTo = new MailboxAddress(displayName, sender);
mailMessage.ReplyTo.Add(replyTo);
}
var bodyBuilder = new BodyBuilder() { HtmlBody = body };
mailMessage.Body = bodyBuilder.ToMessageBody();
mailMessage.Subject = subject;
return SendMail(mailMessage); }
private bool SendMail(MimeMessage mailMessage)
{
try
{
var smtpClient = new SmtpClient();
smtpClient.Timeout = * ; //设置超时时间
string host = _configuration.GetSection("Mail").GetSection("Host").Value;
int port = int.Parse(_configuration.GetSection("Mail").GetSection("Port").Value);
string address = _configuration.GetSection("Mail").GetSection("Address").Value;
string password = _configuration.GetSection("Mail").GetSection("Password").Value;
smtpClient.Connect(host, port, MailKit.Security.SecureSocketOptions.None);//连接到远程smtp服务器
smtpClient.Authenticate(address, password);
smtpClient.Send(mailMessage);//发送邮件
smtpClient.Disconnect(true);
return true; }
catch
{
return false;
} }
发邮件这个问题解决了。可是还有一个需求,那就是发送邮件附件。当时查了国外的资料,也没有弄明白。后来自己慢慢的试出来了。具体做法就是将字符串转化为byte数组。然后借用bodyBuilder的一个方法进行附件的添加。
if (attachments != null)
{
bodyBuilder.Attachments.Add("用户简历.pdf", attachments);
}
这里有个坑,那就是添加附件的时候需要将附件的文件名和格式直接指定。
到这里基本已经完成了。我用单元测试进行测试了一番。关于在控制台进行依赖注入的用法,我能想到就是在单元测试中使用。很方便。比如有时候需要进行数据提交的测试。我们可以在单元测试中造假数据,然后向对应的action提交数据。获取返回结果。不用在界面的一次次的填充数据了。
[Fact]
public void TestSendEmail()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
var k1 = Directory.GetCurrentDirectory();
builder.AddEnvironmentVariables();
var Configuration = builder.Build();
var serviceProvider = new ServiceCollection()
.AddSingleton<IConfigurationRoot>(Configuration)
.AddScoped<MsgServices, MsgServices>()
.BuildServiceProvider();
var msgService = serviceProvider.GetService<MsgServices>();
var k = msgService.SendMail("xiaoqu@cnblogs.com", "1483523635@qq.com", "测试", "你好我进行了测试");
Assert.True(k);
}
需要在单元测试项目的目录中添加appsetting.json文件。(我项目已经升到2.0了,但这些用法还是1.1的旧的用法。)
我的appsetting.json 文件 (敏感信息已删除)
"Mail": {
"Name": "博客园招聘频道",
"Address": "emailAddress",
"Host": "xxxxxxx",
"Port": ,
"Password": "password"
}
单元测试显示效果:
发送附件的测试没有放在单元测试中,因为视图需要加载。显示一张截图吧
最后还有一个问题,还么有解决,就是HTML to PDF中文乱码的问题。我用的是node.js 参考的是微软官网的。英文没有问题,中文就乱码,乱码原因目前正在查找中。期间也尝试过用jspdf 但是中文乱码问题解决的方式并不是很理想。目前常见的解决方式是:获取指定元素所在块的内容,然后进行截图,截图分辨率很低,没有使用。也试过DinkToPdf 我看了一点源码,主要核心的的功能使用的wkhtmltopdf的一个类库,他是在这个类库上进行了一层封装。中文乱码问题解决了,但是不是特别的优雅。考虑到跨平台,也没有使用。目前没有合适的解决方案。正在找node.js中文乱码的原因。希望有人用过的给提点建议。很是头疼的中文乱码问题。
写了这么多的代码最终在界面上显示的功能就是一个小按钮。
发送邮件的小功能(.net core 版)的更多相关文章
- android 常用小功能(第二版)
经历过一段岁月,转眼2013的半年都过去了,第二版整理好的小功能,答应大家发布的,直到今日,终于和大家相见了,第二版没有第一版多,大家也可以去参考第一版的内容,希望大家使用愉快! 目录: 1.获取当前 ...
- iOS常用小功能
CHENYILONG Blog 常用小功能 技术博客http://www.cnblogs.com/ChenYilong/ 新浪微博http://weibo.com/luohanchenyilong ...
- 详解Session分布式共享(.NET CORE版)
一.前言&回顾 在上篇文章Session分布式共享 = Session + Redis + Nginx中,好多同学留言问了我好多问题,其中印象深刻的有:nginx挂了怎么办?采用Redis的S ...
- Visual Studio Debugger中七个鲜为人知的小功能
Visual Studio debugger是一个很棒的调试工具,可以帮助程序猿们快速地发现和解决问题.这里给大家简单介绍一下VS调试工具中的七个鲜为人知的小功能. 1. 一键跳转到指定语句 调 ...
- 小T牛 绿色版 18.08.0100
百度网盘 链接:https://pan.baidu.com/s/1g2PIMBR8YAdz5skH5ogFhw 密码:3o4k 小T牛 小T牛 绿色版 18.08.0100 意见反馈:qq(邮箱):6 ...
- WordPress版微信小程序3.2版发布
WordPress版微信小程序(下称开源版)距离上次更新已经过去大半年了,在此期间,我开发新的专业版本-微慕小程序(下称微慕版),同时开源版的用户越来越多,截止到2018年11月26日,在github ...
- WordPress版微信小程序3.0版发布
距离WordPress版微信小程序上一个版本的发布过去了一个月了.在此间,我的工作有些变化,加上正在开发新版本,目前开源版的完善和升级稍稍有些滞后. 虽然这个版本是3.0版,期间有个过渡的2.8版,不 ...
- WordPress版微信小程序2.6版发布
WordPress版微信小程序的完善和升级的工作一直都在进行中,我争取保证一个月可以出一个版本,希望通过一点点的改进,让这个开源产品日趋完美. 同时,pro版WordPress微信小程序也在紧锣密鼓的 ...
- 用MVC5+EF6+WebApi 做一个小功能(三) 项目搭建
一般一个项目开始之前都会有启动会,需求交底等等,其中会有一个环节,大讲特讲项目的意义,然后取一个高大上的项目名字,咱这是一个小功能谈不上项目,但是名字不能太小气了.好吧,就叫Trump吧.没有任何含义 ...
随机推荐
- JXLS 2.4.0系列教程(五)——更进一步的应用和页面边距bug修复
注:本文代码建立于前面写的代码.不过不看也不要紧. 前面的文章把JXLS 2.4.0 的基本使用写了一遍,现在讲讲一些更进一步的使用方法.我只写一些我用到过的方法,更多的高级使用方法请参考官网. ht ...
- 【转载】keil5中加入STM32F10X_HD,USE_STDPERIPH_DRIVER的原因
初学STM32,在RealView MDK 环境中使用STM32固件库建立工程时,初学者可能会遇到编译不通过的问题.出现如下警告或错误提示: warning: #223-D: function &qu ...
- dede从www跟目录迁移,网站空间
图集缩略图表名dede_uploads 字段url; 图集文章内部的图片表名dede_addonimages 字段imgurls 频道文章列表的图片 ...
- DEDECMS 留言薄模块的使用方法
一.留言薄的安装 留言薄的安装过程和其他插件一样,首先我们进入后台模块管理列表,点击其对应的"安装": 以上步骤,我们完成了留言薄插件的安装. 二.留言薄的卸载 留言薄的卸载,同样 ...
- Eclipse配置maven环境
一.什么是maven? Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个 ...
- iOracle实战笔记(第五天)
导读 今天的主要内容:维护数据的完整性.索引.管理Oracle的权限和角色. 一.维护数据库的数据的完整性 数据完整性用于确保数据库数据遵从一定的商业规则和逻辑规则.在Oracle中,数据完整性可以使 ...
- mysql 中文乱码
- mysql数据库管理工具navicat for mysql怎么用
mysql数据库管理工具navicat for mysql,对于不怎么喜欢图形界面或者不太方便使用SQL的时候.我们可以通过用这个图形界面数据库管理工具来管理mysql,本经验咗嚛就简单介绍一下怎么用 ...
- Jpa 本地方式实现数据的持久化【千锋】
Jpa本身支持多种方式的对象持久化,比如数据库方式,还有一种方式就是本地文件的方式,本文来讲解以本地方式实现的数据持久化,具体的资源大家可以参阅一下网站:http://www.objectdb.com ...
- ThinkPhp关闭Debug后出错解决方案
注:我使用的是ThinkPHP的3.2版本,其他版本类似 从自己入手PHP开发以来,一直使用的是ThinkPHP的框架,前几天偶然间碰到了一个错误,在Debug模式下网站一切正常,而关闭Debug进行 ...