From a0e2492757bbe9aec33586990548dd6e8496e21b Mon Sep 17 00:00:00 2001 From: TekH Date: Mon, 28 Sep 2026 12:35:51 +0200 Subject: [PATCH] Add email queuing for envelope invitation process Introduced functionality to queue and send invitation emails to envelope receivers. Added new dependencies and private properties to support email handling, including repositories for `EmailTemplate` and `EmailOut`, as well as configuration services for `MailParams` and `DispatcherParams`. Added the `QueueInvitationEmailsAsync` method to generate personalized email content using placeholders and store outgoing emails in the `EmailOut` repository. Introduced a helper method `ReplacePlaceHolders` for placeholder substitution in email templates. Updated the `Handle` method to invoke `QueueInvitationEmailsAsync` after setting the envelope status to `EnvelopeQueued`. These changes ensure a modular and reusable email queuing process. --- .../Commands/CreateEnvelopeCommandHandler.cs | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/EnvelopeGenerator.Application/Envelopes/Commands/CreateEnvelopeCommandHandler.cs b/EnvelopeGenerator.Application/Envelopes/Commands/CreateEnvelopeCommandHandler.cs index 5dcdc03c..6b2724d8 100644 --- a/EnvelopeGenerator.Application/Envelopes/Commands/CreateEnvelopeCommandHandler.cs +++ b/EnvelopeGenerator.Application/Envelopes/Commands/CreateEnvelopeCommandHandler.cs @@ -1,10 +1,15 @@ using AutoMapper; using MediatR; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using DigitalData.Core.Abstraction.Application.Repository; +using DigitalData.EmailProfilerDispatcher.Abstraction.Entities; using DigitalData.Core.Exceptions; using EnvelopeGenerator.Domain.Entities; using EnvelopeGenerator.Application.Common.Dto; +using EnvelopeGenerator.Application.Common.Configurations; +using EnvelopeGenerator.Application.Common.Extensions; +using EnvelopeGenerator.Application.Common.Interfaces.Services; using EnvelopeGenerator.Application.Common.Interfaces.SQLExecutor; using EnvelopeGenerator.Application.Histories.Commands; using EnvelopeGenerator.Domain.Constants; @@ -32,6 +37,16 @@ public class CreateEnvelopeCommandHandler : IRequestHandler DocReceiverElementRepository => _provider.GetRequiredService>(); + private IRepository EmailTemplateRepository => _provider.GetRequiredService>(); + + private IRepository EmailOutRepository => _provider.GetRequiredService>(); + + private MailParams MailParams => _provider.GetRequiredService>().Value; + + private DispatcherParams DispatcherParams => _provider.GetRequiredService>().Value; + + private IConfigService ConfigService => _provider.GetRequiredService(); + private IMediator Mediator => _provider.GetRequiredService(); private readonly IMapper _mapper; @@ -370,6 +385,70 @@ public class CreateEnvelopeCommandHandler : IRequestHandler links, + string senderReference, + CancellationToken cancel) + { + var template = await EmailTemplateRepository.Query + .SingleOrDefaultAsync(x => x.Name == EmailTemplateType.DocumentReceived.ToString(), cancel) + ?? throw new InvalidOperationException($"Email template not found: {EmailTemplateType.DocumentReceived}"); + + var signatureHost = await ConfigService.ReadDefaultSignatureHost(); + var senderName = senderReference; + + foreach (var link in links) + { + var receiver = link.Receiver; + if (receiver is null || string.IsNullOrWhiteSpace(receiver.EmailAddress) || string.IsNullOrWhiteSpace(receiver.Signature)) + continue; + + var envelopeKey = (envelope.Uuid, receiver.Signature).ToEnvelopeKey(); + var documentLink = $"{signatureHost.TrimEnd('/')}/envelope/login/{Uri.EscapeDataString(envelopeKey)}"; + + var placeholders = new Dictionary(MailParams.Placeholders) + { + ["[NAME_RECEIVER]"] = link.Name ?? string.Empty, + ["[NAME_SENDER]"] = senderName ?? string.Empty, + ["[DOCUMENT_TITLE]"] = envelope.Title ?? string.Empty, + ["[MESSAGE]"] = envelope.Message ?? string.Empty, + ["[LINK_TO_DOCUMENT]"] = documentLink, + ["[LINK_TO_DOCUMENT_TEXT]"] = documentLink[..Math.Min(40, documentLink.Length)] + ".." + }; + + var subject = ReplacePlaceHolders(template.Subject, placeholders); + var body = ReplacePlaceHolders(template.Body, placeholders); + + var emailOut = new EmailOut + { + EmailAddress = receiver.EmailAddress, + EmailSubj = subject, + EmailBody = body, + AddedWhen = DateTime.Now, + AddedWho = DispatcherParams.AddedWho, + SendingProfile = DispatcherParams.SendingProfile, + ReminderTypeId = DispatcherParams.ReminderTypeId, + EmailAttmt1 = DispatcherParams.EmailAttmt1, + WfId = (int)EnvelopeStatus.MessageInvitationSent, + ReferenceString = receiver.EmailAddress, + ReferenceId = link.ReceiverId + }; + + await EmailOutRepository.CreateAsync(emailOut, cancel); + } + } + + private static string ReplacePlaceHolders(string text, Dictionary placeHolders) + { + foreach (var placeHolder in placeHolders) + text = text.Replace(placeHolder.Key, placeHolder.Value); + + return text; + } }