Files
wpywmail/server-native/DeliveryQueue.cs
T

76 lines
2.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Net;
using System.Net.Mail;
namespace WpywMail.Native;
public sealed class DeliveryQueue
{
private readonly AppConfig config;
private readonly FileStore store;
private readonly DirectSmtpDelivery direct;
public DeliveryQueue(AppConfig config, FileStore store)
{
this.config = config;
this.store = store;
direct = new DirectSmtpDelivery(config, store);
}
public async Task RunAsync(CancellationToken token)
{
AppLog.Info($"[发送] 投递模式:{(config.DeliveryMode.Equals("relay", StringComparison.OrdinalIgnoreCase) ? "SMTP 中继" : "按 MX 直接投递")}");
while (!token.IsCancellationRequested)
{
foreach (var job in store.TakeDueQueue(10))
{
try
{
var message = store.GetById(job.MessageId) ?? throw new InvalidOperationException("发送队列中的邮件不存在。");
await Deliver(message, job.Recipients, token);
store.CompleteQueue(job);
AppLog.Info($"[发送] 投递成功:{string.Join(", ", job.Recipients)}");
}
catch (Exception ex)
{
store.FailQueue(job, ex);
AppLog.Error($"[发送队列] {job.MessageId} → {string.Join(", ", job.Recipients)}:{ex.Message}");
}
}
await Task.Delay(TimeSpan.FromSeconds(5), token).ContinueWith(_ => { });
}
}
private async Task Deliver(MailMessage message, string[] recipients, CancellationToken token)
{
if (config.DeliveryMode.Equals("relay", StringComparison.OrdinalIgnoreCase))
{
await DeliverThroughRelay(message, recipients, token);
return;
}
await direct.DeliverAsync(message, recipients, token);
}
private async Task DeliverThroughRelay(MailMessage message, string[] recipients, CancellationToken token)
{
if (string.IsNullOrWhiteSpace(config.Relay.Host)) throw new InvalidOperationException("DeliveryMode=relay 时必须配置 Relay.Host。");
using var client = new SmtpClient(config.Relay.Host, config.Relay.Port)
{
EnableSsl = config.Relay.EnableSsl,
DeliveryMethod = SmtpDeliveryMethod.Network,
Timeout = 60_000
};
if (!string.IsNullOrWhiteSpace(config.Relay.User)) client.Credentials = new NetworkCredential(config.Relay.User, config.Relay.Password);
using var mail = new System.Net.Mail.MailMessage
{
From = new MailAddress(message.From),
Subject = message.Subject,
Body = message.Text,
BodyEncoding = System.Text.Encoding.UTF8,
SubjectEncoding = System.Text.Encoding.UTF8
};
foreach (var recipient in recipients) mail.To.Add(recipient);
await client.SendMailAsync(mail, token);
}
}