Files
SIFINANCE/SIFinance.Shared/NotificationEmailService.cs
T
2026-09-11 14:55:41 +02:00

51 lines
2.2 KiB
C#

using System.Net.Http.Headers;
using System.Net.Http.Json;
using Microsoft.Extensions.Logging;
namespace SIFinance.Shared;
// Envoie des notifications par email via Microsoft Graph (permission application
// Mail.Send, déjà accordée) — envoie "au nom de" une boîte du tenant (ex. le
// demandeur), pas besoin de boîte de service dédiée. Les échecs sont journalisés mais
// n'interrompent jamais le flux appelant (une notification ratée ne doit pas faire
// échouer la création d'une demande). Vit dans SIFinance.Shared car les modules
// (Achats, Sous-Traitants...) doivent pouvoir l'appeler directement.
public class NotificationEmailService(
IHttpClientFactory httpClientFactory,
EntraGraphTokenProvider tokenProvider,
ILogger<NotificationEmailService> logger)
{
public async Task EnvoyerAsync(string expediteurEmail, string destinataireEmail, string sujet, string corpsHtml, CancellationToken ct)
{
try
{
var token = await tokenProvider.GetTokenAsync(ct);
var http = httpClientFactory.CreateClient();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var payload = new
{
message = new
{
subject = sujet,
body = new { contentType = "HTML", content = corpsHtml },
toRecipients = new[] { new { emailAddress = new { address = destinataireEmail } } },
},
saveToSentItems = false,
};
var response = await http.PostAsJsonAsync(
$"https://graph.microsoft.com/v1.0/users/{Uri.EscapeDataString(expediteurEmail)}/sendMail", payload, ct);
if (!response.IsSuccessStatusCode)
{
var body = await response.Content.ReadAsStringAsync(ct);
logger.LogWarning("Échec d'envoi d'email de notification ({Status}) : {Body}", response.StatusCode, body);
}
}
catch (Exception ex) when (ex is not OperationCanceledException)
{
logger.LogWarning(ex, "Échec d'envoi d'email de notification à {Destinataire}.", destinataireEmail);
}
}
}