Errors MailKit SendMailAsync

This commit is contained in:
Игорь Гордеев 2024-05-16 18:55:15 +04:00
parent cdb16bba7b
commit 69557dc426
23 changed files with 525 additions and 138 deletions

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="SmtpClientHost" value="smtp.gmail.com" />
<add key="SmtpClientPort" value="587" />
<add key="PopHost" value="pop.gmail.com" />
<add key="PopPort" value="995" />
<add key="MailLogin" value="89176335310x@gmail.com" />
<add key="MailPassword" value="wmbu qrgy ocwl tadm" />
</appSettings>
</configuration>

View File

@ -8,6 +8,8 @@ using SushiBarContracts.BusinessLogicsContracts;
using SushiBarContracts.StoragesContracts; using SushiBarContracts.StoragesContracts;
using SushiBarDatabaseImplement.Implements; using SushiBarDatabaseImplement.Implements;
using SushiBarBusinessLogic; using SushiBarBusinessLogic;
using SushiBarBusinessLogic.MailWorker;
using SushiBarContracts.BindingModels;
namespace SushiBarView namespace SushiBarView
{ {
@ -24,13 +26,32 @@ namespace SushiBarView
// To customize application configuration such as set high DPI settings or default font, // To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration. // see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize(); ApplicationConfiguration.Initialize();
var services = new ServiceCollection();
ConfigureServices(services);
_serviceProvider = services.BuildServiceProvider();
try
{
var mailSender = _serviceProvider.GetService<AbstractMailWorker>();
mailSender?.MailConfig(new MailConfigBindingModel
{
MailLogin = System.Configuration.ConfigurationManager.AppSettings["MailLogin"] ?? string.Empty,
MailPassword = System.Configuration.ConfigurationManager.AppSettings["MailPassword"] ?? string.Empty,
SmtpClientHost = System.Configuration.ConfigurationManager.AppSettings["SmtpClientHost"] ?? string.Empty,
SmtpClientPort = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["SmtpClientPort"]),
PopHost = System.Configuration.ConfigurationManager.AppSettings["PopHost"] ?? string.Empty,
PopPort = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["PopPort"])
});
var services = new ServiceCollection(); var timer = new System.Threading.Timer(new TimerCallback(MailCheck!), null, 0, 100000);
ConfigureServices(services); }
_serviceProvider = services.BuildServiceProvider(); catch (Exception ex)
{
var logger = _serviceProvider.GetService<ILogger>();
logger?.LogError(ex, "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
}
Application.Run(_serviceProvider.GetRequiredService<FormMain>()); Application.Run(_serviceProvider.GetRequiredService<FormMain>());
} }
private static void ConfigureServices(ServiceCollection services) private static void ConfigureServices(ServiceCollection services)
{ {
@ -44,16 +65,18 @@ namespace SushiBarView
services.AddTransient<ISushiStorage, SushiStorage>(); services.AddTransient<ISushiStorage, SushiStorage>();
services.AddTransient<IClientStorage, ClientStorage>(); services.AddTransient<IClientStorage, ClientStorage>();
services.AddTransient<IImplementerStorage, ImplementerStorage>(); services.AddTransient<IImplementerStorage, ImplementerStorage>();
services.AddTransient<IMessageInfoStorage, MessageInfoStorage>();
services.AddTransient<IIngredientLogic, IngredientLogic>(); services.AddTransient<IIngredientLogic, IngredientLogic>();
services.AddTransient<IOrderLogic, OrderLogic>(); services.AddTransient<IOrderLogic, OrderLogic>();
services.AddTransient<ISushiLogic, SushiLogic>(); services.AddTransient<ISushiLogic, SushiLogic>();
services.AddTransient<IClientLogic, ClientLogic>(); services.AddTransient<IClientLogic, ClientLogic>();
services.AddTransient<IReportLogic, ReportLogic>(); services.AddTransient<IReportLogic, ReportLogic>();
services.AddTransient<IImplementerLogic, ImplementerLogic>(); services.AddTransient<IImplementerLogic, ImplementerLogic>();
services.AddTransient<IWorkProcess, WorkModeling>(); services.AddTransient<IWorkProcess, WorkModeling>();
services.AddTransient<IMessageInfoLogic, MessageInfoLogic>();
services.AddTransient<FormMain>(); services.AddTransient<FormMain>();
services.AddTransient<FormIngredient>(); services.AddTransient<FormIngredient>();
services.AddTransient<FormIngredients>(); services.AddTransient<FormIngredients>();
services.AddTransient<FormCreateOrder>(); services.AddTransient<FormCreateOrder>();
@ -70,7 +93,8 @@ namespace SushiBarView
services.AddTransient<AbstractSaveToExcel, SaveToExcel>(); services.AddTransient<AbstractSaveToExcel, SaveToExcel>();
services.AddTransient<AbstractSaveToWord, SaveToWord>(); services.AddTransient<AbstractSaveToWord, SaveToWord>();
services.AddTransient<AbstractSaveToPdf, SaveToPdf>(); services.AddTransient<AbstractSaveToPdf, SaveToPdf>();
} services.AddSingleton<AbstractMailWorker, MailKitWorker>();
}
} private static void MailCheck(object obj) => ServiceProvider?.GetService<AbstractMailWorker>()?.MailCheck();
}
} }

View File

@ -93,12 +93,12 @@ namespace SushiBarBusinessLogic
{ {
throw new ArgumentNullException("Нет ФИО пользователя", nameof(model.ClientFIO)); throw new ArgumentNullException("Нет ФИО пользователя", nameof(model.ClientFIO));
} }
if (string.IsNullOrEmpty(model.Email) || !Regex.IsMatch(model.Email, @"^[a-z0-9._%+-]+\@([a-z0-9-]+\.)+[a-z]{2,4}$")) if (string.IsNullOrEmpty(model.Email) || !Regex.IsMatch(model.Email, @"^[A-Za-z0-9._%+-]+\@([a-z0-9-]+\.)+[a-z]{2,4}$"))
{ {
throw new ArgumentNullException("Нет указана валидная почта", nameof(model.Email)); throw new ArgumentNullException("Нет указана валидная почта", nameof(model.Email));
} }
if (string.IsNullOrEmpty(model.Password) || !Regex.IsMatch(model.Password, @"^(?=.*[A-Za-z])(?=.*\d)(?=.*[^A-Za-z0-9\n]).{10,50}$")) if (!Regex.IsMatch(model.Email, @"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$"))
{ {
throw new ArgumentNullException("Не указан правильный пароль", nameof(model.Password)); throw new ArgumentNullException("Не указан правильный пароль", nameof(model.Password));
} }
_logger.LogInformation("Client. ClientFIO:{ClientFIO}.Email:{Email}.Id:{Id}", _logger.LogInformation("Client. ClientFIO:{ClientFIO}.Email:{Email}.Id:{Id}",

View File

@ -1,17 +1,10 @@
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using SushiBar.SearchModels;
using SushiBar.StoragesContracts;
using SushiBarContracts.BindingModels; using SushiBarContracts.BindingModels;
using SushiBarContracts.BusinessLogicsContracts; using SushiBarContracts.BusinessLogicsContracts;
using SushiBarContracts.SearchModel;
using SushiBarContracts.SearchModels; using SushiBarContracts.SearchModels;
using SushiBarContracts.StoragesContracts; using SushiBarContracts.StoragesContracts;
using SushiBarContracts.ViewModels; using SushiBarContracts.ViewModels;
using SushiBarDataModels.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SushiBarBusinessLogic namespace SushiBarBusinessLogic
{ {

View File

@ -11,17 +11,18 @@ namespace SushiBarBusinessLogic.BusinessLogics
{ {
public class OrderLogic : IOrderLogic public class OrderLogic : IOrderLogic
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IOrderStorage _orderStorage; private readonly IOrderStorage _orderStorage;
private readonly AbstractMailWorker _mailWorker; private readonly AbstractMailWorker _mailWorker;
static readonly object _locker = new object(); private readonly IClientLogic _clientLogic;
public OrderLogic(ILogger<OrderLogic> logger, IOrderStorage orderStorage,AbstractMailWorker mailWorker) public OrderLogic(ILogger<OrderLogic> logger, IOrderStorage orderStorage, AbstractMailWorker mailWorker, IClientLogic clientLogic)
{ {
_logger = logger; _logger = logger;
_orderStorage = orderStorage; _orderStorage = orderStorage;
_mailWorker = mailWorker; _mailWorker = mailWorker;
} _clientLogic = clientLogic;
public List<OrderViewModel>? ReadList(OrderSearchModel? model) }
public List<OrderViewModel>? ReadList(OrderSearchModel? model)
{ {
_logger.LogInformation("ReadList. ClientId:{ClientId}.Status:{Status}.ImplementerId:{ImplementerId}.DateFrom:{DateFrom}.DateTo:{DateTo}OrderId:{Id}", _logger.LogInformation("ReadList. ClientId:{ClientId}.Status:{Status}.ImplementerId:{ImplementerId}.DateFrom:{DateFrom}.DateTo:{DateTo}OrderId:{Id}",
model?.ClientId, model?.Status, model?.ImplementerId, model?.DateFrom, model?.DateTo, model?.Id); model?.ClientId, model?.Status, model?.ImplementerId, model?.DateFrom, model?.DateTo, model?.Id);
@ -52,25 +53,23 @@ namespace SushiBarBusinessLogic.BusinessLogics
Subject = $"Изменение статуса заказа номер {element.Id}", Subject = $"Изменение статуса заказа номер {element.Id}",
Text = $"Ваш заказ номер {element.Id} на суши {element.SushiName} от {element.DateCreate} на сумму {element.Sum} принят." Text = $"Ваш заказ номер {element.Id} на суши {element.SushiName} от {element.DateCreate} на сумму {element.Sum} принят."
})); }));
return true; SendOrderStatusMail(element.ClientId, $"Новый заказ создан. Номер заказа #{element.Id}", $"Заказ #{element.Id} от {element.DateCreate} на сумму {element.Sum:0.00} принят");
return true;
} }
public bool TakeOrderInWork(OrderBindingModel model) public bool TakeOrderInWork(OrderBindingModel model)
{ {
lock (_locker) return StatusUpdate(model, OrderStatus.Выполняется);
{ }
return ChangeStatus(model, OrderStatus.Выполняется);
}
}
public bool FinishOrder(OrderBindingModel model) public bool FinishOrder(OrderBindingModel model)
{ {
return ChangeStatus(model, OrderStatus.Готов); return StatusUpdate(model, OrderStatus.Готов);
} }
public bool DeliveryOrder(OrderBindingModel model) public bool DeliveryOrder(OrderBindingModel model)
{ {
return ChangeStatus(model, OrderStatus.Выдан); return StatusUpdate(model, OrderStatus.Выдан);
} }
private void CheckModel(OrderBindingModel model, bool withParams = true) private void CheckModel(OrderBindingModel model, bool withParams = true)
@ -99,48 +98,43 @@ namespace SushiBarBusinessLogic.BusinessLogics
model.SushiId, model.Count, model.Sum, model.Id); model.SushiId, model.Count, model.Sum, model.Id);
} }
private bool ChangeStatus(OrderBindingModel model, OrderStatus requiredStatus) private bool StatusUpdate(OrderBindingModel model, OrderStatus newStatus)
{ {
CheckModel(model, false); var viewModel = _orderStorage.GetElement(new OrderSearchModel { Id = model.Id });
var element = _orderStorage.GetElement(new OrderSearchModel() if (viewModel == null)
{ {
Id = model.Id throw new ArgumentNullException(nameof(model));
}); }
if (element == null) if (viewModel.Status + 1 != newStatus)
{ {
throw new InvalidOperationException(nameof(element)); _logger.LogWarning("Change status operation failed");
} throw new InvalidOperationException();
model.DateCreate = element.DateCreate; }
model.SushiId = element.SushiId; model.Status = newStatus;
model.DateImplement = element.DateImplement; if (model.Status == OrderStatus.Готов)
model.ClientId = element.ClientId; {
if (!model.ImplementerId.HasValue) model.DateImplement = DateTime.Now;
{ }
model.ImplementerId = element.ImplementerId; else
} {
model.Status = element.Status; model.DateImplement = viewModel.DateImplement;
model.Count = element.Count; }
model.Sum = element.Sum; if (viewModel.ImplementerId.HasValue)
if (requiredStatus - model.Status == 1) {
{ model.ImplementerId = viewModel.ImplementerId.Value;
model.Status = requiredStatus; }
if (model.Status == OrderStatus.Готов) CheckModel(model, false);
{ var result = _orderStorage.Update(model);
model.DateImplement = DateTime.Now; if (result == null)
} {
if (_orderStorage.Update(model) == null) _logger.LogWarning("Update operation failed");
{ return false;
_logger.LogWarning("Update operation failed"); }
return false; SendOrderStatusMail(result.ClientId, $"Изменен статус заказа #{result.Id}", $"Заказ #{model.Id} изменен статус на {result.Status}");
} return true;
return true; }
}
_logger.LogWarning("Changing status operation faled: Current-{Status}:required-{requiredStatus}.", model.Status, requiredStatus);
throw new InvalidOperationException($"Невозможно приствоить статус {requiredStatus} заказу с текущим статусом {model.Status}");
} public OrderViewModel? ReadElement(OrderSearchModel model)
public OrderViewModel? ReadElement(OrderSearchModel model)
{ {
if (model == null) if (model == null)
{ {
@ -157,5 +151,20 @@ namespace SushiBarBusinessLogic.BusinessLogics
_logger.LogInformation("ReadElement find. Id:{Id}", element.Id); _logger.LogInformation("ReadElement find. Id:{Id}", element.Id);
return element; return element;
} }
} private bool SendOrderStatusMail(int clientId, string subject, string text)
{
var client = _clientLogic.ReadElement(new() { Id = clientId });
if (client == null)
{
return false;
}
_mailWorker.MailSendAsync(new()
{
MailAddress = client.Email,
Subject = subject,
Text = text
});
return true;
}
}
} }

View File

@ -1,34 +1,36 @@
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SushiBar.StoragesContracts;
using SushiBarContracts.BindingModels; using SushiBarContracts.BindingModels;
using SushiBarContracts.BusinessLogicsContracts; using SushiBarContracts.BusinessLogicsContracts;
using SushiBarContracts.SearchModels;
using SushiBarContracts.StoragesContracts;
using SushiBarContracts.ViewModels;
namespace SushiBarBusinessLogic.MailWorker namespace SushiBarBusinessLogic.MailWorker
{ {
public abstract class AbstractMailWorker public abstract class AbstractMailWorker
{ {
protected string _mailLogin = string.Empty; protected string _mailLogin = string.Empty;
protected string _mailPassword = string.Empty; protected string _mailPassword = string.Empty;
protected string _smtpClientHost = string.Empty; protected string _smtpClientHost = string.Empty;
protected int _smtpClientPort; protected int _smtpClientPort;
protected string _popHost = string.Empty; protected string _popHost = string.Empty;
protected int _popPort; protected int _popPort;
private readonly IMessageInfoLogic _messageInfoLogic; private readonly IMessageInfoLogic _messageInfoLogic;
private readonly IClientLogic _clientLogic;
private readonly ILogger _logger; private readonly ILogger _logger;
public AbstractMailWorker(ILogger<AbstractMailWorker> logger, IMessageInfoLogic messageInfoLogic) public AbstractMailWorker(ILogger<AbstractMailWorker> logger, IMessageInfoLogic messageInfoLogic, IClientLogic clientLogic)
{ {
_logger = logger; _logger = logger;
_messageInfoLogic = messageInfoLogic; _messageInfoLogic = messageInfoLogic;
_clientLogic = clientLogic;
} }
public void MailConfig(MailConfigBindingModel config) public void MailConfig(MailConfigBindingModel config)
{ {
_mailLogin = config.MailLogin; _mailLogin = config.MailLogin;
@ -37,8 +39,9 @@ namespace SushiBarBusinessLogic.MailWorker
_smtpClientPort = config.SmtpClientPort; _smtpClientPort = config.SmtpClientPort;
_popHost = config.PopHost; _popHost = config.PopHost;
_popPort = config.PopPort; _popPort = config.PopPort;
_logger.LogDebug("Config: {login}, {password}, {clientHost}, {clientPOrt}, {popHost}, {popPort}", _mailLogin, _mailPassword.Length, _smtpClientHost, _smtpClientPort, _popHost, _popPort); _logger.LogDebug("Config: {login}, {password}, {clientHost}, {clientPOrt}, {popHost}, {popPort}", _mailLogin, _mailPassword, _smtpClientHost, _smtpClientPort, _popHost, _popPort);
} }
public async void MailSendAsync(MailSendInfoBindingModel info) public async void MailSendAsync(MailSendInfoBindingModel info)
{ {
if (string.IsNullOrEmpty(_mailLogin) || string.IsNullOrEmpty(_mailPassword)) if (string.IsNullOrEmpty(_mailLogin) || string.IsNullOrEmpty(_mailPassword))
@ -59,6 +62,7 @@ namespace SushiBarBusinessLogic.MailWorker
_logger.LogDebug("Send Mail: {To}, {Subject}", info.MailAddress, info.Subject); _logger.LogDebug("Send Mail: {To}, {Subject}", info.MailAddress, info.Subject);
await SendMailAsync(info); await SendMailAsync(info);
} }
public async void MailCheck() public async void MailCheck()
{ {
if (string.IsNullOrEmpty(_mailLogin) || string.IsNullOrEmpty(_mailPassword)) if (string.IsNullOrEmpty(_mailLogin) || string.IsNullOrEmpty(_mailPassword))
@ -80,10 +84,14 @@ namespace SushiBarBusinessLogic.MailWorker
_logger.LogDebug("Check Mail: {Count} new mails", list.Count); _logger.LogDebug("Check Mail: {Count} new mails", list.Count);
foreach (var mail in list) foreach (var mail in list)
{ {
mail.ClientId = _clientLogic.ReadElement(new() { Email = mail.SenderName })?.Id;
_messageInfoLogic.Create(mail); _messageInfoLogic.Create(mail);
} }
} }
protected abstract Task SendMailAsync(MailSendInfoBindingModel info); protected abstract Task SendMailAsync(MailSendInfoBindingModel info);
protected abstract Task<List<MessageInfoBindingModel>> ReceiveMailAsync(); protected abstract Task<List<MessageInfoBindingModel>> ReceiveMailAsync();
} }
} }

View File

@ -6,41 +6,41 @@ using SushiBarContracts.BusinessLogicsContracts;
using SushiBarContracts.BindingModels; using SushiBarContracts.BindingModels;
using MailKit.Net.Pop3; using MailKit.Net.Pop3;
using MailKit.Security; using MailKit.Security;
using MailChimp.Net.Logic;
namespace SushiBarBusinessLogic.MailWorker namespace SushiBarBusinessLogic.MailWorker
{ {
public class MailKitWorker : AbstractMailWorker public class MailKitWorker : AbstractMailWorker
{ {
public MailKitWorker(ILogger<MailKitWorker> logger, IMessageInfoLogic messageInfoLogic) : base(logger, messageInfoLogic) { } public MailKitWorker(ILogger<MailKitWorker> logger, IMessageInfoLogic messageInfoLogic, IClientLogic clientLogic) : base(logger, messageInfoLogic, clientLogic) { }
protected override async Task SendMailAsync(MailSendInfoBindingModel info) protected override async Task SendMailAsync(MailSendInfoBindingModel info)
{ {
using var objMailMessage = new MailMessage(); using var objMailMessage = new MailMessage();
using var objSmtpClient = new SmtpClient(_smtpClientHost, _smtpClientPort); using var objSmtpClient = new SmtpClient(_smtpClientHost, _smtpClientPort);
try try
{ {
objMailMessage.From = new MailAddress(_mailLogin); objMailMessage.From = new MailAddress(_mailLogin);
objMailMessage.To.Add(new MailAddress(info.MailAddress)); objMailMessage.To.Add(new MailAddress(info.MailAddress));
objMailMessage.Subject = info.Subject; objMailMessage.Subject = info.Subject;
objMailMessage.Body = info.Text; objMailMessage.Body = info.Text;
objMailMessage.SubjectEncoding = Encoding.UTF8; objMailMessage.SubjectEncoding = Encoding.UTF8;
objMailMessage.BodyEncoding = Encoding.UTF8; objMailMessage.BodyEncoding = Encoding.UTF8;
objSmtpClient.UseDefaultCredentials = false; objSmtpClient.UseDefaultCredentials = false;
objSmtpClient.EnableSsl = true; objSmtpClient.EnableSsl = true;
objSmtpClient.DeliveryMethod = SmtpDeliveryMethod.Network; objSmtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
objSmtpClient.Credentials = new NetworkCredential(_mailLogin, _mailPassword); objSmtpClient.Credentials = new NetworkCredential(_mailLogin, _mailPassword);
await Task.Run(() => objSmtpClient.Send(objMailMessage)); await Task.Run(() => objSmtpClient.Send(objMailMessage));
} }
catch (Exception) catch (Exception)
{ {
throw; throw;
} }
} }
protected override async Task<List<MessageInfoBindingModel>> ReceiveMailAsync() protected override async Task<List<MessageInfoBindingModel>> ReceiveMailAsync()
{ {
var list = new List<MessageInfoBindingModel>(); var list = new List<MessageInfoBindingModel>();
using var client = new Pop3Client(); using var client = new Pop3Client();

View File

@ -8,6 +8,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="DocumentFormat.OpenXml" Version="3.0.2" /> <PackageReference Include="DocumentFormat.OpenXml" Version="3.0.2" />
<PackageReference Include="MailChimp.Net.V3" Version="5.5.0" />
<PackageReference Include="MailKit" Version="4.5.0" /> <PackageReference Include="MailKit" Version="4.5.0" />
<PackageReference Include="MigraDocCore.DocumentObjectModel" Version="1.3.63" /> <PackageReference Include="MigraDocCore.DocumentObjectModel" Version="1.3.63" />
<PackageReference Include="MigraDocCore.Rendering" Version="1.3.63" /> <PackageReference Include="MigraDocCore.Rendering" Version="1.3.63" />

View File

@ -146,7 +146,13 @@ namespace SushiBarClientApp.Controllers
); );
return count * (prod?.Price ?? 1); return count * (prod?.Price ?? 1);
} }
} public IActionResult Mails()
{
} if (APIClient.Client == null)
{
return Redirect("~/Home/Enter");
}
return View(APIClient.GetRequest<List<MessageInfoViewModel>>($"api/client/getmessages?clientId={APIClient.Client.Id}"));
}
}
}

View File

@ -0,0 +1,54 @@
@using SushiBarContracts.ViewModels
@model List<MessageInfoViewModel>
@{
ViewData["Title"] = "Mails";
}
<div class="text-center">
<h1 class="display-4">Письма</h1>
</div>
<div class="text-center">
@{
if (Model == null)
{
<h3 class="display-4">Авторизируйтесь</h3>
return;
}
<table class="table">
<thead>
<tr>
<th>
Дата письма
</th>
<th>
Заголовок
</th>
<th>
Текст
</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.DateDelivery)
</td>
<td>
@Html.DisplayFor(modelItem => item.Subject)
</td>
<td>
@Html.DisplayFor(modelItem => item.Body)
</td>
</tr>
}
</tbody>
</table>
}
</div>

View File

@ -33,6 +33,9 @@
<li class="nav-item"> <li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Register">Регистрация</a> <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Register">Регистрация</a>
</li> </li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Mails">Письма</a>
</li>
</ul> </ul>
</div> </div>
</div> </div>

View File

@ -1,4 +1,5 @@
using SushiBarDataModels.Models; using PrecastConcretePlantDataModels.Models;
using SushiBarDataModels.Models;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;

View File

@ -1,4 +1,5 @@
using SushiBarDataModels.Models; using PrecastConcretePlantDataModels.Models;
using SushiBarDataModels.Models;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PrecastConcretePlantDataModels.Models
{
public interface IMessageInfoModel
{
string MessageId { get; }
int? ClientId { get; }
string SenderName { get; }
DateTime DateDelivery { get; }
string Subject { get; }
string Body { get; }
}
}

View File

@ -0,0 +1,52 @@
using SushiBarContracts.BindingModels;
using SushiBarContracts.SearchModels;
using SushiBarContracts.StoragesContracts;
using SushiBarContracts.ViewModels;
using SushiBarDatabaseImplement.Models;
namespace SushiBarDatabaseImplement.Implements
{
public class MessageInfoStorage : IMessageInfoStorage
{
public MessageInfoViewModel? GetElement(MessageInfoSearchModel model)
{
using var context = new SushiBarDatabase();
if (model.MessageId != null)
{
return context.Messages.FirstOrDefault(x => x.MessageId == model.MessageId)?.GetViewModel;
}
return null;
}
public List<MessageInfoViewModel> GetFilteredList(MessageInfoSearchModel model)
{
using var context = new SushiBarDatabase();
return context.Messages
.Where(x => x.ClientId == model.ClientId)
.Select(x => x.GetViewModel)
.ToList();
}
public List<MessageInfoViewModel> GetFullList()
{
using var context = new SushiBarDatabase();
return context.Messages
.Select(x => x.GetViewModel)
.ToList();
}
public MessageInfoViewModel? Insert(MessageInfoBindingModel model)
{
using var context = new SushiBarDatabase();
var newMessage = MessageInfo.Create(model);
if (newMessage == null || context.Messages.Any(x => x.MessageId.Equals(model.MessageId)))
{
return null;
}
context.Messages.Add(newMessage);
context.SaveChanges();
return newMessage.GetViewModel;
}
}
}

View File

@ -12,8 +12,8 @@ using SushiBarDatabaseImplement;
namespace SushiBarDatabaseImplement.Migrations namespace SushiBarDatabaseImplement.Migrations
{ {
[DbContext(typeof(SushiBarDatabase))] [DbContext(typeof(SushiBarDatabase))]
[Migration("20240512150027_6Lab")] [Migration("20240516141726_tested17")]
partial class _6Lab partial class tested17
{ {
/// <inheritdoc /> /// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder) protected override void BuildTargetModel(ModelBuilder modelBuilder)
@ -97,6 +97,36 @@ namespace SushiBarDatabaseImplement.Migrations
b.ToTable("Ingredients"); b.ToTable("Ingredients");
}); });
modelBuilder.Entity("SushiBarDatabaseImplement.Models.MessageInfo", b =>
{
b.Property<string>("MessageId")
.HasColumnType("nvarchar(450)");
b.Property<string>("Body")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int?>("ClientId")
.HasColumnType("int");
b.Property<DateTime>("DateDelivery")
.HasColumnType("datetime2");
b.Property<string>("SenderName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Subject")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("MessageId");
b.HasIndex("ClientId");
b.ToTable("Messages");
});
modelBuilder.Entity("SushiBarDatabaseImplement.Models.Order", b => modelBuilder.Entity("SushiBarDatabaseImplement.Models.Order", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
@ -186,6 +216,15 @@ namespace SushiBarDatabaseImplement.Migrations
b.ToTable("SushiIngredients"); b.ToTable("SushiIngredients");
}); });
modelBuilder.Entity("SushiBarDatabaseImplement.Models.MessageInfo", b =>
{
b.HasOne("SushiBarDatabaseImplement.Models.Client", "Client")
.WithMany()
.HasForeignKey("ClientId");
b.Navigation("Client");
});
modelBuilder.Entity("SushiBarDatabaseImplement.Models.Order", b => modelBuilder.Entity("SushiBarDatabaseImplement.Models.Order", b =>
{ {
b.HasOne("SushiBarDatabaseImplement.Models.Client", "Client") b.HasOne("SushiBarDatabaseImplement.Models.Client", "Client")

View File

@ -6,7 +6,7 @@ using Microsoft.EntityFrameworkCore.Migrations;
namespace SushiBarDatabaseImplement.Migrations namespace SushiBarDatabaseImplement.Migrations
{ {
/// <inheritdoc /> /// <inheritdoc />
public partial class _6Lab : Migration public partial class tested17 : Migration
{ {
/// <inheritdoc /> /// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder) protected override void Up(MigrationBuilder migrationBuilder)
@ -70,6 +70,27 @@ namespace SushiBarDatabaseImplement.Migrations
table.PrimaryKey("PK_ListSushi", x => x.Id); table.PrimaryKey("PK_ListSushi", x => x.Id);
}); });
migrationBuilder.CreateTable(
name: "Messages",
columns: table => new
{
MessageId = table.Column<string>(type: "nvarchar(450)", nullable: false),
ClientId = table.Column<int>(type: "int", nullable: true),
SenderName = table.Column<string>(type: "nvarchar(max)", nullable: false),
DateDelivery = table.Column<DateTime>(type: "datetime2", nullable: false),
Subject = table.Column<string>(type: "nvarchar(max)", nullable: false),
Body = table.Column<string>(type: "nvarchar(max)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Messages", x => x.MessageId);
table.ForeignKey(
name: "FK_Messages_Clients_ClientId",
column: x => x.ClientId,
principalTable: "Clients",
principalColumn: "Id");
});
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "Orders", name: "Orders",
columns: table => new columns: table => new
@ -134,6 +155,11 @@ namespace SushiBarDatabaseImplement.Migrations
onDelete: ReferentialAction.Cascade); onDelete: ReferentialAction.Cascade);
}); });
migrationBuilder.CreateIndex(
name: "IX_Messages_ClientId",
table: "Messages",
column: "ClientId");
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_Orders_ClientId", name: "IX_Orders_ClientId",
table: "Orders", table: "Orders",
@ -163,6 +189,9 @@ namespace SushiBarDatabaseImplement.Migrations
/// <inheritdoc /> /// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder) protected override void Down(MigrationBuilder migrationBuilder)
{ {
migrationBuilder.DropTable(
name: "Messages");
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "Orders"); name: "Orders");

View File

@ -94,6 +94,36 @@ namespace SushiBarDatabaseImplement.Migrations
b.ToTable("Ingredients"); b.ToTable("Ingredients");
}); });
modelBuilder.Entity("SushiBarDatabaseImplement.Models.MessageInfo", b =>
{
b.Property<string>("MessageId")
.HasColumnType("nvarchar(450)");
b.Property<string>("Body")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int?>("ClientId")
.HasColumnType("int");
b.Property<DateTime>("DateDelivery")
.HasColumnType("datetime2");
b.Property<string>("SenderName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Subject")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("MessageId");
b.HasIndex("ClientId");
b.ToTable("Messages");
});
modelBuilder.Entity("SushiBarDatabaseImplement.Models.Order", b => modelBuilder.Entity("SushiBarDatabaseImplement.Models.Order", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
@ -183,6 +213,15 @@ namespace SushiBarDatabaseImplement.Migrations
b.ToTable("SushiIngredients"); b.ToTable("SushiIngredients");
}); });
modelBuilder.Entity("SushiBarDatabaseImplement.Models.MessageInfo", b =>
{
b.HasOne("SushiBarDatabaseImplement.Models.Client", "Client")
.WithMany()
.HasForeignKey("ClientId");
b.Navigation("Client");
});
modelBuilder.Entity("SushiBarDatabaseImplement.Models.Order", b => modelBuilder.Entity("SushiBarDatabaseImplement.Models.Order", b =>
{ {
b.HasOne("SushiBarDatabaseImplement.Models.Client", "Client") b.HasOne("SushiBarDatabaseImplement.Models.Client", "Client")

View File

@ -0,0 +1,54 @@
using PrecastConcretePlantDataModels.Models;
using SushiBarContracts.BindingModels;
using SushiBarContracts.ViewModels;
using System.ComponentModel.DataAnnotations;
namespace SushiBarDatabaseImplement.Models
{
public class MessageInfo : IMessageInfoModel
{
[Key]
public string MessageId { get; private set; } = string.Empty;
public int? ClientId { get; private set; }
public string SenderName { get; private set; } = string.Empty;
public DateTime DateDelivery { get; private set; } = DateTime.Now;
public string Subject { get; private set; } = string.Empty;
public string Body { get; private set; } = string.Empty;
public Client? Client { get; private set; }
public static MessageInfo? Create(MessageInfoBindingModel model)
{
if (model == null)
{
return null;
}
return new()
{
Body = model.Body,
Subject = model.Subject,
ClientId = model.ClientId,
MessageId = model.MessageId,
SenderName = model.SenderName,
DateDelivery = model.DateDelivery,
};
}
public MessageInfoViewModel GetViewModel => new()
{
Body = Body,
Subject = Subject,
ClientId = ClientId,
MessageId = MessageId,
SenderName = SenderName,
DateDelivery = DateDelivery,
};
}
}

View File

@ -10,7 +10,7 @@ namespace SushiBarDatabaseImplement
{ {
if (optionsBuilder.IsConfigured == false) if (optionsBuilder.IsConfigured == false)
{ {
optionsBuilder.UseSqlServer(@"Data Source=DESKTOP-E2VPEN3\SQLEXPRESS;Initial Catalog=SushiBarDatabase;Integrated Security=True;MultipleActiveResultSets=True;;TrustServerCertificate=True"); optionsBuilder.UseSqlServer(@"Data Source=DESKTOP-E2VPEN3\SQLEXPRESS;Initial Catalog=SushiBarDatabaseTest;Integrated Security=True;MultipleActiveResultSets=True;;TrustServerCertificate=True");
} }
base.OnConfiguring(optionsBuilder); base.OnConfiguring(optionsBuilder);
} }
@ -23,5 +23,6 @@ namespace SushiBarDatabaseImplement
public virtual DbSet<Order> Orders { set; get; } public virtual DbSet<Order> Orders { set; get; }
public virtual DbSet<Client> Clients { set; get; } public virtual DbSet<Client> Clients { set; get; }
public virtual DbSet<Implementer> Implementers { set; get; } public virtual DbSet<Implementer> Implementers { set; get; }
} public virtual DbSet<MessageInfo> Messages { set; get; }
}
} }

View File

@ -2,6 +2,7 @@
using SushiBarContracts.BindingModel; using SushiBarContracts.BindingModel;
using SushiBarContracts.BusinessLogicsContracts; using SushiBarContracts.BusinessLogicsContracts;
using SushiBarContracts.SearchModel; using SushiBarContracts.SearchModel;
using SushiBarContracts.SearchModels;
using SushiBarContracts.ViewModels; using SushiBarContracts.ViewModels;
@ -12,12 +13,13 @@ namespace SushiBarRestApi.Controllers
public class ClientController : Controller public class ClientController : Controller
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IClientLogic _logic; private readonly IClientLogic _logic;
public ClientController(IClientLogic logic, ILogger<ClientController> private readonly IMessageInfoLogic _mailLogic;
logger) public ClientController(IClientLogic logic, IMessageInfoLogic mailLogic, ILogger<ClientController> logger)
{ {
_logger = logger; _logger = logger;
_logic = logic; _logic = logic;
_mailLogic = mailLogic;
} }
[HttpGet] [HttpGet]
public ClientViewModel? Login(string login, string password) public ClientViewModel? Login(string login, string password)
@ -62,7 +64,22 @@ namespace SushiBarRestApi.Controllers
throw; throw;
} }
} }
[HttpGet]
public List<MessageInfoViewModel>? GetMessages(int clientId)
{
try
{
return _mailLogic.ReadList(new MessageInfoSearchModel
{
ClientId = clientId
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка получения писем клиента");
throw;
}
} }
}
}
}

View File

@ -1,6 +1,8 @@
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
using SushiBarBusinessLogic; using SushiBarBusinessLogic;
using SushiBarBusinessLogic.BusinessLogics; using SushiBarBusinessLogic.BusinessLogics;
using SushiBarBusinessLogic.MailWorker;
using SushiBarContracts.BindingModels;
using SushiBarContracts.BusinessLogicsContracts; using SushiBarContracts.BusinessLogicsContracts;
using SushiBarContracts.StoragesContracts; using SushiBarContracts.StoragesContracts;
using SushiBarDatabaseImplement.Implements; using SushiBarDatabaseImplement.Implements;
@ -14,9 +16,13 @@ builder.Services.AddTransient<IOrderStorage, OrderStorage>();
builder.Services.AddTransient<ISushiStorage, SushiStorage>(); builder.Services.AddTransient<ISushiStorage, SushiStorage>();
builder.Services.AddTransient<IOrderLogic, OrderLogic>(); builder.Services.AddTransient<IOrderLogic, OrderLogic>();
builder.Services.AddTransient<IClientLogic, ClientLogic>(); builder.Services.AddTransient<IClientLogic, ClientLogic>();
builder.Services.AddTransient<IMessageInfoLogic, MessageInfoLogic>();
builder.Services.AddTransient<IMessageInfoStorage, MessageInfoStorage>();
builder.Services.AddTransient<ISushiLogic, SushiLogic>(); builder.Services.AddTransient<ISushiLogic, SushiLogic>();
builder.Services.AddTransient<IImplementerStorage, ImplementerStorage>(); builder.Services.AddTransient<IImplementerStorage, ImplementerStorage>();
builder.Services.AddTransient<IImplementerLogic, ImplementerLogic>(); builder.Services.AddTransient<IImplementerLogic, ImplementerLogic>();
builder.Services.AddSingleton<AbstractMailWorker, MailKitWorker>();
builder.Services.AddControllers(); builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
@ -31,6 +37,16 @@ builder.Services.AddSwaggerGen(c =>
}); });
}); });
var app = builder.Build(); var app = builder.Build();
var mailSender = app.Services.GetService<AbstractMailWorker>();
mailSender?.MailConfig(new MailConfigBindingModel
{
MailLogin = builder.Configuration?.GetSection("MailLogin")?.Value?.ToString() ?? string.Empty,
MailPassword = builder.Configuration?.GetSection("MailPassword")?.Value?.ToString() ?? string.Empty,
SmtpClientHost = builder.Configuration?.GetSection("SmtpClientHost")?.Value?.ToString() ?? string.Empty,
SmtpClientPort = Convert.ToInt32(builder.Configuration?.GetSection("SmtpClientPort")?.Value?.ToString()),
PopHost = builder.Configuration?.GetSection("PopHost")?.Value?.ToString() ?? string.Empty,
PopPort = Convert.ToInt32(builder.Configuration?.GetSection("PopPort")?.Value?.ToString())
});
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment()) if (app.Environment.IsDevelopment())
{ {
@ -38,7 +54,7 @@ if (app.Environment.IsDevelopment())
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json",
"AbstractShopRestApi v1")); "AbstractShopRestApi v1"));
} }
app.UseHttpsRedirection();
app.UseAuthorization(); app.UseAuthorization();
app.MapControllers(); app.MapControllers();
app.Run(); app.Run();

View File

@ -5,5 +5,11 @@
"Microsoft.AspNetCore": "Warning" "Microsoft.AspNetCore": "Warning"
} }
}, },
"AllowedHosts": "*" "AllowedHosts": "*",
} "SmtpClientHost": "smtp.gmail.com",
"SmtpClientPort": "587",
"PopHost": "pop.gmail.com",
"PopPort": "995",
"MailLogin": "89176335310x@gmail.com",
"MailPassword": "wmbu qrgy ocwl tadm"
}