forked from ddrilling/AsbCloudServer
Степанов Дмитрий Александрович
4b2d4f1bba
1. Адаптировал EmailService под сервис транспорта отправки уведомлений по Email 2. Заменил использование EmailService на NotificationService 3. Поправил тесты 4. Создал запрос для отправки уведомлений
141 lines
5.1 KiB
C#
141 lines
5.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Net.Mail;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using AsbCloudApp.Data;
|
|
using AsbCloudApp.Exceptions;
|
|
using AsbCloudApp.Services.Notifications;
|
|
using AsbCloudInfrastructure.Background;
|
|
using Microsoft.Extensions.Configuration;
|
|
|
|
namespace AsbCloudInfrastructure.Services.Email
|
|
{
|
|
|
|
public class EmailNotificationTransportService : INotificationTransportService
|
|
{
|
|
private readonly BackgroundWorker backgroundWorker;
|
|
private readonly bool IsConfigured;
|
|
private readonly string sender;
|
|
private readonly string smtpServer;
|
|
private readonly string smtpPassword;
|
|
|
|
public EmailNotificationTransportService(BackgroundWorker backgroundWorker,
|
|
IConfiguration configuration)
|
|
{
|
|
sender = configuration.GetValue("email:sender", string.Empty);
|
|
smtpPassword = configuration.GetValue("email:password", string.Empty);
|
|
smtpServer = configuration.GetValue("email:smtpServer", string.Empty);
|
|
|
|
var configError = string.IsNullOrEmpty(sender) ||
|
|
string.IsNullOrEmpty(smtpPassword) ||
|
|
string.IsNullOrEmpty(smtpServer);
|
|
|
|
IsConfigured = !configError;
|
|
|
|
this.backgroundWorker = backgroundWorker;
|
|
}
|
|
|
|
public int IdTransportType => 1;
|
|
|
|
public Task SendAsync(NotificationDto notification, CancellationToken cancellationToken)
|
|
{
|
|
if (!IsConfigured)
|
|
{
|
|
Trace.TraceWarning("smtp is not configured");
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(notification.UserEmail))
|
|
{
|
|
Trace.TraceWarning("User email is not null");
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
var workId = MakeWorkId(new []{ notification.UserEmail }, notification.Title, notification.Message);
|
|
if (!backgroundWorker.Contains(workId))
|
|
{
|
|
var workAction = MakeEmailSendWorkAction(new []{ notification.UserEmail }, notification.Title, notification.Message);
|
|
var work = new WorkBase(workId, workAction);
|
|
backgroundWorker.Push(work);
|
|
}
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SendRangeAsync(IEnumerable<NotificationDto> notifications, CancellationToken cancellationToken)
|
|
{
|
|
var tasks = notifications
|
|
.Select(notification => SendAsync(notification, cancellationToken));
|
|
|
|
return Task.WhenAll(tasks);
|
|
}
|
|
|
|
|
|
private Func<string, IServiceProvider, CancellationToken, Task> MakeEmailSendWorkAction(IEnumerable<string> addresses, string subject, string htmlBody)
|
|
{
|
|
var mailAddresses = new List<MailAddress>();
|
|
foreach (var address in addresses)
|
|
{
|
|
if (MailAddress.TryCreate(address, out MailAddress? mailAddress))
|
|
mailAddresses.Add(mailAddress);
|
|
else
|
|
Trace.TraceWarning($"Mail {address} is not correct.");
|
|
}
|
|
|
|
if (!mailAddresses.Any())
|
|
throw new ArgumentException($"No valid email found. List:[{string.Join(',', addresses)}]", nameof(addresses));
|
|
|
|
if (string.IsNullOrEmpty(subject))
|
|
throw new ArgumentInvalidException($"{nameof(subject)} should be set", nameof(subject));
|
|
|
|
var workAction = async (string id, IServiceProvider serviceProvider, CancellationToken token) =>
|
|
{
|
|
var from = new MailAddress(sender);
|
|
var message = new MailMessage
|
|
{
|
|
From = from
|
|
};
|
|
|
|
foreach (var mailAddress in mailAddresses)
|
|
message.To.Add(mailAddress);
|
|
|
|
message.BodyEncoding = System.Text.Encoding.UTF8;
|
|
message.Body = htmlBody;
|
|
message.Subject = subject;
|
|
message.IsBodyHtml = true;
|
|
|
|
using var client = new SmtpClient(smtpServer);
|
|
client.EnableSsl = true;
|
|
client.UseDefaultCredentials = false;
|
|
client.Credentials = new System.Net.NetworkCredential(sender, smtpPassword);
|
|
|
|
await client.SendMailAsync(message, token);
|
|
Trace.TraceInformation($"Send email to {string.Join(',', addresses)} subj:{subject} html body count {htmlBody.Length}");
|
|
};
|
|
return workAction;
|
|
}
|
|
|
|
private static string MakeWorkId(IEnumerable<string> addresses, string subject, string content)
|
|
{
|
|
var hash = GetHashCode(addresses);
|
|
hash ^= subject.GetHashCode();
|
|
hash ^= content.GetHashCode();
|
|
return hash.ToString("x");
|
|
}
|
|
|
|
private static int GetHashCode(IEnumerable<string> strings)
|
|
{
|
|
int hash = -1397075115;
|
|
var enumerator = strings.GetEnumerator();
|
|
|
|
while (enumerator.MoveNext())
|
|
hash ^= enumerator.Current.GetHashCode();
|
|
return hash;
|
|
}
|
|
}
|
|
|
|
}
|