diff --git a/src/client/Bootstrap.Client/Controllers/Api/InterfaceController.cs b/src/client/Bootstrap.Client/Controllers/Api/InterfaceController.cs index 9a5f717b..f98a94c5 100644 --- a/src/client/Bootstrap.Client/Controllers/Api/InterfaceController.cs +++ b/src/client/Bootstrap.Client/Controllers/Api/InterfaceController.cs @@ -1,4 +1,5 @@ -using Microsoft.AspNetCore.Authorization; +using Bootstrap.Client.Extensions; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using System.Net; @@ -59,17 +60,18 @@ namespace Bootstrap.Client.Controllers.Api var port = section.GetValue("Port", 25); var enableSsl = section.GetValue("EnableSsl", false); - if (!string.IsNullOrEmpty(password)) + var smtpMessage = new SmtpMessage() { - using var mailSender = new SmtpClient(smtpHost) - { - Credentials = new NetworkCredential(from, password), - Port = port, - EnableSsl = enableSsl - }; - await mailSender.SendMailAsync(from, to, title, message); - } - return true; + Host = smtpHost, + Password = password, + From = from, + To = to, + Port = port, + EnableSsl = enableSsl, + Title = title, + Message = message + }; + return await smtpMessage.SendAsync(); } } } diff --git a/src/client/Bootstrap.Client/Extensions/SmtpExtensions.cs b/src/client/Bootstrap.Client/Extensions/SmtpExtensions.cs new file mode 100644 index 00000000..9e6923ae --- /dev/null +++ b/src/client/Bootstrap.Client/Extensions/SmtpExtensions.cs @@ -0,0 +1,148 @@ +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Mail; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Bootstrap.Client.Extensions +{ + /// + /// SmtpExtensions 扩展类 + /// + public static class SmtpExtensions + { + /// + /// 异步发送方法 + /// + public static Task SendAsync(this SmtpMessage message) + { + message.Push(); + return Task.FromResult(true); + } + } + + /// + /// SmtpMessage 邮件实体类 + /// + public class SmtpMessage + { + /// + /// 获得/设置 主机地址 + /// + public string Host { get; set; } = ""; + + /// + /// 获得/设置 邮箱密码 + /// + public string Password { get; set; } = ""; + + /// + /// 获得/设置 发件人地址 + /// + public string From { get; set; } = ""; + + /// + /// 获得/设置 收件人地址 + /// + public string To { get; set; } = ""; + + /// + /// 获得/设置 端口 + /// + public int Port { get; set; } + + /// + /// 获得/设置 是否启用 SSL + /// + public bool EnableSsl { get; set; } + + /// + /// 获得/设置 邮件标题 + /// + public string Title { get; set; } = ""; + + /// + /// 获得/设置 邮件正文 + /// + public string Message { get; set; } = ""; + + private static BlockingCollection _messageQueue = new BlockingCollection(new ConcurrentQueue()); + private static CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); + private static readonly List _currentBatch = new List(); + private static Task _logTask = Task.Run(ProcessLogQueue); + + /// + /// 将邮件添加到队列中 + /// + public void Push() + { + if (!_messageQueue.IsAddingCompleted) _messageQueue.Add(this, _cancellationTokenSource.Token); + } + + private static async Task ProcessLogQueue() + { + while (!_cancellationTokenSource.IsCancellationRequested) + { + var limit = 100; + while (limit > 0 && _messageQueue.TryTake(out var message)) + { + _currentBatch.Add(message); + limit--; + } + + try + { + if (_currentBatch.Any()) + { + await SendAsync(_currentBatch); + _currentBatch.Clear(); + } + await Task.Delay(60000, _cancellationTokenSource.Token); + } + catch (TaskCanceledException) + { + break; + } + } + _cancellationTokenSource.Dispose(); + + // flush message to file + while (_messageQueue.TryTake(out var message)) _currentBatch.Add(message); + await SendAsync(_currentBatch); + } + + private static async Task SendAsync(IEnumerable messages) + { + if (messages.Any()) + { + var content = new StringBuilder(); + SmtpClient? sender = null; + string from = ""; + string to = ""; + string title = ""; + foreach (var msg in messages) + { + if (sender == null) + { + from = msg.From; + to = msg.To; + title = msg.Title; + sender = new SmtpClient(msg.Host) + { + Credentials = new NetworkCredential(msg.From, msg.Password), + Port = msg.Port, + EnableSsl = msg.EnableSsl + }; + } + + // 合并消息 + content.AppendLine(msg.Message); + } + if (sender != null) await sender.SendMailAsync(from, to, title, content.ToString()); + } + } + } +}