MailProcessor
This commit is contained in:
17
StandManager.MailProcessor/Mail/Email.cs
Normal file
17
StandManager.MailProcessor/Mail/Email.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
namespace StandManager.MailProcessor.Mail;
|
||||||
|
|
||||||
|
public class Email
|
||||||
|
{
|
||||||
|
public string From { get; set; }
|
||||||
|
public List<string> To { get; set; }
|
||||||
|
public List<string>? Cc { get; set; }
|
||||||
|
public string Subject { get; set; }
|
||||||
|
public string Body { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EmailConfig
|
||||||
|
{
|
||||||
|
public string From { get; set; }
|
||||||
|
public string ServerAddress { get; set; }
|
||||||
|
public string MailSplitChar { get; set; }
|
||||||
|
}
|
||||||
@ -1,18 +1,77 @@
|
|||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Net.Http.Json;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using StandManager.MailProcessor.Mail;
|
||||||
using StandManager.Service.Interfaces;
|
using StandManager.Service.Interfaces;
|
||||||
|
|
||||||
public class MailProcessor
|
public class MailProcessor
|
||||||
{
|
{
|
||||||
private readonly IManagerService _managerService;
|
private readonly IManagerService _managerService;
|
||||||
|
private readonly EmailConfig _config;
|
||||||
|
|
||||||
public MailProcessor(IManagerService managerService)
|
public MailProcessor(IManagerService managerService, EmailConfig config)
|
||||||
{
|
{
|
||||||
_managerService = managerService;
|
_managerService = managerService;
|
||||||
|
_config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Process()
|
public async Task Process()
|
||||||
{
|
{
|
||||||
var list = await _managerService.MailQueueService.RicercaQueryable(x =>
|
var list = await _managerService.MailQueueService.RicercaQueryable(x =>
|
||||||
x.Eliminato == false && x.Sent == false);
|
x.Eliminato == false && x.Sent == false && string.IsNullOrEmpty(x.Error), solaLettura:false);
|
||||||
|
|
||||||
|
using var httpClient = new HttpClient();
|
||||||
|
foreach (var mailQueue in list)
|
||||||
|
{
|
||||||
|
var email = new Email()
|
||||||
|
{
|
||||||
|
From = _config.From,
|
||||||
|
Body = string.IsNullOrEmpty(mailQueue.Args) ? mailQueue.Body : string.Format(mailQueue.Body, mailQueue.Args?.Split(_config.MailSplitChar) ?? [""]),
|
||||||
|
Cc = null,
|
||||||
|
Subject = mailQueue.Subject,
|
||||||
|
To = new(){"g.vitari@oaservice.it"} // mailQueue.ToList.Split(";").ToList()
|
||||||
|
};
|
||||||
|
var messageJson = JsonSerializer.Serialize(email);
|
||||||
|
|
||||||
|
// multipart
|
||||||
|
using var form = new MultipartFormDataContent();
|
||||||
|
form.Add(
|
||||||
|
new StringContent(messageJson, Encoding.UTF8, "application/json"),
|
||||||
|
"messageJson"
|
||||||
|
);
|
||||||
|
|
||||||
|
//Attachments
|
||||||
|
/*var filePath = @"C:\temp\test.pdf";
|
||||||
|
var fileBytes = await File.ReadAllBytesAsync(filePath);
|
||||||
|
|
||||||
|
var fileContent = new ByteArrayContent(fileBytes);
|
||||||
|
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/pdf");
|
||||||
|
|
||||||
|
form.Add(
|
||||||
|
fileContent,
|
||||||
|
"attachments",
|
||||||
|
Path.GetFileName(filePath)
|
||||||
|
);*/
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var response = await httpClient.PostAsync(
|
||||||
|
_config.ServerAddress,
|
||||||
|
form
|
||||||
|
);
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
mailQueue.Sent = true;
|
||||||
|
await _managerService.MailQueueService.Salva(mailQueue);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
mailQueue.Sent = false;
|
||||||
|
mailQueue.Error = e.Message;
|
||||||
|
await _managerService.MailQueueService.Salva(mailQueue);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
var a = list;
|
var a = list;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4,6 +4,7 @@ using Microsoft.Extensions.Configuration;
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using StandManager.Infrastructure.DAL.Context;
|
using StandManager.Infrastructure.DAL.Context;
|
||||||
|
using StandManager.MailProcessor.Mail;
|
||||||
using StandManager.Service;
|
using StandManager.Service;
|
||||||
using StandManager.Service.Interfaces;
|
using StandManager.Service.Interfaces;
|
||||||
using StandManager.Service.Repository;
|
using StandManager.Service.Repository;
|
||||||
@ -19,6 +20,10 @@ var host = Host.CreateDefaultBuilder(args)
|
|||||||
var impl = allProviderTypes.FirstOrDefault(c => c.IsClass && intfc.Name[1..] == c.Name);
|
var impl = allProviderTypes.FirstOrDefault(c => c.IsClass && intfc.Name[1..] == c.Name);
|
||||||
if (impl != null) services.AddScoped(intfc, impl);
|
if (impl != null) services.AddScoped(intfc, impl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var emailConfigSection = context.Configuration.GetSection("EmailConfig");
|
||||||
|
services.Configure<EmailConfig>(emailConfigSection);
|
||||||
|
|
||||||
//Database
|
//Database
|
||||||
var connectionString = context.Configuration.GetConnectionString("ConnectionString");
|
var connectionString = context.Configuration.GetConnectionString("ConnectionString");
|
||||||
services.AddDbContext<StandManagerDbContext>(options =>
|
services.AddDbContext<StandManagerDbContext>(options =>
|
||||||
|
|||||||
@ -8,5 +8,10 @@
|
|||||||
"Microsoft.AspNetCore": "Warning"
|
"Microsoft.AspNetCore": "Warning"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"AllowedHosts": "*"
|
"AllowedHosts": "*",
|
||||||
|
"EmailConfig": {
|
||||||
|
"From": "",
|
||||||
|
"ServerAddress": "",
|
||||||
|
"MailSplitChar": "#"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,4 +5,5 @@ namespace StandManager.Service.Interfaces;
|
|||||||
|
|
||||||
public interface IMailQueueService : ITService<MailQueue>
|
public interface IMailQueueService : ITService<MailQueue>
|
||||||
{
|
{
|
||||||
|
Task<MailQueue> Salva(MailQueue entity);
|
||||||
}
|
}
|
||||||
@ -13,4 +13,12 @@ public class MailQueueService : TService<MailQueue>, IMailQueueService
|
|||||||
{
|
{
|
||||||
_unitOfWork = unitOfWork;
|
_unitOfWork = unitOfWork;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<MailQueue> Salva(MailQueue entity)
|
||||||
|
{
|
||||||
|
_unitOfWork.MailQueueRepository.Update(entity);
|
||||||
|
await _unitOfWork.Salva();
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -6,4 +6,5 @@ namespace StandManager.Service.Repository;
|
|||||||
public interface IStandManagerUnitOfWork : IUnitOfWork
|
public interface IStandManagerUnitOfWork : IUnitOfWork
|
||||||
{
|
{
|
||||||
public IStandManagerGenericRepository<Utente> UtenteRepository { get; }
|
public IStandManagerGenericRepository<Utente> UtenteRepository { get; }
|
||||||
|
public IStandManagerGenericRepository<MailQueue> MailQueueRepository { get; }
|
||||||
}
|
}
|
||||||
@ -24,4 +24,7 @@ public class StandManagerUnitOfWork : UnitOfWork, IStandManagerUnitOfWork
|
|||||||
|
|
||||||
private IStandManagerGenericRepository<Utente> _utenteRepository;
|
private IStandManagerGenericRepository<Utente> _utenteRepository;
|
||||||
public new IStandManagerGenericRepository<Utente> UtenteRepository => _utenteRepository ??= new StandManagerGenericRepository<Utente>(_context);
|
public new IStandManagerGenericRepository<Utente> UtenteRepository => _utenteRepository ??= new StandManagerGenericRepository<Utente>(_context);
|
||||||
|
|
||||||
|
private IStandManagerGenericRepository<MailQueue> _mailQueueRepository;
|
||||||
|
public new IStandManagerGenericRepository<MailQueue> MailQueueRepository => _mailQueueRepository ??= new StandManagerGenericRepository<MailQueue>(_context);
|
||||||
}
|
}
|
||||||
@ -1,9 +1,7 @@
|
|||||||
@attribute [Authorize]
|
@attribute [Authorize]
|
||||||
@page "/management/Clienti"
|
@page "/management/Clienti"
|
||||||
@using ClosedXML.Excel
|
|
||||||
@using Microsoft.EntityFrameworkCore
|
@using Microsoft.EntityFrameworkCore
|
||||||
@using StandManager.Model
|
@using StandManager.Model
|
||||||
@using System.Threading.Tasks
|
|
||||||
|
|
||||||
@rendermode InteractiveServer
|
@rendermode InteractiveServer
|
||||||
|
|
||||||
|
|||||||
108
StandManager/Components/Pages/Management/Profile.razor
Normal file
108
StandManager/Components/Pages/Management/Profile.razor
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
@page "/management/profile"
|
||||||
|
@using Microsoft.AspNetCore.Identity
|
||||||
|
@using StandManager.Model
|
||||||
|
|
||||||
|
@attribute [Authorize]
|
||||||
|
@rendermode InteractiveServer
|
||||||
|
|
||||||
|
<div class="page-wrapper">
|
||||||
|
<!-- BEGIN PAGE BODY -->
|
||||||
|
<div class="page-body">
|
||||||
|
<div class="container-xl">
|
||||||
|
<div class="row row-cards">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="row">
|
||||||
|
<!-- Page pre-title -->
|
||||||
|
<div class="page-pretitle"> </div>
|
||||||
|
<h2 class="page-title">Profilo</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<EditForm Model="profilo" OnValidSubmit="onProfiloSave" FormName="profiloForm">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-4 mb-3">
|
||||||
|
<RadzenText TextStyle="TextStyle.Subtitle2" TagName="TagName.H3">Nome</RadzenText>
|
||||||
|
<RadzenTextBox Style="width: 100%" aria-label="Nome" @bind-Value="@profilo.Nome" />
|
||||||
|
</div>
|
||||||
|
<div class="col-4 mb-3">
|
||||||
|
<RadzenText TextStyle="TextStyle.Subtitle2" TagName="TagName.H3">Cognome</RadzenText>
|
||||||
|
<RadzenTextBox Style="width: 100%" aria-label="Cognome" @bind-Value="@profilo.Cognome" />
|
||||||
|
</div>
|
||||||
|
<div class="col-4 mb-3">
|
||||||
|
<RadzenText TextStyle="TextStyle.Subtitle2" TagName="TagName.H3">Email</RadzenText>
|
||||||
|
<RadzenTextBox Style="width: 100%" aria-label="Email" @bind-Value="@profilo.Email" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-4 mb-3">
|
||||||
|
<RadzenText TextStyle="TextStyle.Subtitle2" TagName="TagName.H3">Password</RadzenText>
|
||||||
|
<RadzenTextBox Style="width: 100%" aria-label="Password" @bind-Value="@profilo.Password" Placeholder="Compila questo campo solo se desideri modificare la password." />
|
||||||
|
</div>
|
||||||
|
<div class="col-4 mb-3">
|
||||||
|
<RadzenText TextStyle="TextStyle.Subtitle2" TagName="TagName.H3">Conferma Password</RadzenText>
|
||||||
|
<RadzenTextBox Style="width: 100%" aria-label="Nome" @bind-Value="@profilo.ConfirmPassword" Placeholder="Compila questo campo solo se desideri modificare la password." />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-4 mb-3">
|
||||||
|
<button type="button" class="btn btn-default w-100" @onclick="backToHome">
|
||||||
|
Annulla
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-4 mb-3">
|
||||||
|
<button type="submit" class="btn btn-primary w-100">
|
||||||
|
Salva
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</EditForm>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@code{
|
||||||
|
[SupplyParameterFromForm]
|
||||||
|
private ProfiloViewModel profilo { get; set; } = new();
|
||||||
|
private Guid userId = new();
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
await base.OnInitializedAsync();
|
||||||
|
userId = await MembershipUtils.GetUserId(_auth);
|
||||||
|
|
||||||
|
profilo = await _managerService.UtenteService
|
||||||
|
.RicercaPer(x => x.Id == userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task onProfiloSave()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
profilo.Validate();
|
||||||
|
var user = await _managerService.UtenteService.RicercaPer(x => x.Id == userId, solaLettura: false);
|
||||||
|
user = profilo.Map(user);
|
||||||
|
if (!string.IsNullOrEmpty(profilo.Password))
|
||||||
|
{
|
||||||
|
var hasher = new PasswordHasher<Utente>();
|
||||||
|
user.Password = hasher.HashPassword(user, profilo.Password);
|
||||||
|
}
|
||||||
|
await _managerService.UtenteService.Salva(user, userId);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await _dialogService.Alert(ex.Message, "Errore");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Torna alla pagina di elenco clienti senza salvare altre modifiche.
|
||||||
|
/// </summary>
|
||||||
|
private void backToHome()
|
||||||
|
{
|
||||||
|
_navManager.NavigateTo("/management");
|
||||||
|
}
|
||||||
|
}
|
||||||
47
StandManager/Model/ProfiloViewModel.cs
Normal file
47
StandManager/Model/ProfiloViewModel.cs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using OAService.Domain.Entita;
|
||||||
|
using StandManager.Domain.Entita;
|
||||||
|
|
||||||
|
namespace StandManager.Model;
|
||||||
|
|
||||||
|
public class ProfiloViewModel
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string Username { get; set; }
|
||||||
|
public string Email { get; set; }
|
||||||
|
public string Password { get; set; }
|
||||||
|
public string ConfirmPassword { get; set; }
|
||||||
|
public string Nome { get; set; }
|
||||||
|
public string Cognome { get; set; }
|
||||||
|
|
||||||
|
public static implicit operator ProfiloViewModel(Utente model)
|
||||||
|
{
|
||||||
|
return model == null
|
||||||
|
? null
|
||||||
|
: new ProfiloViewModel()
|
||||||
|
{
|
||||||
|
Cognome = model.Cognome,
|
||||||
|
Nome = model.Nome,
|
||||||
|
Email = model.Email,
|
||||||
|
Username = model.Username,
|
||||||
|
Id = model.Id
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public Utente Map(Utente user)
|
||||||
|
{
|
||||||
|
user.Nome = Nome;
|
||||||
|
user.Cognome = Cognome;
|
||||||
|
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Validate()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(Nome)) throw new ValidationException("Il nome inserito non è valido");
|
||||||
|
if (string.IsNullOrEmpty(Cognome)) throw new ValidationException("Il cognome inserito non è valido");
|
||||||
|
if (!string.IsNullOrEmpty(Password) && string.IsNullOrEmpty(ConfirmPassword)) throw new Exception("E' necessario inserire la password di conferma");
|
||||||
|
if (!string.IsNullOrEmpty(Password) && !string.IsNullOrEmpty(ConfirmPassword) && Password != ConfirmPassword)
|
||||||
|
throw new ValidationException("Le due password non corrispondono");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,9 +1,8 @@
|
|||||||
using StandManager.Domain.Entita;
|
using StandManager.Domain.Entita;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
|
|
||||||
namespace StandManager.Model
|
namespace StandManager.Model;
|
||||||
{
|
|
||||||
public class UtenteViewModel
|
public class UtenteViewModel
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
@ -46,4 +45,3 @@ namespace StandManager.Model
|
|||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user