diff --git a/Olive.Email/Email.Sending/MailMessageCreator.cs b/Olive.Email/Email.Sending/MailMessageCreator.cs index 9241eb7cf..275fc4e49 100644 --- a/Olive.Email/Email.Sending/MailMessageCreator.cs +++ b/Olive.Email/Email.Sending/MailMessageCreator.cs @@ -1,121 +1,127 @@ -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Configuration; using System.Collections.Generic; using System.Linq; using System.Net.Mail; using System.Net.Mime; using System.Threading.Tasks; -namespace Olive.Email +namespace Olive.Email; + +/// +/// Creates instances based on an . +/// +public interface IMailMessageCreator +{ + Task Create(IEmailMessage message); +} + +/// +/// Default implementation of . +/// +public sealed class MailMessageCreator : IMailMessageCreator { - public interface IMailMessageCreator + private readonly EmailConfiguration _config; + private readonly IEmailAttachmentSerializer _attachmentSerializer; + + public MailMessageCreator(IConfiguration config, IEmailAttachmentSerializer attachmentSerializer) { - Task Create(IEmailMessage message); + ArgumentNullException.ThrowIfNull(config); + _config = config.GetSection("Email").Get() ?? new EmailConfiguration(); + _attachmentSerializer = attachmentSerializer ?? throw new ArgumentNullException(nameof(attachmentSerializer)); } - class MailMessageCreator : IMailMessageCreator + public async Task Create(IEmailMessage message) { - EmailConfiguration Config; + ArgumentNullException.ThrowIfNull(message); - public MailMessageCreator(IConfiguration config, IEmailAttachmentSerializer attachmentSerializer) + var result = new MailMessage { - Config = config.GetSection("Email").Get(); - AttachmentSerializer = attachmentSerializer; - } + Subject = message.Subject.Or("[NO SUBJECT]").Remove("\r", "\n"), + Body = message.Body, + From = CreateFrom(message) + }; - public IEmailAttachmentSerializer AttachmentSerializer { get; } + result.Headers.Add(Constants.EMAIL_MESSAGE_ID_HEADER_KEY, message.GetId().ToString()); - public async Task Create(IEmailMessage message) - { - var result = new MailMessage - { - Subject = message.Subject.Or("[NO SUBJECT]").Remove("\r", "\n"), - Body = message.Body, - From = CreateFrom(message) - }; + foreach (var recipient in GetEffectiveRecipients(message.To)) + result.To.Add(recipient); - result.Headers - .Add(Constants.EMAIL_MESSAGE_ID_HEADER_KEY, message.GetId().ToString()); + foreach (var recipient in GetEffectiveRecipients(message.Cc + _config.AutoAddCc.WithPrefix(","))) + result.CC.Add(recipient); - GetEffectiveRecipients(message.To).Do(x => result.To.Add(x)); - GetEffectiveRecipients(message.Cc + Config.AutoAddCc.WithPrefix(",")).Do(x => result.CC.Add(x)); - GetEffectiveRecipients(message.Bcc + Config.AutoAddBcc.WithPrefix(",")).Do(x => result.Bcc.Add(x)); + foreach (var recipient in GetEffectiveRecipients(message.Bcc + _config.AutoAddBcc.WithPrefix(","))) + result.Bcc.Add(recipient); - result.ReplyToList.Add(CreateReplyTo(message)); + result.ReplyToList.Add(CreateReplyTo(message)); - result.AlternateViews.AddRange(GetBodyViews(message)); - result.Attachments.AddRange(await AttachmentSerializer.Extract(message)); + result.AlternateViews.AddRange(GetBodyViews(message)); + result.Attachments.AddRange(await _attachmentSerializer.Extract(message)); - return result; - } + return result; + } - MailAddress CreateFrom(IEmailMessage message) - { - var address = message.FromAddress.Or(Config.From?.Address); - var name = message.FromName.Or(Config.From?.Name); - return new MailAddress(address, name); - } + private MailAddress CreateFrom(IEmailMessage message) => + new(message.FromAddress.Or(_config.From?.Address), + message.FromName.Or(_config.From?.Name)); - MailAddress CreateReplyTo(IEmailMessage message) - { - var address = message.ReplyToAddress - .Or(Config.ReplyTo?.Address) - .Or(message.FromAddress) - .Or(Config.From?.Address); + private MailAddress CreateReplyTo(IEmailMessage message) + { + var address = message.ReplyToAddress + .Or(_config.ReplyTo?.Address) + .Or(message.FromAddress) + .Or(_config.From?.Address); - var name = message.ReplyToName - .Or(Config.ReplyTo?.Name) - .Or(message.FromName) - .Or(Config.From?.Name); + var name = message.ReplyToName + .Or(_config.ReplyTo?.Name) + .Or(message.FromName) + .Or(_config.From?.Name); - return new MailAddress(address, name); - } + return new MailAddress(address, name); + } - string[] GetEffectiveRecipients(string to) - { - return to.OrEmpty().Split(',').Trim().Where(x => CanSendTo(x)).ToArray(); - } + private IEnumerable GetEffectiveRecipients(string? to) => + to.OrEmpty().Split(',').Trim().Where(CanSendTo); - bool CanSendTo(string recipientAddress) - { - var permittedDomains = Config.Permitted.Domains.ToLowerOrEmpty().Or("geeks.ltd.uk|uat.co"); - if (permittedDomains == "*") return true; + private bool CanSendTo(string recipientAddress) + { + var permittedDomains = _config.Permitted.Domains.ToLowerOrEmpty().Or("geeks.ltd.uk|uat.co"); + if (permittedDomains == "*") return true; - if (permittedDomains.Split('|').Trim().Any(d => recipientAddress.TrimEnd(">").EndsWith("@" + d))) - return true; + if (permittedDomains.Split('|').Trim().Any(d => recipientAddress.TrimEnd(">").EndsWith("@" + d))) + return true; - var addresses = Config.Permitted.Addresses.ToLowerOrEmpty().Split('|').Trim().ToArray(); + var addresses = _config.Permitted.Addresses.ToLowerOrEmpty().Split('|').Trim().ToArray(); - return addresses.Any() && new MailAddress(recipientAddress).Address.IsAnyOf(addresses); - } + return addresses.Any() && new MailAddress(recipientAddress).Address.IsAnyOf(addresses); + } - IEnumerable GetBodyViews(IEmailMessage message) - { - yield return AlternateView.CreateAlternateViewFromString( - message.Body.RemoveHtmlTags(), + private IEnumerable GetBodyViews(IEmailMessage message) + { + yield return AlternateView.CreateAlternateViewFromString( + message.Body.RemoveHtmlTags(), new ContentType("text/plain; charset=UTF-8")); - if (message.Html) - { - var htmlView = AlternateView.CreateAlternateViewFromString( - message.Body, new ContentType("text/html; charset=UTF-8")); - - htmlView.LinkedResources.AddRange(AttachmentSerializer.GetLinkedResources(message)); - yield return htmlView; - } + if (message.Html) + { + var htmlView = AlternateView.CreateAlternateViewFromString( + message.Body, + new ContentType("text/html; charset=UTF-8")); - if (message.VCalendarView.HasValue()) - { - var calendarType = new ContentType("text/calendar"); - calendarType.Parameters.Add("method", "REQUEST"); - calendarType.Parameters.Add("name", "meeting.ics"); + htmlView.LinkedResources.AddRange(_attachmentSerializer.GetLinkedResources(message)); + yield return htmlView; + } - var calendarView = AlternateView - .CreateAlternateViewFromString(message.VCalendarView, calendarType); + if (message.VCalendarView.HasValue()) + { + var calendarType = new ContentType("text/calendar"); + calendarType.Parameters.Add("method", "REQUEST"); + calendarType.Parameters.Add("name", "meeting.ics"); - calendarView.TransferEncoding = TransferEncoding.SevenBit; + var calendarView = AlternateView.CreateAlternateViewFromString(message.VCalendarView, calendarType); + calendarView.TransferEncoding = TransferEncoding.SevenBit; - yield return calendarView; - } + yield return calendarView; } } -} \ No newline at end of file +} +