using System.Web; using JNPF.Common.Configuration; using JNPF.Common.Core.Manager; using JNPF.Common.Core.Manager.Files; using JNPF.Common.Enums; using JNPF.Common.Extension; using JNPF.Common.Filter; using JNPF.Common.Models; using JNPF.Common.Options; using JNPF.Common.Security; using JNPF.DependencyInjection; using JNPF.DynamicApiController; using JNPF.Extend.Entitys; using JNPF.Extend.Entitys.Dto.Email; using JNPF.Extras.Thirdparty.Email; using JNPF.FriendlyException; using JNPF.LinqBuilder; using Mapster; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json.Linq; using SqlSugar; namespace JNPF.Extend; /// /// 邮件收发 /// 版 本:V3.2 /// 版 权:拓通智联科技有限公司(http://www.tuotong-tech.com) /// 日 期:2021-06-01 . /// [ApiDescriptionSettings(Tag = "Extend", Name = "Email", Order = 600)] [Route("api/extend/[controller]")] public class EmailService : IDynamicApiController, ITransient { private readonly ISqlSugarRepository _repository; private readonly ITenant _db; private readonly IUserManager _userManager; private readonly IFileManager _fileManager; public EmailService(ISqlSugarRepository repository, IUserManager userManager, ISqlSugarClient context, IFileManager fileManager) { _repository = repository; _userManager = userManager; _db = context.AsTenant(); _fileManager = fileManager; } #region Get /// /// (带分页)获取邮件列表(收件箱、标星件、草稿箱、已发送). /// /// 请求参数 /// [HttpGet("")] public async Task GetList([FromQuery] EmailListQuery input) { switch (input.type) { case "inBox"://收件箱 return await GetReceiveList(input); case "star"://标星件 return await GetStarredList(input); case "draft"://草稿箱 return await GetDraftList(input); case "sent"://已发送 return await GetSentList(input); default: return PageResult.SqlSugarPageResult(new SqlSugarPagedList()); } } /// /// 信息(收件/发件). /// /// 主键值. /// [HttpGet("{id}")] public async Task GetInfo_Api(string id) { var output = new EmailInfoOutput(); var data = await GetInfo(id); var jobj = data.ToObject(); if (jobj.ContainsKey("Read")) { var entity = data.Adapt(); output = entity.Adapt(); output.bodyText = HttpUtility.HtmlDecode(entity.BodyText); } else { var entity = data.Adapt(); output = entity.Adapt(); output.bodyText = HttpUtility.HtmlDecode(entity.BodyText); } return output; } /// /// 信息(配置). /// /// [HttpGet("Config")] public async Task GetConfigInfo_Api() { return (await GetConfigInfo()).Adapt(); } #endregion #region Post /// /// 删除. /// /// 主键值. /// [HttpDelete("{id}")] public async Task Delete(string id) { try { _db.BeginTran(); var entity = await GetInfo(id); if (entity is EmailReceiveEntity) { //删除邮件 var mailConfig = await GetConfigInfo(); var mailReceiveEntity = entity as EmailReceiveEntity; MailUtil.Delete(new MailParameterInfo { Account = mailConfig.Account, Password = mailConfig.Password, POP3Host = mailConfig.POP3Host, POP3Port = mailConfig.POP3Port.ParseToInt() }, mailReceiveEntity.MID); } //删除数据 var isOk = false; if (entity is EmailReceiveEntity) isOk = await _repository.AsSugarClient().Updateable((EmailReceiveEntity)entity).CallEntityMethod(m => m.Delete()).UpdateColumns(it => new { it.DeleteMark, it.DeleteTime, it.DeleteUserId }).ExecuteCommandHasChangeAsync(); else isOk = await _repository.AsSugarClient().Updateable((EmailSendEntity)entity).CallEntityMethod(m => m.Delete()).UpdateColumns(it => new { it.DeleteMark, it.DeleteTime, it.DeleteUserId }).ExecuteCommandHasChangeAsync(); if (!isOk) throw Oops.Oh(ErrorCode.COM1002); _db.CommitTran(); } catch (Exception ex) { _db.RollbackTran(); throw Oops.Oh(ErrorCode.COM1002); } } /// /// 设置已读邮件. /// /// /// [HttpPut("{id}/Actions/Read")] public async Task ReceiveRead(string id) { var isOk = await _repository.AsSugarClient().Updateable().SetColumns(it => new EmailReceiveEntity() { Read = 1, LastModifyUserId = _userManager.UserId, LastModifyTime = SqlFunc.GetDate() }).Where(it => it.Id.Equals(id)).ExecuteCommandHasChangeAsync(); if (!isOk) throw Oops.Oh(ErrorCode.COM1008); } /// /// 设置未读邮件. /// /// /// [HttpPut("{id}/Actions/Unread")] public async Task ReceiveUnread(string id) { var isOk = await _repository.AsSugarClient().Updateable().SetColumns(it => new EmailReceiveEntity() { Read = 0, LastModifyUserId = _userManager.UserId, LastModifyTime = SqlFunc.GetDate() }).Where(it => it.Id.Equals(id)).ExecuteCommandHasChangeAsync(); if (!isOk) throw Oops.Oh(ErrorCode.COM1008); } /// /// 设置星标邮件 /// /// /// [HttpPut("{id}/Actions/Star")] public async Task ReceiveYesStarred(string id) { var isOk = await _repository.AsSugarClient().Updateable().SetColumns(it => new EmailReceiveEntity() { Starred = 1, LastModifyUserId = _userManager.UserId, LastModifyTime = SqlFunc.GetDate() }).Where(it => it.Id.Equals(id)).ExecuteCommandHasChangeAsync(); if (!isOk) throw Oops.Oh(ErrorCode.COM1008); } /// /// 设置取消星标. /// /// /// [HttpPut("{id}/Actions/Unstar ")] public async Task ReceiveNoStarred(string id) { var isOk = await _repository.AsSugarClient().Updateable().SetColumns(it => new EmailReceiveEntity() { Starred = 0, LastModifyUserId = _userManager.UserId, LastModifyTime = SqlFunc.GetDate() }).Where(it => it.Id.Equals(id)).ExecuteCommandHasChangeAsync(); if (!isOk) throw Oops.Oh(ErrorCode.COM1008); } /// /// 收邮件. /// /// [HttpPost("Receive")] public async Task Receive() { var mailConfig = await GetConfigInfo(); if (mailConfig != null) { var mailAccount = mailConfig.Adapt(); if (MailUtil.CheckConnected(mailAccount)) { new List(); var startTime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd") + " 00:00"); var endTime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd") + " 23:59"); var receiveCount = await _repository.AsSugarClient().Queryable().CountAsync(x => x.MAccount == mailConfig.Account && SqlFunc.Between(x.CreatorTime, startTime, endTime)); List entitys = MailUtil.Get(mailAccount, receiveCount).Select(item => new EmailReceiveEntity { MAccount = mailConfig.Account, MID = item.UID, Sender = item.To, SenderName = item.ToName, Subject = item.Subject, BodyText = HttpUtility.HtmlEncode(item.BodyText), Attachment = item.Attachment.ToJsonString(), Date = item.Date, Read = 0 }).ToList(); if (entitys.Count > 0) { await _repository.AsSugarClient().Insertable(entitys).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync(); } return entitys.Count; } else { throw Oops.Oh(ErrorCode.Ex0003); } } else { throw Oops.Oh(ErrorCode.Ex0004); } } /// /// 存草稿. /// /// 对象实体. /// [HttpPost("Actions/SaveDraft")] public async Task SaveDraft([FromBody] EmailActionsSaveDraftInput input) { var entity = input.Adapt(); entity.BodyText = HttpUtility.HtmlEncode(entity.BodyText); entity.To = input.recipient; entity.Sender = App.GetConfig("JNPF_App", true).ErrorReportTo; var isOk = 0; entity.State = -1; if (entity.Id.IsEmpty()) { isOk = await _repository.AsSugarClient().Insertable(entity).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync(); } else { isOk = await _repository.AsSugarClient().Updateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommandAsync(); } if (isOk < 1) throw Oops.Oh(ErrorCode.COM1008); } /// /// 发邮件. /// /// 对象实体. /// [HttpPost("")] public async Task SaveSent([FromBody] EmailSendInput input) { var entity = input.Adapt(); var mailConfig = await GetConfigInfo(); foreach (var item in input.recipient.Split(",")) { if (!item.IsEmail()) throw Oops.Oh(ErrorCode.Ex0003); if (mailConfig != null) { entity.BodyText = HttpUtility.HtmlEncode(entity.BodyText); entity.To = item; entity.Sender = App.GetConfig("JNPF_App", true).ErrorReportTo; entity.State = 1; var isOk = 0; if (entity.Id.IsEmpty()) { entity.Sender = mailConfig.Account; isOk = await _repository.AsSugarClient().Insertable(entity).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync(); } else { isOk = await _repository.AsSugarClient().Updateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommandAsync(); } //拷贝文件,注意:从临时文件夹拷贝到邮件文件夹 var attachmentList = entity.Attachment.ToList(); var temporaryFile = FileVariable.TemporaryFilePath; var mailFilePath = FileVariable.EmailFilePath; foreach (MailFileParameterInfo mailFile in attachmentList) { FileHelper.MoveFile(Path.Combine(temporaryFile, mailFile.fileId), Path.Combine(mailFilePath, mailFile.fileId)); mailFile.fileName = mailFile.name; } //发送邮件 var mailModel = new MailInfo(); mailModel.To = entity.To; mailModel.CC = entity.CC; mailModel.Bcc = entity.BCC; mailModel.Subject = entity.Subject; mailModel.BodyText = HttpUtility.HtmlDecode(entity.BodyText); mailModel.Attachment = attachmentList; MailUtil.Send(new MailParameterInfo { AccountName = mailConfig.SenderName, Account = mailConfig.Account, Password = mailConfig.Password, SMTPHost = mailConfig.SMTPHost, SMTPPort = mailConfig.SMTPPort.ParseToInt(), Ssl = mailConfig.Ssl == 1 }, mailModel); if (isOk < 1) throw Oops.Oh(ErrorCode.COM1008); } else { throw Oops.Oh(ErrorCode.Ex0004); } } } /// /// 保存邮箱配置 /// /// 对象实体 /// [HttpPut("Config")] public async Task SaveConfig([FromBody] EmailConfigUpInput input) { var entity = input.Adapt(); var data = await GetConfigInfo(); var isOk = 0; if (data == null) { isOk = await _repository.AsSugarClient().Insertable(entity).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync(); } else { entity.Id = data.Id; isOk = await _repository.AsSugarClient().Updateable(entity).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync(); } if (isOk < 1) throw Oops.Oh(ErrorCode.COM1008); } /// /// 邮箱账户密码验证. /// /// 对象实体 [HttpPost("Config/Actions/CheckMail")] public void CheckLogin([FromBody] EmailConfigActionsCheckMailInput input) { var entity = input.Adapt(); if (!MailUtil.CheckConnected(entity.Adapt())) throw Oops.Oh(ErrorCode.Ex0003); } /// /// 下载附件. /// /// 文件对象 [HttpPost("Download")] public async Task Download(AnnexModel fileModel) { var filePath = Path.Combine(FileVariable.EmailFilePath, fileModel.FileId); if (await _fileManager.ExistsFile(filePath)) { _fileManager.DownloadFileByType(filePath, fileModel.FileName); } } #endregion #region PrivateMethod /// /// 信息(配置). /// /// private async Task GetConfigInfo() { return await _repository.AsSugarClient().Queryable().FirstAsync(x => x.CreatorUserId == _userManager.UserId); } /// /// 列表(收件箱). /// /// /// private async Task GetReceiveList(EmailListQuery input) { var whereLambda = LinqExpression.And(); whereLambda = whereLambda.And(x => x.CreatorUserId == _userManager.UserId && x.DeleteMark == null); if (input.endTime != null && input.startTime != null) { var start = Convert.ToDateTime(string.Format("{0:yyyy-MM-dd 00:00:00}", input.startTime?.TimeStampToDateTime())); var end = Convert.ToDateTime(string.Format("{0:yyyy-MM-dd 23:59:59}", input.endTime?.TimeStampToDateTime())); whereLambda = whereLambda.And(x => SqlFunc.Between(x.Date, start, end)); } if (!string.IsNullOrEmpty(input.keyword)) { whereLambda = whereLambda.And(m => m.Sender.Contains(input.keyword) || m.Subject.Contains(input.keyword)); } var list = await _repository.AsSugarClient().Queryable().Where(whereLambda) .OrderBy(x => x.Date, OrderByType.Desc).ToPagedListAsync(input.currentPage, input.pageSize); var pageList = new SqlSugarPagedList() { list = list.list.Adapt>(), pagination = list.pagination }; return PageResult.SqlSugarPageResult(pageList); } /// /// 列表(未读邮件). /// /// /// private async Task GetUnreadList(EmailListQuery input) { var whereLambda = LinqExpression.And(); whereLambda = whereLambda.And(x => x.CreatorUserId == _userManager.UserId && x.Read == 0 && x.DeleteMark == null); if (input.endTime != null && input.startTime != null) { var start = Convert.ToDateTime(string.Format("{0:yyyy-MM-dd 00:00:00}", input.startTime?.TimeStampToDateTime())); var end = Convert.ToDateTime(string.Format("{0:yyyy-MM-dd 23:59:59}", input.endTime?.TimeStampToDateTime())); whereLambda = whereLambda.And(x => SqlFunc.Between(x.CreatorTime, start, end)); } if (!string.IsNullOrEmpty(input.keyword)) { whereLambda = whereLambda.And(m => m.Sender.Contains(input.keyword) || m.Subject.Contains(input.keyword)); } var list = await _repository.AsSugarClient().Queryable().Where(whereLambda).OrderBy(x => x.Date, OrderByType.Desc).ToPagedListAsync(input.currentPage, input.pageSize); var pageList = new SqlSugarPagedList() { list = list.list.Adapt>(), pagination = list.pagination }; return PageResult.SqlSugarPageResult(pageList); } /// /// 列表(星标件). /// /// /// private async Task GetStarredList(EmailListQuery input) { var whereLambda = LinqExpression.And(); whereLambda = whereLambda.And(x => x.CreatorUserId == _userManager.UserId && x.Starred == 1 && x.DeleteMark == null); if (input.endTime != null && input.startTime != null) { var start = Convert.ToDateTime(string.Format("{0:yyyy-MM-dd 00:00:00}", input.startTime?.TimeStampToDateTime())); var end = Convert.ToDateTime(string.Format("{0:yyyy-MM-dd 23:59:59}", input.endTime?.TimeStampToDateTime())); whereLambda = whereLambda.And(x => SqlFunc.Between(x.CreatorTime, start, end)); } //关键字(用户、IP地址、功能名称) if (!string.IsNullOrEmpty(input.keyword)) { whereLambda = whereLambda.And(m => m.Sender.Contains(input.keyword) || m.Subject.Contains(input.keyword)); } var list = await _repository.AsSugarClient().Queryable().Where(whereLambda).OrderBy(x => x.Date, OrderByType.Desc).ToPagedListAsync(input.currentPage, input.pageSize); var pageList = new SqlSugarPagedList() { list = list.list.Adapt>(), pagination = list.pagination }; return PageResult.SqlSugarPageResult(pageList); } /// /// 列表(草稿箱). /// /// /// private async Task GetDraftList(EmailListQuery input) { var whereLambda = LinqExpression.And(); whereLambda = whereLambda.And(x => x.CreatorUserId == _userManager.UserId && x.State == -1 && x.DeleteMark == null); if (input.endTime != null && input.startTime != null) { var start = Convert.ToDateTime(string.Format("{0:yyyy-MM-dd 00:00:00}", input.startTime?.TimeStampToDateTime())); var end = Convert.ToDateTime(string.Format("{0:yyyy-MM-dd 23:59:59}", input.endTime?.TimeStampToDateTime())); whereLambda = whereLambda.And(x => SqlFunc.Between(x.CreatorTime, start, end)); } if (!string.IsNullOrEmpty(input.keyword)) { whereLambda = whereLambda.And(m => m.Sender.Contains(input.keyword) || m.Subject.Contains(input.keyword)); } var list = await _repository.AsSugarClient().Queryable().Where(whereLambda).OrderBy(x => x.CreatorTime, OrderByType.Desc).ToPagedListAsync(input.currentPage, input.pageSize); var pageList = new SqlSugarPagedList() { list = list.list.Adapt>(), pagination = list.pagination }; return PageResult.SqlSugarPageResult(pageList); } /// /// 列表(已发送). /// /// /// private async Task GetSentList(EmailListQuery input) { var whereLambda = LinqExpression.And(); whereLambda = whereLambda.And(x => x.CreatorUserId == _userManager.UserId && x.State != -1 && x.DeleteMark == null); if (input.endTime != null && input.startTime != null) { var start = Convert.ToDateTime(string.Format("{0:yyyy-MM-dd 00:00:00}", input.startTime?.TimeStampToDateTime())); var end = Convert.ToDateTime(string.Format("{0:yyyy-MM-dd 23:59:59}", input.endTime?.TimeStampToDateTime())); whereLambda = whereLambda.And(x => SqlFunc.Between(x.CreatorTime, start, end)); } if (!string.IsNullOrEmpty(input.keyword)) { whereLambda = whereLambda.And(m => m.Sender.Contains(input.keyword) || m.Subject.Contains(input.keyword)); } var list = await _repository.AsSugarClient().Queryable().Where(whereLambda).OrderBy(x => x.CreatorTime, OrderByType.Desc).ToPagedListAsync(input.currentPage, input.pageSize); var pageList = new SqlSugarPagedList() { list = list.list.Adapt>(), pagination = list.pagination }; return PageResult.SqlSugarPageResult(pageList); } /// /// 信息. /// /// /// private async Task GetInfo(string id) { var entity = new object(); if (await _repository.AsSugarClient().Queryable().AnyAsync(x => x.Id == id && x.DeleteMark == null)) { var receiveInfo = await _repository.AsSugarClient().Queryable().FirstAsync(x => x.Id == id && x.DeleteMark == null); receiveInfo.Read = 1; await _repository.AsSugarClient().Updateable(receiveInfo).CallEntityMethod(m => m.LastModify()).UpdateColumns(x => new { x.LastModifyTime, x.LastModifyUserId, x.Read }).ExecuteCommandHasChangeAsync(); entity = receiveInfo; } else { entity = await _repository.AsSugarClient().Queryable().FirstAsync(x => x.Id == id && x.DeleteMark == null); } return entity; } #endregion }