|
|
|
@ -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<MailboxAddress>();
|
|
|
|
|
var arrTo = sendTo.Replace(",", ";").Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
|
foreach (var item in arrTo)
|
|
|
|
|
{
|
|
|
|
|
sendToList.Add(new MailboxAddress(item, item));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//分拆cc邮箱地址
|
|
|
|
|
var ccList = new List<MailboxAddress>();
|
|
|
|
|
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<string>();
|
|
|
|
|
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<string>(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 = $"<p>{string.Join("</p><p>", insTextList)}</p>{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 发送记录查询
|
|
|
|
|
//发件记录
|
|
|
|
|