Commit dc38d7f9 by 任天宇
parents 883bf10b 5c339567
...@@ -8,10 +8,6 @@ namespace Kivii.EmailPools ...@@ -8,10 +8,6 @@ namespace Kivii.EmailPools
{ {
internal class Configs internal class Configs
{ {
public const string TableNameEmailPool = "EML_EmailPools"; public const string TableNamePrefixEmailPool = "Emls";
public const string TableNameSmtpConfig = "EML_SmtpConfigs";
public const string EmailPoolDbFolderPath = "/EmailPools/Files";
} }
} }
...@@ -7,35 +7,13 @@ using System.Threading.Tasks; ...@@ -7,35 +7,13 @@ using System.Threading.Tasks;
namespace Kivii.EmailPools.Entities namespace Kivii.EmailPools.Entities
{ {
[Api(Description = "邮箱池")]
/// <summary> [Alias(Configs.TableNamePrefixEmailPool)]
/// 发送状态 public class EmailPool<T> : EmailPoolBase, IEntityInGenericTypeDb, IEntityHasRemark, IEntity, IEntityHasCreator, IHasCreator, IEntityHasUpdater, IHasUpdater
/// </summary>
public enum SendStatus
{ {
/// <summary>
/// 待发
/// </summary>
Sending,
/// <summary>
/// 完成
/// </summary>
Complete,
/// <summary>
/// 取消
/// </summary>
Cancel,
/// <summary>
/// 失败
/// </summary>
Fail
} }
[Api(Description = "邮箱池")] [Api(Description = "邮箱池")]
[Alias(Configs.TableNameEmailPool)]
public class EmailPool : EmailPoolBase,IEntityInAssemblyDb, public class EmailPool : EmailPoolBase,IEntityInAssemblyDb,
IEntityHasRemark, IEntityHasRemark,
IEntityHasCreator, IEntityHasUpdater IEntityHasCreator, IEntityHasUpdater
...@@ -86,10 +64,6 @@ namespace Kivii.EmailPools.Entities ...@@ -86,10 +64,6 @@ namespace Kivii.EmailPools.Entities
[InternalSetter] [InternalSetter]
public bool IsSended { get; set; } public bool IsSended { get; set; }
[ApiMember(Description = "发送状态")]
public SendStatus SendStatus { get; set; }
[ApiMember(Description = "附件地址")] [ApiMember(Description = "附件地址")]
[StringLength(1000)] [StringLength(1000)]
public string FilePath { get; set; } public string FilePath { get; set; }
......
using Kivii.DataAnnotations;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Kivii.EmailPools.Entities
{
[Api(Description = "邮箱配置")]
[Alias(Configs.TableNameSmtpConfig)]
public class SmtpConfig: EntityWithMetadata, IEntityInAssemblyDb
{
[ApiMember(Description = "配置名称")]
[StringLength(200)]
public string Title { get; set; }
[ApiMember(Description = "内部编码")]
[Unique]
[StringLength(200)]
public string InternalCode { get; set; }
[ApiMember(Description = "默认配置")]
public bool IsDefault { get; set; }
[ApiMember(Description = "描述")]
[StringLength(500)]
public string Description { get; set; }
[ApiMember(Description = "smtp服务地址")]
[StringLength(300)]
public string SmtpUrl { get; set; }
[ApiMember(Description = "邮箱地址")]
[Unique]
[StringLength(300)]
public string Address { get; set; }
[ApiMember(Description = "邮箱友好名称")]
[StringLength(300)]
public string Name { get; set; }
[ApiMember(Description = "邮箱账号")]
[StringLength(300)]
public string UserId { get; set; }
[ApiMember(Description = "邮箱密码")]
[StringLength(300)]
public string Password { get; set; }
[ApiMember(Description = "摘要")]
[StringLength(1000)]
public string Summary { get; set; }
[ApiMember(Description = "备注")]
[StringLength(2000)]
public string Remark { get; set; }
}
}
using Kivii.EmailPools.Entities;
using Kivii.Linq;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Net.Mail;
using System.Text;
using System.Threading.Tasks;
namespace Kivii.EmailPools
{
public static class Extension
{
public static List<EmailPool<G>> Accept<G>(this List<EmailPool> items, IDbConnection conn = null)
{
if (conn == null) conn = KiviiContext.GetOpenedDbConnection<EmailPool<G>>();
var rtns = new List<EmailPool<G>>();
foreach (var item in items)
{
try
{
try
{
var to = new MailAddress(item.ToAddress, item.ToName);
}
catch
{
throw new Exception($"收件地址{item.ToAddress},格式错误");
}
EmailPool<G> emailPool = new EmailPool<G>();
emailPool.PopulateWith(item);
conn.Insert(emailPool);
rtns.Add(emailPool);
}
catch
{
continue;
}
}
return rtns;
}
public static List<EmailPool<G>> GetPreSending<G>(this IDbConnection conn)
{
if (conn == null) conn = KiviiContext.GetOpenedDbConnection<EmailPool<G>>();
var rtns = conn.Select<EmailPool<G>>(o => o.IsSended == false);
return rtns;
}
public static List<EmailPool<G>> SendComplete<G>(this List<EmailPool<G>> items, string operatorName=null, Guid? operatorKvid=null, IDbConnection conn = null)
{
var rtns = new List<EmailPool<G>>();
if (conn == null) conn = KiviiContext.GetOpenedDbConnection<EmailPool<G>>();
if (operatorName.IsNullOrEmpty())
{
operatorName = KiviiContext.CurrentMember.FullName;
operatorKvid = KiviiContext.CurrentMember.Kvid;
}
foreach (var item in items)
{
item.IsSended = true;
item.AddOnlyProperties(o => o.IsSended);
item.OperatorName = operatorName;
item.AddOnlyProperties(o => o.OperatorName);
if (operatorKvid != null)
{
item.OperatorKvid = operatorKvid.Value;
item.AddOnlyProperties(o => o.OperatorKvid);
}
item.Category = "发送成功";
item.AddOnlyProperties(o => o.Category);
//item.Remark = "";
//item.AddOnlyProperties(o => o.Remark);
conn.UpdateOnly(item);
rtns.Add(item);
var log = new EntityLog<G>();
log.OwnerKvid = item.OwnerKvid;
log.BizId = item.OwnerName;
log.BizKvid = item.OwnerKvid;
log.BizType = typeof(G).FullName;
log.Type = "电子邮箱";
log.Title = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
log.Summary = "电子邮箱发送完成";
log.Remark = $"[发送成功] 已成功将{item.OwnerName} 发送至客户邮箱({item.ToAddress}). 时间:{DateTime.Now:yyyy-MM-dd HH:mm:ss}!";
conn.Insert(log);
}
return rtns;
}
public static List<EmailPool<G>> SendFail<G>(this List<EmailPool<G>> items, string operatorName = null, Guid? operatorKvid = null, IDbConnection conn = null)
{
var rtns = new List<EmailPool<G>>();
if (conn == null) conn = KiviiContext.GetOpenedDbConnection<EmailPool<G>>();
if (operatorName.IsNullOrEmpty())
{
operatorName = KiviiContext.CurrentMember.FullName;
operatorKvid = KiviiContext.CurrentMember.Kvid;
}
foreach (var item in items)
{
item.IsSended = true;
item.AddOnlyProperties(o => o.IsSended);
item.OperatorName = operatorName;
item.AddOnlyProperties(o => o.OperatorName);
if (operatorKvid != null)
{
item.OperatorKvid = operatorKvid.Value;
item.AddOnlyProperties(o => o.OperatorKvid);
}
item.Category = $"发送失败";
item.AddOnlyProperties(o => o.Category);
item.AddOnlyProperties(o => o.Remark);
conn.UpdateOnly(item);
rtns.Add(item);
var log = new EntityLog<G>();
log.OwnerKvid = item.OwnerKvid;
log.BizId = item.OwnerName;
log.BizKvid = item.OwnerKvid;
log.BizType = typeof(G).FullName;
log.Type = "电子邮箱";
log.Title = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
log.Summary = "电子邮箱发送失败";
log.Remark = $"[发送失败] 发送{item.ToAddress}失败原因:{item.Remark}. 时间:{DateTime.Now:yyyy-MM-dd HH:mm:ss}!";
conn.Insert(log);
}
return rtns;
}
public static List<EmailPool<G>> SendCancel<G>(this List<EmailPool<G>> items, string operatorName = null, Guid? operatorKvid = null, bool isDelete=false, IDbConnection conn = null)
{
var rtns = new List<EmailPool<G>>();
if (conn == null) conn = KiviiContext.GetOpenedDbConnection<EmailPool<G>>();
if (operatorName.IsNullOrEmpty())
{
operatorName = KiviiContext.CurrentMember.FullName;
operatorKvid = KiviiContext.CurrentMember.Kvid;
}
foreach (var item in items)
{
if (isDelete)
{
item.Status = -1;
item.AddOnlyProperties(o => o.Status);
conn.UpdateOnly(item);
rtns.Add(item);
continue;
}
if (item.IsSended) continue;
item.IsSended = true;
item.AddOnlyProperties(o => o.IsSended);
item.OperatorName = operatorName;
item.AddOnlyProperties(o => o.OperatorName);
if (operatorKvid != null)
{
item.OperatorKvid = operatorKvid.Value;
item.AddOnlyProperties(o => o.OperatorKvid);
}
item.Category = $"取消发送";
item.AddOnlyProperties(o => o.Category);
conn.UpdateOnly(item);
rtns.Add(item);
var log = new EntityLog<G>();
log.OwnerKvid = item.OwnerKvid;
log.BizId = item.OwnerName;
log.BizKvid = item.OwnerKvid;
log.BizType = typeof(G).FullName;
log.Type = "电子邮箱";
log.Title = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
log.Summary = "取消电子邮箱发送";
log.Remark = $"[取消发送] 操作人:{KiviiContext.CurrentMember.FullName}. 时间:{DateTime.Now:yyyy-MM-dd HH:mm:ss}!";
conn.Insert(log);
}
return rtns;
}
}
}
using Kivii.EmailPools.Entities;
using Kivii.Linq;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Text;
using System.Threading.Tasks;
namespace Kivii.EmailPools
{
public static class Extensions
{
private static Dictionary<string, SmtpConfig> _smtpConfigs = new Dictionary<string, SmtpConfig>();
/// <summary>
/// 获取Smtp配置
/// </summary>
/// <param name="FromAddress"></param>
/// <returns></returns>
public static SmtpConfig GetSmtpConfig(this string FromAddress)
{
//默认key
var key = "default";
if (!FromAddress.IsNullOrEmpty())
{
try
{
//验证传入的邮箱地址格式是否正确,正确就赋值key,不正确key取默认值
var addr = new System.Net.Mail.MailAddress(FromAddress);
key = FromAddress;
}
catch { }
}
if (_smtpConfigs.ContainsKey(key))
{
return _smtpConfigs[key];
}
var conn = KiviiContext.GetOpenedDbConnection<SmtpConfig>();
var smtpConfigs = conn.Select<SmtpConfig>();
if (!smtpConfigs.IsNullOrEmpty())
{
var defaultConfig = smtpConfigs.FirstOrDefault(o => o.IsDefault);
if (defaultConfig == null) defaultConfig = smtpConfigs.FirstOrDefault();
_smtpConfigs["default"] = defaultConfig;
foreach (var item in smtpConfigs)
{
_smtpConfigs[item.Address] = item;
}
}
if (_smtpConfigs.ContainsKey(key))
{
return _smtpConfigs[key];
}
return null;
}
/// <summary>
/// 通过emialPool找到对应的附件
/// </summary>
/// <param name="pool"></param>
/// <returns></returns>
public static List<Attachment> GetAttachments(this EmailPool pool)
{
var conn=KiviiContext.GetOpenedDbConnection<EmailPool>();
var query = conn.From<EntityDbFile<EmailPool>>();
query.Where(o => o.ParentKvid == Guid.Empty&&o.DbFolderPath==Configs.EmailPoolDbFolderPath && o.OwnerKvid == pool.Kvid);
var dbFiles = conn.Select(query);
if (dbFiles.IsNullOrEmpty()) return null;
var rtns = new List<Attachment>();
foreach (var dbFile in dbFiles)
{
//获取到文件的实际存储路径
var physicalStorageFilePath = dbFile.GetPhysicalPath();
if (!File.Exists(physicalStorageFilePath)) continue;//判断此文件是否存在,不存在就跳过
var attach = new Attachment(physicalStorageFilePath);
rtns.Add(attach);
}
return rtns;
}
/// <summary>
/// 发送email
/// </summary>
/// <param name="pool"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static EmailPool Sending(this EmailPool pool)
{
var config = pool.FromAddress.GetSmtpConfig();
if (config == null) throw new Exception("未找到指定SMTP配置,请先配置SMTP服务信息");
MailAddress from = null;
MailAddress to = null;
try
{
from = new MailAddress(config.Address, config.Name);
}
catch
{
throw new Exception($"发送地址{config.Address},格式错误");
}
try
{
to = new MailAddress(pool.ToAddress, pool.ToName);
}
catch
{
throw new Exception($"收件地址{pool.ToAddress},格式错误");
}
SmtpClient smtp = new SmtpClient(config.SmtpUrl);
smtp.UseDefaultCredentials = false;
smtp.Credentials = new NetworkCredential(config.UserId, config.Password);
smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
smtp.EnableSsl = true;
MailMessage msg = new MailMessage();
msg.From = from;
msg.To.Add(to);
msg.BodyEncoding = Encoding.UTF8;
msg.Body = pool.Body;
msg.Subject = pool.Subject;
msg.IsBodyHtml = pool.IsBodyHtml;
var attachs = pool.GetAttachments();
if (!attachs.IsNullOrEmpty())
{
foreach (var attach in attachs)
{
msg.Attachments.Add(attach);
}
}
try
{
smtp.Send(msg);
pool.SendStatus = SendStatus.Complete;
pool.AddOnlyProperties(o => o.SendStatus);
}
catch (SmtpException ex)
{
pool.SendStatus = SendStatus.Fail;
pool.AddOnlyProperties(o => o.SendStatus);
pool.Remark = ex.Message;
pool.AddOnlyProperties(o => o.Remark);
}
finally
{
pool.IsSended = true;
pool.AddOnlyProperties(o => o.IsSended);
}
return pool;
}
}
}
...@@ -25,20 +25,21 @@ ...@@ -25,20 +25,21 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath> <OutputPath>..\..\Kivii%27s Releases\</OutputPath>
<DefineConstants>TRACE</DefineConstants> <DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Kivii.Common.V4.5, Version=5.6.2024.1160, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="Kivii.Common.V4.5, Version=5.6.2024.10240, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Kivii.Common.5.6.2024.1160\lib\net45\Kivii.Common.V4.5.dll</HintPath> <HintPath>..\..\packages\Kivii.Common.5.6.2024.10240\lib\net45\Kivii.Common.V4.5.dll</HintPath>
</Reference> </Reference>
<Reference Include="Kivii.Core.V4.5, Version=5.6.2023.9000, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="Kivii.Core.V4.5, Version=5.6.2024.10000, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Kivii.Core.5.6.2023.9000\lib\net45\Kivii.Core.V4.5.dll</HintPath> <HintPath>..\..\packages\Kivii.Core.5.6.2024.10000\lib\net45\Kivii.Core.V4.5.dll</HintPath>
</Reference> </Reference>
<Reference Include="Kivii.Linq.V4.5, Version=5.6.2024.2000, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="Kivii.Linq.V4.5, Version=5.6.2024.10000, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Kivii.Linq.5.6.2024.2000\lib\net45\Kivii.Linq.V4.5.dll</HintPath> <HintPath>..\..\packages\Kivii.Linq.5.6.2024.10000\lib\net45\Kivii.Linq.V4.5.dll</HintPath>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
...@@ -52,8 +53,7 @@ ...@@ -52,8 +53,7 @@
<ItemGroup> <ItemGroup>
<Compile Include="Configs.cs" /> <Compile Include="Configs.cs" />
<Compile Include="Entities\EmailPool.cs" /> <Compile Include="Entities\EmailPool.cs" />
<Compile Include="Entities\SmtpConfig.cs" /> <Compile Include="Extension.cs" />
<Compile Include="Extensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Transforms\RestfulEmailPool.cs" /> <Compile Include="Transforms\RestfulEmailPool.cs" />
</ItemGroup> </ItemGroup>
...@@ -61,4 +61,7 @@ ...@@ -61,4 +61,7 @@
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>if "$(ConfigurationName)"=="Release" if exist "$(TargetDir)Reactor\dotNET_Reactor.exe" (call "$(TargetDir)Reactor\dotNET_Reactor.exe" -file "$(TargetPath)" -targetfile "$(TargetDir)Release\$(TargetFileName)" -stringencryption 0 -antitamp 1 -suppressildasm 1)</PostBuildEvent>
</PropertyGroup>
</Project> </Project>
\ No newline at end of file
...@@ -32,5 +32,5 @@ using System.Runtime.InteropServices; ...@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示: //通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("5.4.2024.4090")] [assembly: AssemblyVersion("5.4.2025.2190")]
[assembly: AssemblyFileVersion("5.4.2023.4090")] [assembly: AssemblyFileVersion("5.4.2025.2190")]
\ No newline at end of file \ No newline at end of file
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="Kivii.Common" version="5.6.2024.1160" targetFramework="net45" /> <package id="Kivii.Common" version="5.6.2024.10240" targetFramework="net45" />
<package id="Kivii.Core" version="5.6.2023.9000" targetFramework="net45" /> <package id="Kivii.Core" version="5.6.2024.10000" targetFramework="net45" />
<package id="Kivii.Linq" version="5.6.2024.2000" targetFramework="net45" /> <package id="Kivii.Linq" version="5.6.2024.10000" targetFramework="net45" />
</packages> </packages>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment