netcore 简单实现邮件发送
在很多应用系统中,都会有邮件发送功能。例如当用户注册过程中向用户邮箱发送验证信息;当客户完成订单时发送邮件进行提醒;当系统出现异常时向指定账号发送邮件报警等等。
以前,开发过程中大多数都是使用微软的smtpclient发送邮件。但是微软本身封装的组件stmpclient内部连接管理混乱(可查看https://www.infoq.cn/article/2017/04/MailKit-MimeKit-Official);并且支持的协议不足,特别是ssl方面,现在已经被微软标记为obsolete(过时的)。曾经在使用阿里云作为服务器需要发邮件时,阿里云提示禁用25端口(25端口不安全,容易被黑)而推荐使用465端口。但是微软的StmpClient竟然不支持465...着实坑了一把。
现今在实现邮件发送功能时,更多的是选择使用(微软也推荐的)第三方组件Mailkit。当然我们也可以使用一些云邮箱服务,例如Amazon Simple Email Service。
MailKit简单实现邮件发送
MailKit是开源的,基于MimeKit的跨平台.NET邮件库,支持IMAP、POP3、SMTP协议。也是当前微软推荐使用的。
开源地址:https://github.com/jstedfast/MailKit
以下是简单实现邮件发送功能
1 public class MailKitManagement 2 { 3 public readonly MailKitConfig _mailKitConfig; 4 public MailKitManagement(IOptions<MailKitConfig> mailKitConfigOption) 5 { 6 _mailKitConfig = mailKitConfigOption?.Value; 7 } 8 /// <summary> 9 /// send email 10 /// </summary> 11 /// <param name="toMailAddressList"></param> 12 /// <param name="ccAddresList"></param> 13 /// <param name="subject"></param> 14 /// <param name="body"></param> 15 /// <param name="attachmentList"></param> 16 /// <param name="isHtml"></param> 17 /// <returns></returns> 18 public async Task SendMessageAsync(List<string> toMailAddressList, List<string> ccAddresList, string subject, string body, List<string> attachmentList = null, bool isHtml = false) 19 { 20 var mailMessage = new MimeMessage(); 21 mailMessage.From.Add(new MailboxAddress(_mailKitConfig.DisplayName, _mailKitConfig.MailAddress)); 22 foreach (var mailAddressItem in toMailAddressList) 23 { 24 mailMessage.To.Add(MailboxAddress.Parse(mailAddressItem)); 25 } 26 if (ccAddresList != null) 27 { 28 ccAddresList.ForEach(p => 29 { 30 mailMessage.Cc.Add(MailboxAddress.Parse(p)); 31 }); 32 } 33 34 mailMessage.Subject = subject; 35 TextPart messageBody = null; 36 if (isHtml) 37 { 38 messageBody = new TextPart(TextFormat.Html) 39 { 40 Text = body, 41 }; 42 } 43 else 44 { 45 messageBody = new TextPart(TextFormat.Plain) 46 { 47 Text = body, 48 }; 49 } 50 var mulitiPart = new Multipart("mixed") 51 { 52 }; 53 mulitiPart.Add(messageBody); 54 if (attachmentList != null && attachmentList.Count > 0) 55 { 56 foreach (var attatchItem in attachmentList) 57 { 58 using (var stream = File.OpenRead(attatchItem)) 59 { 60 var attachment = new MimePart() 61 { 62 Content = new MimeContent(stream, ContentEncoding.Default), 63 ContentDisposition = new ContentDisposition(ContentDisposition.Attachment), 64 ContentTransferEncoding = ContentEncoding.Base64, 65 FileName = Path.GetFileName(attatchItem) 66 }; 67 mulitiPart.Add(attachment); 68 } 69 } 70 } 71 mailMessage.Body = mulitiPart; 72 using (var client = new MailKit.Net.Smtp.SmtpClient()) 73 { 74 if (_mailKitConfig.IsSsl) 75 { 76 client.ServerCertificateValidationCallback = (s, c, h, e) => true; 77 } 78 79 client.Connect(_mailKitConfig.MailServer, _mailKitConfig.SmtpPort, false); 80 81 // Disable the XOAUTH2 authentication mechanism. 82 //client.AuthenticationMechanisms.Remove("XOAUTH2"); 83 84 // Note: only needed if the SMTP server requires authentication 85 client.Authenticate(_mailKitConfig.MailAddress, _mailKitConfig.Password); 86 await client.SendAsync(mailMessage); 87 client.Disconnect(true); 88 } 89 } 90 }
Amazon Simple Email Service简单实现发送邮件
Amazon Simple Email Service 是Amazon提供的邮件服务。需要有响应的Amazon账号,而且在达到一定量时会被要求收费,一般不建议个人使用。对于一些企业可以考虑(但也很少会用)。(之前工作中跟老外部分有交互时,老外推荐使用....)
1 /* 2 * Amazon Simple Email Service 3 * 参照 https://docs.aws.amazon.com/ses/latest/DeveloperGuide/send-using-sdk-net.html 4 * 5 */ 6 /// <summary> 7 /// aws email helper 8 /// need to using AWSSDK.Core.3.7.0.44 and AWSSDK.SimpleEmail.3.7.0.42. 9 /// </summary> 10 public class AwsEmailManagement 11 { 12 13 private readonly AwsEmailConfig _awsConfig; 14 public AwsEmailManagement(IOptions<AwsEmailConfig> awsConfigOption) 15 { 16 this._awsConfig = awsConfigOption?.Value; 17 } 18 19 /// <summary> 20 /// send email 21 /// </summary> 22 /// <param name="toEmailList"></param> 23 /// <param name="ccEmailList"></param> 24 /// <param name="subject"></param> 25 /// <param name="body"></param> 26 /// <param name="isHtml"></param> 27 /// <returns></returns> 28 public async Task SendMessageAsync(List<string> toMailAddressList, List<string> ccAddresList, string subject, string body, bool isHtml = false,string configurationSetName = "") 29 { 30 31 AWSCredentials awsCredentials = new BasicAWSCredentials(_awsConfig.AccessKey, _awsConfig.SecretKey); 32 AmazonSimpleEmailServiceConfig clientConfiguration = new AmazonSimpleEmailServiceConfig(); 33 if (_awsConfig.IsEnableProxy) 34 { 35 clientConfiguration.ProxyHost = _awsConfig.ProxyUrl; 36 clientConfiguration.ProxyPort = _awsConfig.ProxyPort; 37 } 38 using (var client = new AmazonSimpleEmailServiceClient(awsCredentials, clientConfiguration)) 39 { 40 var sendRequest = new SendEmailRequest 41 { 42 Source = _awsConfig.EmailAddress, 43 Destination = new Destination 44 { 45 ToAddresses = toMailAddressList, 46 }, 47 Message = new Message 48 { 49 Subject = new Content(subject), 50 Body = new Body(), 51 }, 52 53 }; 54 55 if (isHtml) 56 { 57 sendRequest.Message.Body.Html = new Content(body); 58 } 59 else 60 { 61 sendRequest.Message.Body.Text = new Content(body); 62 } 63 if (ccAddresList != null && ccAddresList.Count > 0) 64 { 65 sendRequest.Destination.CcAddresses = ccAddresList; 66 } 67 68 sendRequest.ConfigurationSetName =configurationSetName; 69 70 var response = await client.SendEmailAsync(sendRequest); 71 } 72 } 73 }
配置文件类(AwsEmailConfig)定义
1 public class AwsEmailConfig 2 { 3 public string AccessKey { get; set; } 4 public string SecretKey { get; set; } 5 public bool IsEnableProxy { get; set; } 6 public string ProxyUrl { get; set; } 7 public int ProxyPort { get; set; } 8 9 public string EmailAddress { get; set; } 10 11 }