From 978601da8ea401f54b41eb624af0b12e4d98afa8 Mon Sep 17 00:00:00 2001 From: wanghaomei Date: Wed, 15 Feb 2023 16:28:20 +0800 Subject: [PATCH] =?UTF-8?q?eml=E5=B8=A6=E8=87=AA=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E8=BD=AC=E5=8F=91=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MailSend.Web/Controllers/MailController.cs | 329 ++++++++++++++++++++- MailSend.Web/MailSend.Web.csproj | 13 + MailSend.Web/Web.config | 4 + MailSend.Web/packages.config | 4 + 4 files changed, 349 insertions(+), 1 deletion(-) diff --git a/MailSend.Web/Controllers/MailController.cs b/MailSend.Web/Controllers/MailController.cs index 4837b65..afef1a2 100644 --- a/MailSend.Web/Controllers/MailController.cs +++ b/MailSend.Web/Controllers/MailController.cs @@ -1,10 +1,13 @@ -using log4net; +using HtmlAgilityPack; +using log4net; using MailSend.Common; using MailSend.Common.Models; using MailSend.Web.Models; +using MimeKit; using Newtonsoft.Json; using System; using System.Collections.Generic; +using System.Configuration; using System.IO; using System.Linq; using System.Text; @@ -210,6 +213,330 @@ namespace MailSend.Web.Controllers return Json(resp); } + //转发邮件 + [HttpPost] + public ActionResult Transmit() + { + var resp = new RespCommon(); + + //需上传eml文件 + if (Request.Files.Count > 0) + { + var smtpList = mailData.MailSendSmtp.AsNoTracking() + .Select(x => x.GID) + .ToList(); + + var sendTo = Request.Form["SendTo"]; + var ccTo = Request.Form["CcTo"]; + var smtpConfig = Request.Form["SmtpConfig"]; //SmtpConfig + var mailAccount = Request.Form["MailAccount"]; + var password = Request.Form["Password"]; + int.TryParse(Request.Form["Port"], out int port); + var smtpServer = Request.Form["SmtpServer"]; + bool.TryParse(Request.Form["SmtpSSL"], out bool smtpSSL); + var showName = Request.Form["ShowName"]; + + var prefixText = Request.Form["PrefixText"]; //前缀文本 + + if (string.IsNullOrEmpty(sendTo)) + { + resp.Success = false; + resp.Code = RespCommon.RespCodeParamError; + resp.Message = "收件人不能为空"; + return Json(resp); + } + + //分拆收件邮箱地址 + var sendToList = new List(); + var arrTo = sendTo.Replace(",", ";").Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); + foreach (var item in arrTo) + { + sendToList.Add(new MailboxAddress(item, item)); + } + + //分拆cc邮箱地址 + var ccList = new List(); + if (!string.IsNullOrEmpty(ccTo)) + { + var arrCc = ccTo.Replace(",", ";").Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); + foreach (var item in arrCc) + { + ccList.Add(new MailboxAddress(item, item)); + } + } + + MailSendSmtp smtpInfo = null; + //没有SmtpConfig参数时,需要提供发件邮箱信息 + if (string.IsNullOrEmpty(smtpConfig)) + { + if (string.IsNullOrEmpty(mailAccount) + || string.IsNullOrEmpty(password) + || string.IsNullOrEmpty(smtpServer) + || port == 0) + { + resp.Success = false; + resp.Code = RespCommon.RespCodeParamError; + resp.Message = "发件邮箱信息无效"; + return Json(resp); + } + else + { + var smtpDB = mailData.MailSendSmtp.FirstOrDefault(x => x.Account == mailAccount); + if (smtpDB == null) + { + smtpDB = new MailSendSmtp(); + smtpDB.GID = Guid.NewGuid().ToString(); + smtpDB.Account = mailAccount; + mailData.MailSendSmtp.Add(smtpDB); + } + + smtpDB.Password = password; + smtpDB.Port = port; + smtpDB.Server = smtpServer; + smtpDB.UseSSL = smtpSSL; + mailData.SaveChanges(); + smtpConfig = smtpDB.GID; + smtpInfo = smtpDB; + } + } + else + { + if (!smtpList.Contains(smtpConfig)) + { + resp.Success = false; + resp.Code = RespCommon.RespCodeParamError; + resp.Message = "SmtpConfig无效"; + return Json(resp); + } + + smtpInfo = mailData.MailSendSmtp.AsNoTracking().First(x => x.GID == smtpConfig); + } + + + for (var i = 0; i < Request.Files.Count; i++) + { + var file = Request.Files[i]; + if (file.ContentLength == 0) + { + resp.Success = false; + resp.Code = RespCommon.RespCodeParamError; + resp.Message = "文件内容不能为空"; + return Json(resp); + } + + var fileExt = Path.GetExtension(file.FileName).ToLower(); + if (fileExt != ".eml") + { + resp.Success = false; + resp.Code = RespCommon.RespCodeParamError; + resp.Message = "文件格式错误"; + return Json(resp); + } + + MimeMessage mail = null; + try + { + mail = MimeMessage.Load(file.InputStream); + } + catch + { + resp.Success = false; + resp.Code = RespCommon.RespCodeParamError; + resp.Message = "文件格式错误"; + return Json(resp); + } + + if (string.IsNullOrEmpty(mail.Subject)) + { + resp.Success = false; + resp.Code = RespCommon.RespCodeParamError; + resp.Message = "主题不能为空"; + return Json(resp); + } + + //发送人 + mail.From.Clear(); + mail.From.Add(new MailboxAddress(string.IsNullOrEmpty(showName) ? smtpInfo.Account : showName, smtpInfo.Account)); + + //收件人 + mail.To.Clear(); + mail.To.AddRange(sendToList); + + //cc + mail.Cc.Clear(); + mail.Cc.AddRange(ccList); + + #region 附加前缀 + var insTextList = new List(); + if (!string.IsNullOrEmpty(prefixText)) + { + insTextList.AddRange(prefixText.Split("\r\n".ToCharArray())); + } + + if (insTextList.Count > 0) + { + var textParts = mail.BodyParts.Where(x => !x.IsAttachment && x.ContentType.MediaType == "text"); + if (textParts != null && textParts.Any()) + { + foreach (var part in textParts) + { + var tp = part as TextPart; + var contentText = tp.Text; + + Encoding srcEncoding = null; + if (!string.IsNullOrEmpty(tp.ContentType.Charset)) + { + srcEncoding = Encoding.GetEncoding(tp.ContentType.Charset); + } + + + if (tp.ContentType.MimeType.Contains("html")) + { + HtmlDocument htmldoc = new HtmlDocument(); + var htmlEncoding = htmldoc.DetectEncodingHtml(tp.Text); + + htmldoc.LoadHtml(tp.Text); + var bodyNode = htmldoc.DocumentNode.SelectSingleNode("//body"); + var metaLastNode = htmldoc.DocumentNode.SelectSingleNode("//meta[last()]"); + var metaCharsetNode = htmldoc.DocumentNode.SelectSingleNode("//meta[contains(@http-equiv,'Content-Type')]"); + + Encoding toEncoding = null; + if (srcEncoding == null) + { + srcEncoding = htmldoc.DeclaredEncoding; + } + + if (srcEncoding == Encoding.ASCII || srcEncoding == Encoding.GetEncoding("iso-8859-1") || srcEncoding == null) + { + toEncoding = Encoding.UTF8; + tp.ContentType.CharsetEncoding = toEncoding; + if (metaCharsetNode != null) + { + metaCharsetNode.SetAttributeValue("content", "text/html; charset=utf-8"); + } + } + else + { + toEncoding = srcEncoding; + } + + if (bodyNode != null) + { + var insTextReverse = new List(insTextList.ToArray()); + insTextReverse.Reverse(); + foreach (var text in insTextReverse) + { + var insNode = htmldoc.CreateElement("p"); + insNode.AppendChild(htmldoc.CreateTextNode(text)); + bodyNode.InsertBefore(insNode, bodyNode.FirstChild); + } + + MemoryStream ms = new MemoryStream(); + htmldoc.Save(ms, toEncoding); + + contentText = toEncoding.GetString(ms.ToArray()); + } + else if (metaLastNode != null) + { + foreach (var text in insTextList) + { + var insNode = htmldoc.CreateElement("p"); + insNode.AppendChild(htmldoc.CreateTextNode(text)); + htmldoc.DocumentNode.InsertAfter(insNode, metaLastNode); + } + + MemoryStream ms = new MemoryStream(); + htmldoc.Save(ms, toEncoding); + + contentText = toEncoding.GetString(ms.ToArray()); + } + else + { + contentText = $"

{string.Join("

", insTextList)}

{contentText}"; + } + + tp.SetText(toEncoding, contentText); + } + else + { + Encoding toEncoding = null; + if (srcEncoding == Encoding.ASCII || srcEncoding == Encoding.GetEncoding("iso-8859-1") || srcEncoding == null) + { + toEncoding = Encoding.UTF8; + tp.ContentType.CharsetEncoding = toEncoding; + } + else + { + toEncoding = srcEncoding; + } + + contentText = $"{string.Join("\r\n", insTextList)}\r\n{contentText}"; + tp.SetText(toEncoding, contentText); + tp.ContentType.CharsetEncoding = toEncoding; + } + + } + } + else + { + var mult = new Multipart("mixed"); + var newPart = new TextPart("plain"); + newPart.SetText(Encoding.UTF8, string.Join("\r\n", insTextList)); + mult.Add(newPart); + mult.Add(mail.Body); + mail.Body = mult; + } + } + #endregion + + var mailSend = new Common.MailSend(); + mailSend.GID = Guid.NewGuid().ToString().Replace("-", ""); + mailSend.SendTo = mail.To.ToString(); + mailSend.CCTo = mail.Cc?.ToString(); + mailSend.Title = mail.Subject; + mailSend.SmtpConfig = smtpConfig; + + mailData.MailSend.Add(mailSend); + + //保存eml文件 + string emlFilePath = ConfigurationManager.AppSettings["EmlFilePath"]; + var saveEmlPath = string.Empty; + if (string.IsNullOrEmpty(emlFilePath)) + { + saveEmlPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "EmlFiles"); + } + else + { + saveEmlPath = Path.Combine(emlFilePath, "EmlFiles"); + } + + if (!Directory.Exists(saveEmlPath)) + { + Directory.CreateDirectory(saveEmlPath); + } + + var saveFileName = Path.Combine(saveEmlPath, $"{mailSend.GID}.eml"); + mail.WriteTo(saveFileName); + mailSend.EmlFile = saveFileName; //记录eml文件位置 + + } + + mailData.SaveChanges(); + + resp.Success = true; + resp.Code = RespCommon.RespCodeSuccess; + resp.Message = "提交成功"; + + return Json(resp); + } + else + { + resp.Success = false; + resp.Code = RespCommon.RespCodeParamError; + resp.Message = "请上传eml文件"; + return Json(resp); + } + } #region 发送记录查询 //发件记录 diff --git a/MailSend.Web/MailSend.Web.csproj b/MailSend.Web/MailSend.Web.csproj index e5e1ac9..f8c6fd5 100644 --- a/MailSend.Web/MailSend.Web.csproj +++ b/MailSend.Web/MailSend.Web.csproj @@ -46,12 +46,18 @@ 4 + + ..\packages\Portable.BouncyCastle.1.9.0\lib\net40\BouncyCastle.Crypto.dll + ..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.dll ..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.SqlServer.dll + + ..\packages\HtmlAgilityPack.1.11.46\lib\Net45\HtmlAgilityPack.dll + ..\packages\log4net.2.0.14\lib\net45\log4net.dll @@ -59,6 +65,9 @@ ..\packages\Microsoft.Extensions.Logging.Abstractions.2.1.1\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll + + ..\packages\MimeKit.3.1.1\lib\net46\MimeKit.dll + ..\packages\Quartz.3.3.3\lib\net461\Quartz.dll @@ -69,9 +78,13 @@ ..\packages\Quartz.Plugins.3.3.3\lib\net461\Quartz.Plugins.dll + + ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + diff --git a/MailSend.Web/Web.config b/MailSend.Web/Web.config index ec0ad6e..d04d802 100644 --- a/MailSend.Web/Web.config +++ b/MailSend.Web/Web.config @@ -15,6 +15,10 @@ + + + + diff --git a/MailSend.Web/packages.config b/MailSend.Web/packages.config index 3eb095b..6e382a4 100644 --- a/MailSend.Web/packages.config +++ b/MailSend.Web/packages.config @@ -2,6 +2,7 @@ + @@ -12,9 +13,12 @@ + + + \ No newline at end of file