Модели и бизнес-логика по отправке и получению писем

This commit is contained in:
prodigygirl 2023-04-19 15:42:26 +04:00
parent b2fcaab4ee
commit 069bc1e309
8 changed files with 230 additions and 6 deletions

View File

@ -8,6 +8,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace FurnitureAssemblyBusinessLogic
@ -112,6 +113,17 @@ namespace FurnitureAssemblyBusinessLogic
throw new ArgumentNullException("Нет пароля пользователя",
nameof(model.Password));
}
if (!Regex.IsMatch(model.Email, @"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,})+)$"))
{
throw new ArgumentException("Некорректно введена почта клиента", nameof(model.Email));
}
if (!Regex.IsMatch(model.Password, @"^((\w+\d+\W+)|(\w+\W+\d+)|(\d+\w+\W+)|(\d+\W+\w+)|(\W+\w+\d+)|(\W+\d+\w+))[\w\d\W]*$"))
{
throw new ArgumentException("Некорректно введен пароль клиента", nameof(model.Password));
}
_logger.LogInformation("Component. ClientFIO:{ClientFIO}. Email:{ Email}. Id: { Id}", model.ClientFIO, model.Email, model.Id);
var element = _clientStorage.GetElement(new ClientSearchModel { Email = model.Email });
if (element != null && element.Id != model.Id)

View File

@ -8,6 +8,7 @@
<ItemGroup>
<PackageReference Include="DocumentFormat.OpenXml" Version="2.19.0" />
<PackageReference Include="MailKit" Version="4.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" />

View File

@ -0,0 +1,81 @@
using FurnitureAssemblyContracts.BindingModels;
using FurnitureAssemblyContracts.BusinessLogicsContarcts;
using Microsoft.Extensions.Logging;
namespace FurnitureAssemblyBusinessLogic.MailWorker
{
public abstract class AbstractMailWorker
{
protected string _mailLogin = string.Empty;
protected string _mailPassword = string.Empty;
protected string _smtpClientHost = string.Empty;
protected int _smtpClientPort;
protected string _popHost = string.Empty;
protected int _popPort;
private readonly IMessageInfoLogic _messageInfoLogic;
private readonly ILogger _logger;
private readonly IClientLogic _clientLogic;
public AbstractMailWorker(ILogger<AbstractMailWorker> logger,
IMessageInfoLogic messageInfoLogic,
IClientLogic clientLogic)
{
_logger = logger;
_messageInfoLogic = messageInfoLogic;
_clientLogic = clientLogic;
}
public void MailConfig(MailConfigBindingModel config)
{
_mailLogin = config.MailLogin;
_mailPassword = config.MailPassword;
_smtpClientHost = config.SmtpClientHost;
_smtpClientPort = config.SmtpClientPort;
_popHost = config.PopHost;
_popPort = config.PopPort;
_logger.LogDebug("Config: {login}, {password}, {clientHost},{ clientPOrt}, { popHost}, { popPort}", _mailLogin, _mailPassword, _smtpClientHost,
_smtpClientPort, _popHost, _popPort);
}
public async void MailSendAsync(MailSendInfoBindingModel info)
{
if (string.IsNullOrEmpty(_mailLogin) || string.IsNullOrEmpty(_mailPassword))
{
return;
}
if (string.IsNullOrEmpty(_smtpClientHost) || _smtpClientPort == 0)
{
return;
}
if (string.IsNullOrEmpty(info.MailAddress) ||
string.IsNullOrEmpty(info.Subject) || string.IsNullOrEmpty(info.Text))
{
return;
}
_logger.LogDebug("Send Mail: {To}, {Subject}", info.MailAddress,
info.Subject);
await SendMailAsync(info);
}
public async void MailCheck()
{
if (string.IsNullOrEmpty(_mailLogin) || string.IsNullOrEmpty(_mailPassword))
{
return;
}
if (string.IsNullOrEmpty(_popHost) || _popPort == 0)
{
return;
}
if (_messageInfoLogic == null)
{
return;
}
var list = await ReceiveMailAsync();
_logger.LogDebug("Check Mail: {Count} new mails", list.Count);
foreach (var mail in list)
{
mail.ClientId = _clientLogic.ReadElement(new() { Email = mail.SenderName })?.Id;
_messageInfoLogic.Create(mail);
}
}
protected abstract Task SendMailAsync(MailSendInfoBindingModel info);
protected abstract Task<List<MessageInfoBindingModel>> ReceiveMailAsync();
}
}

View File

@ -0,0 +1,79 @@
using FurnitureAssemblyContracts.BindingModels;
using FurnitureAssemblyContracts.BusinessLogicsContarcts;
using Microsoft.Extensions.Logging;
using System.Net.Mail;
using System.Net;
using System.Text;
using MailKit.Net.Pop3;
using MailKit.Security;
namespace FurnitureAssemblyBusinessLogic.MailWorker
{
public class MailKitWorker : AbstractMailWorker
{
public MailKitWorker(ILogger<MailKitWorker> logger, IMessageInfoLogic messageInfoLogic, IClientLogic clientLogic) : base(logger, messageInfoLogic, clientLogic) { }
protected override async Task SendMailAsync(MailSendInfoBindingModel
info)
{
using var objMailMessage = new MailMessage();
using var objSmtpClient = new SmtpClient(_smtpClientHost,_smtpClientPort);
try
{
objMailMessage.From = new MailAddress(_mailLogin);
objMailMessage.To.Add(new MailAddress(info.MailAddress));
objMailMessage.Subject = info.Subject;
objMailMessage.Body = info.Text;
objMailMessage.SubjectEncoding = Encoding.UTF8;
objMailMessage.BodyEncoding = Encoding.UTF8;
objSmtpClient.UseDefaultCredentials = false;
objSmtpClient.EnableSsl = true;
objSmtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
objSmtpClient.Credentials = new NetworkCredential(_mailLogin,
_mailPassword);
await Task.Run(() => objSmtpClient.Send(objMailMessage));
}
catch (Exception)
{
throw;
}
}
protected override async Task<List<MessageInfoBindingModel>>
ReceiveMailAsync()
{
var list = new List<MessageInfoBindingModel>();
using var client = new Pop3Client();
await Task.Run(() =>
{
try
{
client.Connect(_popHost, _popPort, SecureSocketOptions.SslOnConnect);
client.Authenticate(_mailLogin, _mailPassword);
for (int i = 0; i < client.Count; i++)
{
var message = client.GetMessage(i);
foreach (var mail in message.From.Mailboxes)
{
list.Add(new MessageInfoBindingModel
{
DateDelivery = message.Date.DateTime,
MessageId = message.MessageId,
SenderName = mail.Address,
Subject = message.Subject,
Body = message.TextBody
});
}
}
}
catch (AuthenticationException)
{ }
finally
{
client.Disconnect(true);
}
});
return list;
}
}
}

View File

@ -1,4 +1,5 @@
using FurnitureAssemblyContracts.BindingModels;
using FurnitureAssemblyBusinessLogic.MailWorker;
using FurnitureAssemblyContracts.BindingModels;
using FurnitureAssemblyContracts.BusinessLogicsContarcts;
using FurnitureAssemblyContracts.SearchModels;
using FurnitureAssemblyContracts.StoragesContracts;
@ -17,11 +18,15 @@ namespace FurnitureAssemblyBusinessLogic
{
private readonly ILogger _logger;
private readonly IOrderStorage _orderStorage;
private readonly AbstractMailWorker _mailWorker;
private readonly IClientLogic _clientLogic;
public OrderLogic(ILogger<OrderLogic> logger, IOrderStorage orderStorage)
public OrderLogic(ILogger<OrderLogic> logger, IOrderStorage orderStorage, IClientLogic clientLogic, AbstractMailWorker abstractMailWorker)
{
_logger = logger;
_orderStorage = orderStorage;
_clientLogic = clientLogic;
_mailWorker = abstractMailWorker;
}
private bool ChangeStatus(OrderBindingModel model, OrderStatus orderStatus)
@ -31,6 +36,7 @@ namespace FurnitureAssemblyBusinessLogic
return false;
}
model.Status = orderStatus;
SendMail(model.ClientId, $"Статус заказа {model.Id} изменен", $"Заказ {model.Id} переведен в статус {model.Status}");
return true;
}
@ -43,13 +49,13 @@ namespace FurnitureAssemblyBusinessLogic
_logger.LogWarning("Order's status is wrong");
throw new InvalidOperationException("Order's status is wrong");
}
if (_orderStorage.Insert(model) == null)
var order = _orderStorage.Insert(model);
if (order == null)
{
_logger.LogWarning("Insert operation failed");
return false;
}
SendMail(model.ClientId, $"Создание заказа {order.Id}", $"Заказ под номером {order.Id} создан {model.DateCreate}");
return true;
}
@ -61,6 +67,8 @@ namespace FurnitureAssemblyBusinessLogic
return false;
}
model.Status = modelNew.Status;
model.ClientId = modelNew.ClientId;
model.Id = modelNew.Id;
if (!ChangeStatus(model, OrderStatus.Выполняется))
{
_logger.LogWarning("Order's status is wrong");
@ -76,7 +84,9 @@ namespace FurnitureAssemblyBusinessLogic
if (modelNew == null) {
return false;
}
model.Id = modelNew.Id;
model.Status = modelNew.Status;
model.ClientId = modelNew.ClientId;
model.ImplementerId = modelNew.ImplementerId;
if (!ChangeStatus(model, OrderStatus.Готов))
{
@ -95,7 +105,9 @@ namespace FurnitureAssemblyBusinessLogic
{
return false;
}
model.Id = modelNew.Id;
model.Status = modelNew.Status;
model.ClientId = modelNew.ClientId;
model.ImplementerId = modelNew.ImplementerId;
model.DateImplement = modelNew.DateImplement;
if (!ChangeStatus(model, OrderStatus.Выдан))
@ -166,5 +178,22 @@ namespace FurnitureAssemblyBusinessLogic
_logger.LogInformation("ReadElement find. Id:{Id}", element.Id);
return element;
}
private bool SendMail(int clientId, string subject, string text)
{
var client = _clientLogic.ReadElement(new() { Id = clientId});
if (client == null)
{
_logger.LogWarning("Email sending failed. Client with id {Id} not found", clientId);
return false;
}
_mailWorker.MailSendAsync(new MailSendInfoBindingModel()
{
Subject = subject,
Text = text,
MailAddress = client.Email
});
return true;
}
}
}

View File

@ -0,0 +1,13 @@
namespace FurnitureAssemblyContracts.BindingModels
{
public class MailConfigBindingModel
{
public string MailLogin { get; set; } = string.Empty;
public string MailPassword { get; set; } = string.Empty;
public string SmtpClientHost { get; set; } = string.Empty;
public int SmtpClientPort { get; set; }
public string PopHost { get; set; } = string.Empty;
public int PopPort { get; set; }
}
}

View File

@ -0,0 +1,9 @@
namespace FurnitureAssemblyContracts.BindingModels
{
public class MailSendInfoBindingModel
{
public string MailAddress { get; set; } = string.Empty;
public string Subject { get; set; } = string.Empty;
public string Text { get; set; } = string.Empty;
}
}

View File

@ -30,7 +30,7 @@ namespace FurnitureAssemblyDatabaseImplement.Implements
}
using var context = new FurnitureAssemblyDatabase();
return context.Messages
.Where(x => x.ClientId.Equals(model.ClientId))
.Where(x => x.ClientId == model.ClientId)
.Select(x => x.GetViewModel)
.ToList();
}