diff --git a/Solution/WPF-Control.sln b/Solution/WPF-Control.sln index 36665aef..8ab80bba 100644 --- a/Solution/WPF-Control.sln +++ b/Solution/WPF-Control.sln @@ -267,9 +267,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "H.Controls.ColorPicker", ". EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "H.Extensions.Unit", "..\Source\Extensions\H.Extensions.Unit\H.Extensions.Unit.csproj", "{E4ECBFB2-BCD6-4BEB-B88E-932E3587E04B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "H.Controls.QRCoderBox", "..\Source\Controls\H.Controls.QRCoderBox\H.Controls.QRCoderBox.csproj", "{AEC475E3-607E-4290-93B6-5EDFE0229F6C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "H.Controls.QRCoderBox", "..\Source\Controls\H.Controls.QRCoderBox\H.Controls.QRCoderBox.csproj", "{AEC475E3-607E-4290-93B6-5EDFE0229F6C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "H.Controls.ScheduleBox", "..\Source\Controls\H.Controls.ScheduleBox\H.Controls.ScheduleBox.csproj", "{24785305-3565-4A79-B83D-CC990D20C42B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "H.Controls.ScheduleBox", "..\Source\Controls\H.Controls.ScheduleBox\H.Controls.ScheduleBox.csproj", "{24785305-3565-4A79-B83D-CC990D20C42B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "H.Extensions.Mail", "..\Source\Extensions\H.Extensions.Mail\H.Extensions.Mail.csproj", "{7374B023-7B0F-4F6E-9E43-C6B81B8DB564}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -751,6 +753,10 @@ Global {24785305-3565-4A79-B83D-CC990D20C42B}.Debug|Any CPU.Build.0 = Debug|Any CPU {24785305-3565-4A79-B83D-CC990D20C42B}.Release|Any CPU.ActiveCfg = Release|Any CPU {24785305-3565-4A79-B83D-CC990D20C42B}.Release|Any CPU.Build.0 = Release|Any CPU + {7374B023-7B0F-4F6E-9E43-C6B81B8DB564}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7374B023-7B0F-4F6E-9E43-C6B81B8DB564}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7374B023-7B0F-4F6E-9E43-C6B81B8DB564}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7374B023-7B0F-4F6E-9E43-C6B81B8DB564}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -877,6 +883,7 @@ Global {E4ECBFB2-BCD6-4BEB-B88E-932E3587E04B} = {09F8FD00-E76A-4D72-AAB4-7FA06DBE12D4} {AEC475E3-607E-4290-93B6-5EDFE0229F6C} = {9E63ED70-6F96-4CB2-8B9D-EAEC77D0548E} {24785305-3565-4A79-B83D-CC990D20C42B} = {9E63ED70-6F96-4CB2-8B9D-EAEC77D0548E} + {7374B023-7B0F-4F6E-9E43-C6B81B8DB564} = {09F8FD00-E76A-4D72-AAB4-7FA06DBE12D4} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DF825C3D-F4F4-4E62-BBFF-B42A5E81112F} diff --git a/Source/Extensions/H.Extensions.Mail/AssemblyInfo.cs b/Source/Extensions/H.Extensions.Mail/AssemblyInfo.cs new file mode 100644 index 00000000..5378cbc6 --- /dev/null +++ b/Source/Extensions/H.Extensions.Mail/AssemblyInfo.cs @@ -0,0 +1,20 @@ +using System.Windows; +using System.Windows.Markup; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page,SMRZQEVBPSMJXTNG + // app, or any theme specific resource dictionaries) BMJGKKNPMBWLIOEO +)] + +[assembly: XmlnsDefinition("QQ:908293466", "H.Extensions.Mail")] +[assembly: XmlnsPrefix("QQ:908293466", "h")] + +[assembly: XmlnsDefinition("https://github.com/HeBianGu", "H.Extensions.Mail")] +[assembly: XmlnsPrefix("https://github.com/HeBianGu", "h")] + +[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "H.Extensions.Mail")] +[assembly: XmlnsPrefix("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "h")] \ No newline at end of file diff --git a/Source/Extensions/H.Extensions.Mail/Extention.cs b/Source/Extensions/H.Extensions.Mail/Extention.cs new file mode 100644 index 00000000..8ce9bb7a --- /dev/null +++ b/Source/Extensions/H.Extensions.Mail/Extention.cs @@ -0,0 +1,32 @@ + +using H.Extensions.Mail; +using H.Providers.Ioc; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace System +{ + public static class Extention + { + /// + /// 注册 + /// + /// + public static IServiceCollection AddMail(this IServiceCollection services, Action setupAction = null) + { + services.AddOptions(); + services.TryAdd(ServiceDescriptor.Singleton()); + services.TryAdd(ServiceDescriptor.Singleton()); + if (setupAction != null) + services.Configure(setupAction); + return services; + } + + public static IApplicationBuilder UseMail(this IApplicationBuilder builder, Action option = null) + { + SettingDataManager.Instance.Add(SmtpSendOptions.Instance); + option?.Invoke(SmtpSendOptions.Instance); + return builder; + } + } +} diff --git a/Source/Extensions/H.Extensions.Mail/H.Extensions.Mail.csproj b/Source/Extensions/H.Extensions.Mail/H.Extensions.Mail.csproj new file mode 100644 index 00000000..8bc6d7e8 --- /dev/null +++ b/Source/Extensions/H.Extensions.Mail/H.Extensions.Mail.csproj @@ -0,0 +1,6 @@ + + + + + + diff --git a/Source/Extensions/H.Extensions.Mail/IMailLogService.cs b/Source/Extensions/H.Extensions.Mail/IMailLogService.cs new file mode 100644 index 00000000..db9b9e11 --- /dev/null +++ b/Source/Extensions/H.Extensions.Mail/IMailLogService.cs @@ -0,0 +1,7 @@ +namespace H.Extensions.Mail +{ + public interface IMailLogService + { + bool Send(string subject, string body, out string message); + } +} \ No newline at end of file diff --git a/Source/Extensions/H.Extensions.Mail/IMailService.cs b/Source/Extensions/H.Extensions.Mail/IMailService.cs new file mode 100644 index 00000000..92404fc3 --- /dev/null +++ b/Source/Extensions/H.Extensions.Mail/IMailService.cs @@ -0,0 +1,9 @@ +using H.Extensions.Mail; + +namespace H.Extensions.Mail +{ + public interface IMailService + { + bool Send(MailMessageItem messageItem, bool isBodyHtml, out string message); + } +} \ No newline at end of file diff --git a/Source/Extensions/H.Extensions.Mail/MailLogService.cs b/Source/Extensions/H.Extensions.Mail/MailLogService.cs new file mode 100644 index 00000000..02006ec2 --- /dev/null +++ b/Source/Extensions/H.Extensions.Mail/MailLogService.cs @@ -0,0 +1,19 @@ +using System; +using H.Extensions.Mail; + +namespace H.Extensions.Mail +{ + public class MailLogService : IMailLogService + { + public bool Send(string subject, string body, out string message) + { + message = null; + MailMessageItem mail = new MailMessageItem(); + mail.Subject = subject; + mail.Body = body; + mail.From = SmtpSendOptions.Instance.User; + mail.To = new string[] { SmtpSendOptions.Instance.User }; + return Ioc.Instance?.Send(mail, SmtpSendOptions.Instance.IsBodyHtml, out message) == true; + } + } +} diff --git a/Source/Extensions/H.Extensions.Mail/MailService.cs b/Source/Extensions/H.Extensions.Mail/MailService.cs new file mode 100644 index 00000000..75ca17ab --- /dev/null +++ b/Source/Extensions/H.Extensions.Mail/MailService.cs @@ -0,0 +1,81 @@ +using System; +using System.IO; +using System.Net; +using System.Net.Mail; +using System.Net.Mime; +using H.Extensions.Mail; + +namespace H.Extensions.Mail +{ + public class MailService : IMailService + { + public bool Send(MailMessageItem messageItem, bool isBodyHtml, out string message) + { + message = null; + SmtpClient smtp = new SmtpClient() + { + Host = SmtpSendOptions.Instance.Host, + Port = SmtpSendOptions.Instance.Port, + EnableSsl = SmtpSendOptions.Instance.EnableSsl, + DeliveryMethod = SmtpDeliveryMethod.Network, + UseDefaultCredentials = false, + Credentials = new NetworkCredential(SmtpSendOptions.Instance.User, SmtpSendOptions.Instance.Password) + }; + + using MailMessage msg = new(); + msg.From = new MailAddress(messageItem.From); + foreach (var to in messageItem.To) + { + msg.To.Add(new MailAddress(to)); + } + + if (messageItem.Cc != null) + { + foreach (var cc in messageItem.Cc) + { + msg.CC.Add(new MailAddress(cc)); + } + } + + if (messageItem.Bcc != null) + { + foreach (var bcc in messageItem.Bcc) + { + msg.Bcc.Add(new MailAddress(bcc)); + } + } + + msg.Subject = messageItem.Subject; + msg.Body = messageItem.Body; + msg.BodyEncoding = System.Text.Encoding.UTF8; + msg.IsBodyHtml = isBodyHtml; + msg.SubjectEncoding = System.Text.Encoding.UTF8; + if (messageItem.Attachments != null) + { + foreach (var attachment in messageItem.Attachments) + { + Attachment data = new(attachment.FullName, MediaTypeNames.Application.Octet); + var disposition = data.ContentDisposition; + disposition!.CreationDate = File.GetCreationTime(attachment.FullName); + disposition.ModificationDate = File.GetLastWriteTime(attachment.FullName); + disposition.ReadDate = File.GetLastAccessTime(attachment.FullName); + msg.Attachments.Add(data); + } + } + try + { + smtp.Send(msg); + } + catch (System.Exception ex) + { + message = ex.Message; + IocLog.Instance?.Error(ex); + return false; + } + return true; + } + + + } + +} diff --git a/Source/Extensions/H.Extensions.Mail/Provider/MailMessageItem.cs b/Source/Extensions/H.Extensions.Mail/Provider/MailMessageItem.cs new file mode 100644 index 00000000..bbae5051 --- /dev/null +++ b/Source/Extensions/H.Extensions.Mail/Provider/MailMessageItem.cs @@ -0,0 +1,19 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace H.Extensions.Mail +{ + public class MailMessageItem + { + public string From { get; set; } = SmtpSendOptions.Instance.User; + public string[] To { get; set; } = { SmtpSendOptions.Instance.User }; + public string[] Cc { get; set; } + public string[] Bcc { get; set; } + public string Subject { get; set; } + public string Body { get; set; } + public FileInfo[] Attachments { get; set; } + } +} diff --git a/Source/Extensions/H.Extensions.Mail/Provider/SendMainCommand.cs b/Source/Extensions/H.Extensions.Mail/Provider/SendMainCommand.cs new file mode 100644 index 00000000..efae6941 --- /dev/null +++ b/Source/Extensions/H.Extensions.Mail/Provider/SendMainCommand.cs @@ -0,0 +1,20 @@ +using H.Providers.Mvvm; +using System; + +namespace H.Extensions.Mail +{ + public class SendMainCommand : MarkupCommandBase + { + public override void Execute(object parameter) + { + if (parameter is MailMessageItem messageItem) + Ioc.Instance?.Send(messageItem, SmtpSendOptions.Instance.IsBodyHtml, out string message); + } + + public override bool CanExecute(object parameter) + { + return Ioc.Instance != null; + } + } + +} diff --git a/Source/Extensions/H.Extensions.Mail/SmtpSendOptions.cs b/Source/Extensions/H.Extensions.Mail/SmtpSendOptions.cs new file mode 100644 index 00000000..44aae290 --- /dev/null +++ b/Source/Extensions/H.Extensions.Mail/SmtpSendOptions.cs @@ -0,0 +1,99 @@ +using H.Extensions.Setting; +using H.Providers.Ioc; +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; + +namespace H.Extensions.Mail +{ + [Display(Name = "邮件外发设置", GroupName = SettingGroupNames.GroupSystem, Description = "邮件外发设置的信息")] + public class SmtpSendOptions : IocOptionInstance + { + private string _host; + [Required] + [DefaultValue("smtp.163.com")] + [ReadOnly(true)] + [Display(Name = "服务器")] + public string Host + { + get { return _host; } + set + { + _host = value; + RaisePropertyChanged(); + } + } + + + private int _port; + [DefaultValue(25)] + [ReadOnly(true)] + [Display(Name = "端口号")] + public int Port + { + get { return _port; } + set + { + _port = value; + RaisePropertyChanged(); + } + } + + + private bool _enableSsl; + [DefaultValue(true)] + [Display(Name = "启用SSL")] + public bool EnableSsl + { + get { return _enableSsl; } + set + { + _enableSsl = value; + RaisePropertyChanged(); + } + } + + private string _user; + [Required] + [DefaultValue("HeBianGu2024@163.com")] + [Display(Name = "用户名")] + [ReadOnly(true)] + public string User + { + get { return _user; } + set + { + _user = value; + RaisePropertyChanged(); + } + } + + + private string _password; + [Required] + [Display(Name = "密码")] + [Browsable(false)] + public string Password + { + get { return _password; } + set + { + _password = value; + RaisePropertyChanged(); + } + } + + private bool _isBodyHtml; + [Display(Name = "启用HTML格式")] + public bool IsBodyHtml + { + get { return _isBodyHtml; } + set + { + _isBodyHtml = value; + RaisePropertyChanged(); + } + } + + } + +} diff --git a/Source/Extensions/H.Extensions.Mail/Themes/Generic.xaml b/Source/Extensions/H.Extensions.Mail/Themes/Generic.xaml new file mode 100644 index 00000000..ec27ee08 --- /dev/null +++ b/Source/Extensions/H.Extensions.Mail/Themes/Generic.xaml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/H.Modules.Messages.Dialog/AdonerDialog/AdornerDialogPresenter.xaml b/Source/Modules/H.Modules.Messages.Dialog/AdonerDialog/AdornerDialogPresenter.xaml index a2768838..a0f5cbd7 100644 --- a/Source/Modules/H.Modules.Messages.Dialog/AdonerDialog/AdornerDialogPresenter.xaml +++ b/Source/Modules/H.Modules.Messages.Dialog/AdonerDialog/AdornerDialogPresenter.xaml @@ -4,9 +4,11 @@ xmlns:h="https://github.com/HeBianGu" xmlns:local="clr-namespace:H.Modules.Messages.Dialog"> - + - + - - - - + + + + + + + - + - + - + diff --git a/Source/Modules/H.Modules.Setting/SettingViewPresenter.xaml b/Source/Modules/H.Modules.Setting/SettingViewPresenter.xaml index dcd30d80..1c53f6f2 100644 --- a/Source/Modules/H.Modules.Setting/SettingViewPresenter.xaml +++ b/Source/Modules/H.Modules.Setting/SettingViewPresenter.xaml @@ -54,15 +54,19 @@ FontWeight="Bold" Text="{Binding Name}" ToolTip="{Binding Description}" /> - - + + + + + diff --git a/Source/Tests/H.Test.Test/App.xaml.cs b/Source/Tests/H.Test.Test/App.xaml.cs index 5ac39f23..c662bd31 100644 --- a/Source/Tests/H.Test.Test/App.xaml.cs +++ b/Source/Tests/H.Test.Test/App.xaml.cs @@ -67,6 +67,7 @@ protected override void ConfigureServices(IServiceCollection services) }); services.AddSchedule(); + services.AddMail(); } protected override void Configure(IApplicationBuilder app) @@ -77,6 +78,8 @@ protected override void Configure(IApplicationBuilder app) { x.LibvlcPath = "G:\\BaiduNetdiskDownload\\libvlc\\win-x64"; }); + + app.UseMail(); } } } diff --git a/Source/Tests/H.Test.Test/H.Test.Test.csproj b/Source/Tests/H.Test.Test/H.Test.Test.csproj index 9e1656a6..90ccb5de 100644 --- a/Source/Tests/H.Test.Test/H.Test.Test.csproj +++ b/Source/Tests/H.Test.Test/H.Test.Test.csproj @@ -27,6 +27,7 @@ + diff --git a/Source/Tests/H.Test.Test/MainWindow.xaml b/Source/Tests/H.Test.Test/MainWindow.xaml index 705da1f9..4a0deb62 100644 --- a/Source/Tests/H.Test.Test/MainWindow.xaml +++ b/Source/Tests/H.Test.Test/MainWindow.xaml @@ -581,7 +581,8 @@ PropertyName="Value1" /> - + - + @@ -930,6 +931,17 @@ + + +