diff --git a/src/Proffer.Email.InMemory/InMemoryEmailProvider.cs b/src/Proffer.Email.InMemory/InMemoryEmailProvider.cs index 4559531..f80b465 100644 --- a/src/Proffer.Email.InMemory/InMemoryEmailProvider.cs +++ b/src/Proffer.Email.InMemory/InMemoryEmailProvider.cs @@ -24,60 +24,23 @@ public InMemoryEmailProvider(IInMemoryEmailRepository inMemoryEmailRepository) /// /// Sends an email. /// - /// The sender email address. - /// The email recipients. - /// The subject. - /// The body as plain text. - /// The body as HTML. + /// All informations about the email. /// /// A task that represents the asynchronous operation. /// - public Task SendEmailAsync(IEmailAddress from, IEnumerable recipients, string subject, string bodyText, string bodyHtml) - => this.SendEmailAsync(from, recipients, subject, bodyText, bodyHtml, Enumerable.Empty()); - - /// - /// Sends an email. - /// - /// The sender email address. - /// The email recipients. - /// The subject. - /// The body as plain text. - /// The body as HTML. - /// The file attachments. - /// - /// A task that represents the asynchronous operation. - /// - public Task SendEmailAsync(IEmailAddress from, IEnumerable recipients, string subject, string bodyText, string bodyHtml, IEnumerable attachments) - => this.SendEmailAsync(from, recipients, Enumerable.Empty(), Enumerable.Empty(), subject, bodyText, bodyHtml, Enumerable.Empty()); - - /// - /// Sends an email. - /// - /// The sender email address. - /// The email recipients. - /// The CC email recipients. - /// The BCC email recipients. - /// The subject. - /// The body as plain text. - /// The body as HTML. - /// The file attachments. - /// The reply-to email address. - /// - /// A task that represents the asynchronous operation. - /// - public Task SendEmailAsync(IEmailAddress from, IEnumerable recipients, IEnumerable ccRecipients, IEnumerable bccRecipients, string subject, string bodyText, string bodyHtml, IEnumerable attachments, IEmailAddress replyTo = null) + public Task SendEmailAsync(IEmail email) { this.inMemoryEmailRepository.Save(new InMemoryEmail { - Subject = subject, - MessageText = bodyText, - MessageHtml = bodyHtml, - To = recipients.ToArray(), - Cc = ccRecipients.ToArray(), - Bcc = bccRecipients.ToArray(), - From = from, - ReplyTo = replyTo, - Attachments = attachments + Subject = email.Subject, + MessageText = email.BodyText, + MessageHtml = email.BodyHtml, + To = email.Recipients.ToArray(), + Cc = email.CcRecipients.ToArray(), + Bcc = email.BccRecipients.ToArray(), + From = email.From, + ReplyTo = email.ReplyTo, + Attachments = email.Attachments }); return Task.FromResult(0); diff --git a/src/Proffer.Email.SendGrid/SendGridEmailProvider.cs b/src/Proffer.Email.SendGrid/SendGridEmailProvider.cs index ee68abe..d5646bc 100644 --- a/src/Proffer.Email.SendGrid/SendGridEmailProvider.cs +++ b/src/Proffer.Email.SendGrid/SendGridEmailProvider.cs @@ -33,51 +33,14 @@ public SendGridEmailProvider(IEmailProviderOptions options) /// /// Sends an email. /// - /// The sender email address. - /// The email recipients. - /// The subject. - /// The body as plain text. - /// The body as HTML. - /// - /// A task that represents the asynchronous operation. - /// - public Task SendEmailAsync(IEmailAddress from, IEnumerable recipients, string subject, string bodyText, string bodyHtml) - => this.SendEmailAsync(from, recipients, subject, bodyText, bodyHtml, Enumerable.Empty()); - - /// - /// Sends an email. - /// - /// The sender email address. - /// The email recipients. - /// The subject. - /// The body as plain text. - /// The body as HTML. - /// The file attachments. - /// - /// A task that represents the asynchronous operation. - /// - public Task SendEmailAsync(IEmailAddress from, IEnumerable recipients, string subject, string bodyText, string bodyHtml, IEnumerable attachments) - => this.SendEmailAsync(from, recipients, Enumerable.Empty(), Enumerable.Empty(), subject, bodyText, bodyHtml, Enumerable.Empty()); - - /// - /// Sends an email. - /// - /// The sender email address. - /// The email recipients. - /// The CC email recipients. - /// The BCC email recipients. - /// The subject. - /// The body as plain text. - /// The body as HTML. - /// The file attachments. - /// The reply-to email address. + /// All informations about the email. /// Each email address should be unique between to, cc, and bcc recipients. We found duplicates. /// Cannot Send Email: {response.StatusCode} - public async Task SendEmailAsync(IEmailAddress from, IEnumerable recipients, IEnumerable ccRecipients, IEnumerable bccRecipients, string subject, string bodyText, string bodyHtml, IEnumerable attachments, IEmailAddress replyTo = null) + public async Task SendEmailAsync(IEmail email) { - var allRecipients = new List(recipients); - allRecipients.AddRange(ccRecipients); - allRecipients.AddRange(bccRecipients); + var allRecipients = new List(email.Recipients); + allRecipients.AddRange(email.CcRecipients); + allRecipients.AddRange(email.BccRecipients); if (allRecipients.GroupBy(r => r.Email).Count() < allRecipients.Count) { @@ -88,33 +51,33 @@ public async Task SendEmailAsync(IEmailAddress from, IEnumerable SendGridMessage message; - if (recipients.Count() == 1) + if (email.Recipients.Count() == 1) { - message = MailHelper.CreateSingleEmail(from.ToSendGridEmail(), recipients.First().ToSendGridEmail(), subject, bodyText, bodyHtml); + message = MailHelper.CreateSingleEmail(email.From.ToSendGridEmail(), email.Recipients.First().ToSendGridEmail(), email.Subject, email.BodyText, email.BodyHtml); } else { message = MailHelper.CreateSingleEmailToMultipleRecipients( - from.ToSendGridEmail(), - recipients.Select(email => email.ToSendGridEmail()).ToList(), - subject, - bodyText, - bodyHtml); + email.From.ToSendGridEmail(), + email.Recipients.Select(email => email.ToSendGridEmail()).ToList(), + email.Subject, + email.BodyText, + email.BodyHtml); } - foreach (IEmailAddress ccRecipient in ccRecipients) + foreach (IEmailAddress ccRecipient in email.CcRecipients) { message.AddCc(ccRecipient.Email, ccRecipient.DisplayName); } - foreach (IEmailAddress bccRecipient in bccRecipients) + foreach (IEmailAddress bccRecipient in email.BccRecipients) { message.AddBcc(bccRecipient.Email, bccRecipient.DisplayName); } - if (attachments.Any()) + if (email.Attachments.Any()) { - message.AddAttachments(attachments.Select(a => new Attachment + message.AddAttachments(email.Attachments.Select(a => new Attachment { Filename = a.FileName, Type = a.ContentType, @@ -122,9 +85,9 @@ public async Task SendEmailAsync(IEmailAddress from, IEnumerable }).ToList()); } - if (replyTo != null) + if (email.ReplyTo != null) { - message.ReplyTo = replyTo.ToSendGridEmail(); + message.ReplyTo = email.ReplyTo.ToSendGridEmail(); } Response response = await client.SendEmailAsync(message); diff --git a/src/Proffer.Email.Smtp/SmtpEmailProvider.cs b/src/Proffer.Email.Smtp/SmtpEmailProvider.cs index 1afb19a..d00e49d 100644 --- a/src/Proffer.Email.Smtp/SmtpEmailProvider.cs +++ b/src/Proffer.Email.Smtp/SmtpEmailProvider.cs @@ -51,35 +51,6 @@ public SmtpEmailProvider(IServiceProvider serviceProvider, IEmailProviderOptions options.Parameters.TryGetValue("Password", out this.password); } - /// - /// Sends an email. - /// - /// The sender email address. - /// The email recipients. - /// The subject. - /// The body as plain text. - /// The body as HTML. - /// - /// A task that represents the asynchronous operation. - /// - public Task SendEmailAsync(IEmailAddress from, IEnumerable recipients, string subject, string bodyText, string bodyHtml) - => this.SendEmailAsync(from, recipients, subject, bodyText, bodyHtml, Enumerable.Empty()); - - /// - /// Sends an email. - /// - /// The sender email address. - /// The email recipients. - /// The subject. - /// The body as plain text. - /// The body as HTML. - /// The file attachments. - /// - /// A task that represents the asynchronous operation. - /// - public Task SendEmailAsync(IEmailAddress from, IEnumerable recipients, string subject, string bodyText, string bodyHtml, IEnumerable attachments) - => this.SendEmailAsync(from, recipients, Enumerable.Empty(), Enumerable.Empty(), subject, bodyText, bodyHtml, Enumerable.Empty()); - /// /// Sends an email. /// @@ -92,40 +63,40 @@ public Task SendEmailAsync(IEmailAddress from, IEnumerable recipi /// The body as HTML. /// The file attachments. /// The reply-to email address. - public async Task SendEmailAsync(IEmailAddress from, IEnumerable recipients, IEnumerable ccRecipients, IEnumerable bccRecipients, string subject, string bodyText, string bodyHtml, IEnumerable attachments, IEmailAddress replyTo = null) + public async Task SendEmailAsync(IEmail email) { var message = new MimeMessage(); - message.From.Add(new MailboxAddress(from.DisplayName, from.Email)); + message.From.Add(new MailboxAddress(email.From.DisplayName, email.From.Email)); - if (replyTo != null) + if (email.ReplyTo != null) { - message.ReplyTo.Add(new MailboxAddress(replyTo.DisplayName, replyTo.Email)); + message.ReplyTo.Add(new MailboxAddress(email.ReplyTo.DisplayName, email.ReplyTo.Email)); } - foreach (IEmailAddress recipient in recipients) + foreach (IEmailAddress recipient in email.Recipients) { message.To.Add(new MailboxAddress(recipient.DisplayName, recipient.Email)); } - foreach (IEmailAddress recipient in ccRecipients) + foreach (IEmailAddress recipient in email.CcRecipients) { message.Cc.Add(new MailboxAddress(recipient.DisplayName, recipient.Email)); } - foreach (IEmailAddress recipient in bccRecipients) + foreach (IEmailAddress recipient in email.BccRecipients) { message.Bcc.Add(new MailboxAddress(recipient.DisplayName, recipient.Email)); } - message.Subject = subject; + message.Subject = email.Subject; var builder = new BodyBuilder { - TextBody = bodyText, - HtmlBody = bodyHtml + TextBody = email.BodyText, + HtmlBody = email.BodyHtml }; - foreach (IEmailAttachment attachment in attachments) + foreach (IEmailAttachment attachment in email.Attachments) { builder.Attachments.Add(attachment.FileName, attachment.Data, new ContentType(attachment.MediaType, attachment.MediaSubtype)); } diff --git a/src/Proffer.Email/Email.cs b/src/Proffer.Email/Email.cs new file mode 100644 index 0000000..e6983b9 --- /dev/null +++ b/src/Proffer.Email/Email.cs @@ -0,0 +1,51 @@ +using System.Collections.Generic; + +namespace Proffer.Email +{ + /// + /// Contains the features that an email should have. + /// + public class Email : IEmail + { + /// + /// The sender email address. + /// + public IEmailAddress From { get; set; } + /// + /// >The email recipients. + /// + public IEnumerable Recipients { get; set; } + /// + /// The CC email recipients. + /// + public IEnumerable CcRecipients { get; set; } + /// + /// The BCC email recipients. + /// + public IEnumerable BccRecipients { get; set; } + /// + /// The subject. + /// + public string Subject { get; set; } + /// + /// The body as plain text. + /// + public string BodyText { get; set; } + /// + /// The body as HTML. + /// + public string BodyHtml { get; set; } + /// + /// The file attachments. + /// + public IEnumerable Attachments { get; set; } + /// + /// The reply-to email address. + /// + public IEmailAddress ReplyTo { get; set; } + /// + /// For template emails. + /// + public IDictionary TemplateDictionary { get; set; } + } +} diff --git a/src/Proffer.Email/IEmail.cs b/src/Proffer.Email/IEmail.cs new file mode 100644 index 0000000..118c896 --- /dev/null +++ b/src/Proffer.Email/IEmail.cs @@ -0,0 +1,51 @@ +using System.Collections.Generic; + +namespace Proffer.Email +{ + /// + /// Contains the features that an email should have. + /// + public interface IEmail + { + /// + /// The sender email address. + /// + IEmailAddress From { get; set; } + /// + /// >The email recipients. + /// + IEnumerable Recipients { get; set; } + /// + /// The CC email recipients. + /// + IEnumerable CcRecipients { get; set; } + /// + /// The BCC email recipients. + /// + IEnumerable BccRecipients { get; set; } + /// + /// The subject. + /// + string Subject { get; set; } + /// + /// The body as plain text. + /// + string BodyText { get; set; } + /// + /// The body as HTML. + /// + string BodyHtml { get; set; } + /// + /// The file attachments. + /// + IEnumerable Attachments { get; set; } + /// + /// The reply-to email address. + /// + IEmailAddress ReplyTo { get; set; } + /// + /// For template emails. + /// + IDictionary TemplateDictionary { get; set; } + } +} diff --git a/src/Proffer.Email/IEmailBuilder.cs b/src/Proffer.Email/IEmailBuilder.cs new file mode 100644 index 0000000..f4d990c --- /dev/null +++ b/src/Proffer.Email/IEmailBuilder.cs @@ -0,0 +1,64 @@ +using System.Collections.Generic; +using Proffer.Email.Internal; + +namespace Proffer.Email +{ + /// + /// Builds an email object with additional features. + /// + public interface IEmailBuilder + { + /// + /// Returns existing email object + /// + /// + public IEmail Build(); + + /// + /// Adding reply to feature to email object + /// + /// Email Address + /// + public EmailBuilder AddReplyTo(IEmailAddress emailAddress); + /// + /// Adding recipents to email object + /// + /// Recipients + public EmailBuilder AddRecipient(IEnumerable recipients); + /// + /// Adding ccrecipents to email object + /// + /// Cc Recipients + public EmailBuilder AddCarbonCopyRecipient(IEnumerable ccRecipients); + /// + /// Adding bccrecipents to email object + /// + /// Bcc Recipients + public EmailBuilder AddBlackCarbonCopyRecipient(IEnumerable bccRecipients); + /// + /// Adding subject to email object + /// + /// Subject + public EmailBuilder AddSubject(string subject); + /// + /// Adding attachment to email object + /// + /// Attachment + public EmailBuilder AddAttachment(IEnumerable attachments); + /// + /// Adding bodyHtml to email object + /// + /// Body Html + public EmailBuilder AddBodyHtml(string bodyHtml); + /// + /// Adding bodyText to email object + /// + /// Body Text + public EmailBuilder AddBodyText(string bodyText); + /// + /// Adding template feature to email object + /// + /// Template Key + public EmailBuilder AddTemplate(string templateKey); + } +} diff --git a/src/Proffer.Email/IEmailProvider.cs b/src/Proffer.Email/IEmailProvider.cs index 625d273..af88365 100644 --- a/src/Proffer.Email/IEmailProvider.cs +++ b/src/Proffer.Email/IEmailProvider.cs @@ -11,45 +11,10 @@ public interface IEmailProvider /// /// Sends an email. /// - /// The sender email address. - /// The email recipients. - /// The subject. - /// The body as plain text. - /// The body as HTML. + /// All informations about the email. /// /// A task that represents the asynchronous operation. /// - Task SendEmailAsync(IEmailAddress from, IEnumerable recipients, string subject, string bodyText, string bodyHtml); - - /// - /// Sends an email. - /// - /// The sender email address. - /// The email recipients. - /// The subject. - /// The body as plain text. - /// The body as HTML. - /// The file attachments. - /// - /// A task that represents the asynchronous operation. - /// - Task SendEmailAsync(IEmailAddress from, IEnumerable recipients, string subject, string bodyText, string bodyHtml, IEnumerable attachments); - - /// - /// Sends an email. - /// - /// The sender email address. - /// The email recipients. - /// The CC email recipients. - /// The BCC email recipients. - /// The subject. - /// The body as plain text. - /// The body as HTML. - /// The file attachments. - /// The reply-to email address. - /// - /// A task that represents the asynchronous operation. - /// - Task SendEmailAsync(IEmailAddress from, IEnumerable recipients, IEnumerable ccRecipients, IEnumerable bccRecipients, string subject, string bodyText, string bodyHtml, IEnumerable attachments, IEmailAddress replyTo = null); + Task SendEmailAsync(IEmail email); } } diff --git a/src/Proffer.Email/IEmailSender.cs b/src/Proffer.Email/IEmailSender.cs index 2bca7a2..3d71a27 100644 --- a/src/Proffer.Email/IEmailSender.cs +++ b/src/Proffer.Email/IEmailSender.cs @@ -8,171 +8,25 @@ namespace Proffer.Email /// public interface IEmailSender { - /// - /// Sends an email. - /// - /// The subject. - /// The body as plain text. - /// The email recipients. - /// - /// A task that represents the asynchronous operation. - /// - Task SendEmailAsync(string subject, string message, params IEmailAddress[] to); - - /// - /// Sends an email. - /// - /// The sender email address. - /// The subject. - /// The body as plain text. - /// The email recipients. - /// - /// A task that represents the asynchronous operation. - /// - Task SendEmailAsync(IEmailAddress from, string subject, string message, params IEmailAddress[] to); - - /// - /// Sends an email. - /// - /// The sender email address. - /// The reply-to email address. - /// The subject. - /// The body as plain text. - /// If set to true the body shoud be sent as plain text only. - /// The email recipients. - /// - /// A task that represents the asynchronous operation. - /// - Task SendEmailAsync(IEmailAddress from, IEmailAddress replyTo, string subject, string message, bool plainTextOnly, params IEmailAddress[] to); /// /// Sends an email. /// - /// The sender email address. - /// The subject. - /// The body as plain text. - /// The file attachments. - /// The email recipients. - /// - /// A task that represents the asynchronous operation. - /// - Task SendEmailAsync(IEmailAddress from, string subject, string message, IEnumerable attachments, params IEmailAddress[] to); - - /// - /// Sends an email. - /// - /// The sender email address. - /// The reply-to email address. - /// The subject. - /// The body as plain text. - /// If set to true the body shoud be sent as plain text only. - /// The file attachments. - /// The email recipients. - /// - /// A task that represents the asynchronous operation. - /// - Task SendEmailAsync(IEmailAddress from, IEmailAddress replyTo, string subject, string message, bool plainTextOnly, IEnumerable attachments, params IEmailAddress[] to); - - /// - /// Sends an email. - /// - /// The sender email address. - /// The subject. - /// The body as plain text. - /// The file attachments. - /// The email recipients. - /// The CC email recipients. - /// The BCC email recipients. - /// The reply-to email address. - /// If set to true the body shoud be sent as plain text only. - /// - /// A task that represents the asynchronous operation. - /// - Task SendEmailAsync(IEmailAddress from, string subject, string message, IEnumerable attachments, IEmailAddress[] to, IEmailAddress[] cc, IEmailAddress[] bcc, IEmailAddress replyTo = null, bool plainTextOnly = false); - - /// - /// Sends a templated email from the configured default sender email address. - /// - /// The type of context to apply on the template. - /// The template key. - /// The context to apply on the template. - /// The email recipients. - /// - /// A task that represents the asynchronous operation. - /// - Task SendTemplatedEmailAsync(string templateKey, T context, params IEmailAddress[] to); - - /// - /// Sends a templated email. - /// - /// The type of context to apply on the template. - /// The sender email address. - /// The template key. - /// The context to apply on the template. - /// The email recipients. - /// - /// A task that represents the asynchronous operation. - /// - Task SendTemplatedEmailAsync(IEmailAddress from, string templateKey, T context, params IEmailAddress[] to); - - /// - /// Sends a templated email. - /// - /// The type of context to apply on the template. - /// The sender email address. - /// The reply-to email address. - /// The template key. - /// The context to apply on the template. - /// The email recipients. - /// - /// A task that represents the asynchronous operation. - /// - Task SendTemplatedEmailAsync(IEmailAddress from, IEmailAddress replyTo, string templateKey, T context, params IEmailAddress[] to); - - /// - /// Sends a templated email. - /// - /// The type of context to apply on the template. - /// The sender email address. - /// The template key. - /// The context to apply on the template. - /// The file attachments. - /// The email recipients. - /// - /// A task that represents the asynchronous operation. - /// - Task SendTemplatedEmailAsync(IEmailAddress from, string templateKey, T context, IEnumerable attachments, params IEmailAddress[] to); - - /// - /// Sends a templated email. - /// - /// The type of context to apply on the template. - /// The sender email address. - /// The reply-to email address. - /// The template key. - /// The context to apply on the template. - /// The file attachments. - /// The email recipients. + /// Everything about the mail. /// /// A task that represents the asynchronous operation. /// - Task SendTemplatedEmailAsync(IEmailAddress from, IEmailAddress replyTo, string templateKey, T context, IEnumerable attachments, params IEmailAddress[] to); + Task SendEmailAsync(IEmail email); /// /// Sends a templated email. /// /// The type of context to apply on the template. - /// The sender email address. - /// The template key. + /// Everything about the email. /// The context to apply on the template. - /// The file attachments. - /// The email recipients. - /// The CC email recipients. - /// The BCC email recipients. - /// The reply-to email address. /// /// A task that represents the asynchronous operation. /// - Task SendTemplatedEmailAsync(IEmailAddress from, string templateKey, T context, IEnumerable attachments, IEmailAddress[] to, IEmailAddress[] cc, IEmailAddress[] bcc, IEmailAddress replyTo = null); + Task SendTemplatedEmailAsync(IEmail email, T context); } } diff --git a/src/Proffer.Email/Internal/EmailBuilder.cs b/src/Proffer.Email/Internal/EmailBuilder.cs new file mode 100644 index 0000000..4ae5606 --- /dev/null +++ b/src/Proffer.Email/Internal/EmailBuilder.cs @@ -0,0 +1,130 @@ +using System.Collections.Generic; + +namespace Proffer.Email.Internal +{ + /// + /// Builds an email object with additional features. + /// + public class EmailBuilder : IEmailBuilder + { + private IEmail email = new Email(); + + /// + /// Creating the email builder with required two paraters. + /// + /// Who sents mail + /// Who gets email as first responsible + public EmailBuilder(IEmailAddress From, IEnumerable Recipients) + { + this.email.From = From; + this.email.Recipients = Recipients; + this.email.ReplyTo = null; + this.email.TemplateDictionary = new Dictionary + { + { EmailTemplateType.Subject, string.Empty}, + { EmailTemplateType.BodyText, string.Empty}, + { EmailTemplateType.BodyHtml, string.Empty}, + }; + this.email.BccRecipients = new List(); + this.email.CcRecipients = new List(); + } + + /// + /// Replies an email. + /// + /// Email address + public EmailBuilder AddReplyTo(IEmailAddress emailAddress) + { + this.email.ReplyTo = emailAddress; + return this; + } + + /// + /// Adds recipients to email. + /// + /// Recipient's email adressess + public EmailBuilder AddRecipient(IEnumerable recipients) + { + this.email.Recipients = recipients; + return this; + } + + /// + /// Adds ccrecipients to email. + /// + /// /// CcRecipient's email adressess + public EmailBuilder AddCarbonCopyRecipient(IEnumerable ccRecipients) + { + this.email.CcRecipients = ccRecipients; + return this; + } + + /// + /// Adds bccrecipients to email. + /// + /// BccRecipient's email adressess + public EmailBuilder AddBlackCarbonCopyRecipient(IEnumerable bccRecipients) + { + this.email.BccRecipients = bccRecipients; + return this; + } + + /// + /// Adds subject to email. + /// + /// Mail's subject + public EmailBuilder AddSubject(string subject) + { + this.email.Subject = subject; + return this; + } + + /// + /// Adds attachment to email. + /// + /// Mail's attachments + public EmailBuilder AddAttachment(IEnumerable attachments) + { + this.email.Attachments = attachments; + return this; + } + + /// + /// Adds bodyhtml to email. + /// + /// Mail's bodyHtml + public EmailBuilder AddBodyHtml(string bodyHtml) + { + this.email.BodyHtml = bodyHtml; + return this; + } + + /// + /// Adds bodytext to email. + /// + /// Mail's bodyText + public EmailBuilder AddBodyText(string bodyText) + { + this.email.BodyText = bodyText; + return this; + } + + /// + /// Adds templatemail feature to email. + /// + /// Sets mail's send with which template. + public EmailBuilder AddTemplate(string templateKey) + { + this.email.TemplateDictionary = new Dictionary() + { + { EmailTemplateType.Subject, templateKey}, + { EmailTemplateType.BodyText, templateKey }, + { EmailTemplateType.BodyHtml, templateKey}, + }; + + return this; + } + + IEmail IEmailBuilder.Build() => this.email; + } +} diff --git a/src/Proffer.Email/Internal/EmailSender.cs b/src/Proffer.Email/Internal/EmailSender.cs index f06fc10..03453d3 100644 --- a/src/Proffer.Email/Internal/EmailSender.cs +++ b/src/Proffer.Email/Internal/EmailSender.cs @@ -61,217 +61,33 @@ public EmailSender( /// /// Sends an email. /// - /// The subject. - /// The body as plain text. - /// The email recipients. + /// Everything about the mail. /// /// A task that represents the asynchronous operation. /// - public Task SendEmailAsync(string subject, string message, params IEmailAddress[] to) - => this.SendEmailAsync(this.options.DefaultSender, subject, message, to); - - /// - /// Sends an email. - /// - /// The sender email address. - /// The subject. - /// The body as plain text. - /// The email recipients. - /// - /// A task that represents the asynchronous operation. - /// - public Task SendEmailAsync(IEmailAddress from, string subject, string message, params IEmailAddress[] to) - => this.SendEmailAsync(from, subject, message, Enumerable.Empty(), to); - - /// - /// Sends an email. - /// - /// The sender email address. - /// The reply-to email address. - /// The subject. - /// The body as plain text. - /// If set to true the body shoud be sent as plain text only. - /// The email recipients. - /// - /// A task that represents the asynchronous operation. - /// - public Task SendEmailAsync(IEmailAddress from, IEmailAddress replyTo, string subject, string message, bool plainTextOnly, params IEmailAddress[] to) - => this.SendEmailAsync(from, replyTo, subject, message, plainTextOnly, Enumerable.Empty(), to); - - /// - /// Sends an email. - /// - /// The sender email address. - /// The subject. - /// The body as plain text. - /// The file attachments. - /// The email recipients. - /// - /// A task that represents the asynchronous operation. - /// - public Task SendEmailAsync(IEmailAddress from, string subject, string message, IEnumerable attachments, params IEmailAddress[] to) - => this.SendEmailAsync(from, subject, message, attachments, to.ToArray(), new IEmailAddress[0], new IEmailAddress[0]); - - /// - /// Sends an email. - /// - /// The sender email address. - /// The reply-to email address. - /// The subject. - /// The body as plain text. - /// If set to true the body shoud be sent as plain text only. - /// The file attachments. - /// The email recipients. - /// - /// A task that represents the asynchronous operation. - /// - public Task SendEmailAsync(IEmailAddress from, IEmailAddress replyTo, string subject, string message, bool plainTextOnly, IEnumerable attachments, params IEmailAddress[] to) - => this.SendEmailAsync(from, subject, message, attachments, to.ToArray(), new IEmailAddress[0], new IEmailAddress[0], replyTo: replyTo, plainTextOnly: plainTextOnly); - - /// - /// Sends an email. - /// - /// The sender email address. - /// The subject. - /// The body as plain text. - /// The file attachments. - /// The email recipients. - /// The CC email recipients. - /// The BCC email recipients. - /// The reply-to email address. - /// If set to true the body shoud be sent as plain text only. - /// - /// A task that represents the asynchronous operation. - /// - public Task SendEmailAsync(IEmailAddress from, string subject, string message, IEnumerable attachments, IEmailAddress[] to, IEmailAddress[] cc, IEmailAddress[] bcc, IEmailAddress replyTo = null, bool plainTextOnly = false) + public Task SendEmailAsync(IEmail email) { - if (plainTextOnly) - { - return this.DoMockupAndSendEmailAsync( - from, - replyTo, - to, - cc, - bcc, - subject, - message, - null, - attachments); - } - - return this.DoMockupAndSendEmailAsync( - from, - replyTo, - to, - cc, - bcc, - subject, - message, - $"{subject}{message}", - attachments); + return this.DoMockupAndSendEmailAsync(email); } - /// - /// Sends a templated email from the configured default sender email address. - /// - /// The type of context to apply on the template. - /// The template key. - /// The context to apply on the template. - /// The email recipients. - /// - /// A task that represents the asynchronous operation. - /// - public Task SendTemplatedEmailAsync(string templateKey, T context, params IEmailAddress[] to) - => this.SendTemplatedEmailAsync(this.options.DefaultSender, templateKey, context, to); - - /// - /// Sends a templated email. - /// - /// The type of context to apply on the template. - /// The sender email address. - /// The template key. - /// The context to apply on the template. - /// The email recipients. - /// - /// A task that represents the asynchronous operation. - /// - public Task SendTemplatedEmailAsync(IEmailAddress from, string templateKey, T context, params IEmailAddress[] to) - => this.SendTemplatedEmailAsync(from, templateKey, context, Enumerable.Empty(), to); - - /// - /// Sends a templated email. - /// - /// The type of context to apply on the template. - /// The sender email address. - /// The reply-to email address. - /// The template key. - /// The context to apply on the template. - /// The email recipients. - /// - /// A task that represents the asynchronous operation. - /// - public Task SendTemplatedEmailAsync(IEmailAddress from, IEmailAddress replyTo, string templateKey, T context, params IEmailAddress[] to) - => this.SendTemplatedEmailAsync(from, replyTo, templateKey, context, Enumerable.Empty(), to); - /// /// Sends a templated email. /// /// The type of context to apply on the template. - /// The sender email address. - /// The template key. + /// Everything about the mail. /// The context to apply on the template. - /// The file attachments. - /// The email recipients. - /// - /// A task that represents the asynchronous operation. - /// - public Task SendTemplatedEmailAsync(IEmailAddress from, string templateKey, T context, IEnumerable attachments, params IEmailAddress[] to) - => this.SendTemplatedEmailAsync(from, templateKey, context, attachments, to, new IEmailAddress[0], new IEmailAddress[0]); + public async Task SendTemplatedEmailAsync(IEmail email, T context) + { + ITemplate subjectTemplate = await this.GetTemplateAsync(email.TemplateDictionary[EmailTemplateType.Subject], EmailTemplateType.Subject); + email.Subject = subjectTemplate.Apply(context); - /// - /// Sends a templated email. - /// - /// The type of context to apply on the template. - /// The sender email address. - /// The reply-to email address. - /// The template key. - /// The context to apply on the template. - /// The file attachments. - /// The email recipients. - /// - /// A task that represents the asynchronous operation. - /// - public Task SendTemplatedEmailAsync(IEmailAddress from, IEmailAddress replyTo, string templateKey, T context, IEnumerable attachments, params IEmailAddress[] to) - => this.SendTemplatedEmailAsync(from, templateKey, context, attachments, to, new IEmailAddress[0], new IEmailAddress[0], replyTo: replyTo); + ITemplate textTemplate = await this.GetTemplateAsync(email.TemplateDictionary[EmailTemplateType.BodyText], EmailTemplateType.BodyText); + email.BodyText = textTemplate.Apply(context); - /// - /// Sends a templated email. - /// - /// The type of context to apply on the template. - /// The sender email address. - /// The template key. - /// The context to apply on the template. - /// The file attachments. - /// The email recipients. - /// The CC email recipients. - /// The BCC email recipients. - /// The reply-to email address. - public async Task SendTemplatedEmailAsync(IEmailAddress from, string templateKey, T context, IEnumerable attachments, IEmailAddress[] to, IEmailAddress[] cc, IEmailAddress[] bcc, IEmailAddress replyTo = null) - { - ITemplate subjectTemplate = await this.GetTemplateAsync(templateKey, EmailTemplateType.Subject); - ITemplate textTemplate = await this.GetTemplateAsync(templateKey, EmailTemplateType.BodyText); - ITemplate htmlTemplate = await this.GetTemplateAsync(templateKey, EmailTemplateType.BodyHtml); + ITemplate htmlTemplate = await this.GetTemplateAsync(email.TemplateDictionary[EmailTemplateType.BodyHtml], EmailTemplateType.BodyHtml); + email.BodyHtml = htmlTemplate.Apply(context); - await this.DoMockupAndSendEmailAsync( - from, - replyTo, - to, - cc, - bcc, - subjectTemplate.Apply(context), - textTemplate.Apply(context), - htmlTemplate.Apply(context), - attachments); + await this.DoMockupAndSendEmailAsync(email); } /// @@ -322,45 +138,27 @@ private IEnumerable MockRecipients(IEnumerable rec return finalRecipients; } - private async Task DoMockupAndSendEmailAsync( - IEmailAddress from, - IEmailAddress replyTo, - IEnumerable recipients, - IEnumerable ccRecipients, - IEnumerable bccRecipients, - string subject, - string text, - string html, - IEnumerable attachments) + private async Task DoMockupAndSendEmailAsync(IEmail email) { var mockedUpRecipients = new List(); - IEnumerable finalToRecipients = this.MockRecipients(recipients, mockedUpRecipients); - IEnumerable finalCcRecipients = this.MockRecipients(ccRecipients, mockedUpRecipients); - IEnumerable finalBccRecipients = this.MockRecipients(bccRecipients, mockedUpRecipients); + email.Recipients = this.MockRecipients(email.Recipients, mockedUpRecipients); + email.CcRecipients = this.MockRecipients(email.CcRecipients, mockedUpRecipients); + email.BccRecipients = this.MockRecipients(email.BccRecipients, mockedUpRecipients); if (mockedUpRecipients.Any()) { string disclaimer = this.options.Mockup.Disclaimer; string joinedMockedUpRecipients = string.Join(", ", mockedUpRecipients.Select(r => $"{r.DisplayName} ({r.Email})")); - text = string.Concat(text, Environment.NewLine, disclaimer, Environment.NewLine, joinedMockedUpRecipients); - if (html != null) + email.BodyText = string.Concat(email.BodyText, Environment.NewLine, disclaimer, Environment.NewLine, joinedMockedUpRecipients); + if (email.BodyHtml != null) { - html = string.Concat(html, "
", disclaimer, "
", joinedMockedUpRecipients, "
"); + email.BodyHtml = string.Concat(email.BodyHtml, "
", disclaimer, "
", joinedMockedUpRecipients, "
"); } } - await this.provider.SendEmailAsync( - from, - finalToRecipients, - finalCcRecipients, - finalBccRecipients, - subject, - text, - html, - attachments, - replyTo: replyTo); + await this.provider.SendEmailAsync(email); } } } diff --git a/tests/Proffer.Email.InMemory.Tests/InMemoryEmailProviderTests.cs b/tests/Proffer.Email.InMemory.Tests/InMemoryEmailProviderTests.cs index 25295d0..d7cfb5d 100644 --- a/tests/Proffer.Email.InMemory.Tests/InMemoryEmailProviderTests.cs +++ b/tests/Proffer.Email.InMemory.Tests/InMemoryEmailProviderTests.cs @@ -34,148 +34,118 @@ public InMemoryEmailProviderTests(InMemoryFixture fixture) [Fact] public async Task Should_SendEmailAsync() { - string subject = "Hello!"; - string message = "Message in plain text"; var recipient = new EmailAddress("recipient-1@getproffer.net", "Recipient"); + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, new List() { recipient }) + .AddSubject("Hello!") + .AddBodyText("Message in plain text"); - await this.emailSender.SendEmailAsync(subject, message, recipient); + await this.emailSender.SendEmailAsync(emailBuilder.Build()); - this.fixture.Verify( - subject: subject, - bodyText: message, - bodyHtml: $"{subject}{message}", - recipients: new() { recipient }); + emailBuilder.AddBodyHtml($"{emailBuilder.Build().Subject}{emailBuilder.Build().BodyText}"); + this.fixture.Verify(emailBuilder.Build()); } [Fact] public async Task Should_SendEmailAsync_With_Attachments() { - string subject = "Hello!"; - string message = "Message in plain text"; var recipient = new EmailAddress("recipient-1@getproffer.net", "Recipient"); - IFileReference beach = await this.fixture.Attachments.GetAsync("beach.jpeg", withMetadata: true); IFileReference sample = await this.fixture.Attachments.GetAsync("sample.pdf", withMetadata: true); - var attachments = new List - { - new EmailAttachment(beach.Path, await beach.ReadAllBytesAsync(), beach.Properties.ContentType), - new EmailAttachment(sample.Path, await sample.ReadAllBytesAsync(), sample.Properties.ContentType.Split('/')[0], sample.Properties.ContentType.Split('/')[1]), - }; + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, new List() { recipient }) + .AddSubject("Hello!") + .AddBodyText("Message in plain text") + .AddAttachment(new List + { + new EmailAttachment(beach.Path, await beach.ReadAllBytesAsync(), beach.Properties.ContentType), + new EmailAttachment(sample.Path, await sample.ReadAllBytesAsync(), sample.Properties.ContentType.Split('/')[0], sample.Properties.ContentType.Split('/')[1]), + }); - await this.emailSender.SendEmailAsync(this.options.DefaultSender, subject, message, attachments, recipient); - this.fixture.Verify( - subject: subject, - bodyText: message, - bodyHtml: $"{subject}{message}", - recipients: new() { recipient }, - attachments: attachments); + await this.emailSender.SendEmailAsync(emailBuilder.Build()); + emailBuilder.AddBodyHtml($"{emailBuilder.Build().Subject}{emailBuilder.Build().BodyText}"); + + this.fixture.Verify(emailBuilder.Build()); } [Fact] public async Task Should_SendEmailAsync_With_CarbonCopyRecipients() { - string subject = "Hello!"; - string message = "Message in plain text"; var recipient = new EmailAddress("recipient-1@getproffer.net", "Recipient"); var carbonCopyRecipient = new EmailAddress("cc-recipient@getproffer.net", "Carbon-Copy Recipient"); - await this.emailSender.SendEmailAsync( - this.options.DefaultSender, - subject, - message, - Enumerable.Empty(), - new IEmailAddress[] { recipient }, - new IEmailAddress[] { carbonCopyRecipient }, - Array.Empty()); - - this.fixture.Verify( - subject: subject, - bodyText: message, - bodyHtml: $"{subject}{message}", - recipients: new() { recipient }, - ccRecipients: new() { carbonCopyRecipient }); + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, new List() { recipient }) + .AddCarbonCopyRecipient(new List() { carbonCopyRecipient }) + .AddSubject("Hello!") + .AddBodyText("Message in plain text"); + + await this.emailSender.SendEmailAsync(emailBuilder.Build()); + + emailBuilder.AddBodyHtml($"{emailBuilder.Build().Subject}{emailBuilder.Build().BodyText}"); + + this.fixture.Verify(emailBuilder.Build()); } [Fact] public async Task Should_SendEmailAsync_With_BlackCarbonCopyRecipients() { - string subject = "Hello!"; - string message = "Message in plain text"; var recipient = new EmailAddress("recipient-1@getproffer.net", "Recipient"); var blackCarbonCopyRecipient = new EmailAddress("cc-recipient@getproffer.net", "Carbon-Copy Recipient"); - await this.emailSender.SendEmailAsync( - this.options.DefaultSender, - subject, - message, - Enumerable.Empty(), - new IEmailAddress[] { recipient }, - Array.Empty(), - new IEmailAddress[] { blackCarbonCopyRecipient }); - - this.fixture.Verify( - subject: subject, - bodyText: message, - bodyHtml: $"{subject}{message}", - recipients: new() { recipient }, - bccRecipients: new() { blackCarbonCopyRecipient }); + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, new List() { recipient }) + .AddBlackCarbonCopyRecipient(new List() { blackCarbonCopyRecipient }) + .AddSubject("Hello!") + .AddBodyText("Message in plain text"); + + await this.emailSender.SendEmailAsync(emailBuilder.Build()); + + emailBuilder.AddBodyHtml($"{emailBuilder.Build().Subject}{emailBuilder.Build().BodyText}"); + + this.fixture.Verify(emailBuilder.Build()); } [Fact] public async Task Should_SendEmailAsync_With_PlainTextOnly() { - string subject = "Hello!"; - string message = "Message in plain text"; var recipient = new EmailAddress("recipient-1@getproffer.net", "Recipient"); + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, new List() { recipient }) + .AddSubject("Hello!") + .AddBodyText("Message in plain text"); + + await this.emailSender.SendEmailAsync(emailBuilder.Build()); - await this.emailSender.SendEmailAsync( - this.options.DefaultSender, - this.options.DefaultSender, - subject, - message, - plainTextOnly: true, - recipient); - - this.fixture.Verify( - subject: subject, - bodyText: message, - recipients: new() { recipient }); + this.fixture.Verify(emailBuilder.Build()); } [Fact] public async Task Should_SendEmailAsync_With_ReplyTo() { - string subject = "Hello!"; - string message = "Message in plain text"; var recipient = new EmailAddress("recipient-1@getproffer.net", "Recipient"); var replyTo = new EmailAddress("custom-reply-to@getproffer.net", "Custom Reply-To"); - await this.emailSender.SendEmailAsync(this.options.DefaultSender, replyTo, subject, message, true, recipient); + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, new List() { recipient }) + .AddSubject("Hello!") + .AddBodyText("Message in plain text") + .AddReplyTo(replyTo); - this.fixture.Verify( - subject: subject, - bodyText: message, - recipients: new() { recipient }, - replyTo: replyTo); + await this.emailSender.SendEmailAsync(emailBuilder.Build()); + + this.fixture.Verify(emailBuilder.Build()); } [Fact] public async Task Should_SendEmailAsync_With_Sender() { - string subject = "Hello!"; - string message = "Message in plain text"; var recipient = new EmailAddress("recipient-1@getproffer.net", "Recipient"); var sender = new EmailAddress("custom-sender@getproffer.net", "Custom Sender"); - await this.emailSender.SendEmailAsync(sender, subject, message, recipient); + IEmailBuilder emailBuilder = new EmailBuilder(sender, new List() { recipient }) + .AddSubject("Hello!") + .AddBodyText("Message in plain text"); + + await this.emailSender.SendEmailAsync(emailBuilder.Build()); - this.fixture.Verify( - subject: subject, - bodyText: message, - recipients: new() { recipient }, - sender: sender); + this.fixture.Verify(emailBuilder.Build()); } [Fact] @@ -192,13 +162,16 @@ public async Task Should_SendTemplatedEmailAsync_With_KeyAndContext() var recipient = new EmailAddress("recipient-1@getproffer.net", context.Name); - await this.emailSender.SendTemplatedEmailAsync(templateKey, context, recipient); + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, new List() { recipient }) + .AddTemplate(templateKey); - this.fixture.Verify( - subject: $"Hello {context.Name}!", - bodyHtml: $"

{WebUtility.HtmlEncode(context.Title)}

{Environment.NewLine}{context.RawHtml}", - bodyText: $"{context.Title}{Environment.NewLine}{Environment.NewLine}{context.Message}", - recipients: new() { recipient }); + await this.emailSender.SendTemplatedEmailAsync(emailBuilder.Build(), context); + + emailBuilder.AddSubject($"Hello {context.Name}!") + .AddBodyHtml($"

{WebUtility.HtmlEncode(context.Title)}

{Environment.NewLine}{context.RawHtml}") + .AddBodyText($"{context.Title}{Environment.NewLine}{Environment.NewLine}{context.Message}"); + + this.fixture.Verify(emailBuilder.Build()); } [Fact] @@ -217,15 +190,17 @@ public async Task Should_SendTemplatedEmailAsync_With_SenderAndReplyTo() var replyTo = new EmailAddress("hello@getproffer.net", "Proffer"); var recipient = new EmailAddress("recipient-1@getproffer.net", context.Name); - await this.emailSender.SendTemplatedEmailAsync(sender, replyTo, templateKey, context, recipient); + IEmailBuilder emailBuilder = new EmailBuilder(sender, new List() { recipient }) + .AddTemplate(templateKey) + .AddReplyTo(replyTo); + + await this.emailSender.SendTemplatedEmailAsync(emailBuilder.Build(), context); + + emailBuilder.AddSubject($"Hello {context.Name}!") + .AddBodyHtml($"

{WebUtility.HtmlEncode(context.Title)}

{Environment.NewLine}{context.RawHtml}") + .AddBodyText($"{context.Title}{Environment.NewLine}{Environment.NewLine}{context.Message}"); - this.fixture.Verify( - subject: $"Hello {context.Name}!", - bodyHtml: $"

{WebUtility.HtmlEncode(context.Title)}

{Environment.NewLine}{context.RawHtml}", - bodyText: $"{context.Title}{Environment.NewLine}{Environment.NewLine}{context.Message}", - recipients: new() { recipient }, - sender: sender, - replyTo: replyTo); + this.fixture.Verify(emailBuilder.Build()); } } } diff --git a/tests/Proffer.Email.InMemory.Tests/InMemoryFixture.cs b/tests/Proffer.Email.InMemory.Tests/InMemoryFixture.cs index 1ab0ef7..e6a5080 100644 --- a/tests/Proffer.Email.InMemory.Tests/InMemoryFixture.cs +++ b/tests/Proffer.Email.InMemory.Tests/InMemoryFixture.cs @@ -26,24 +26,15 @@ public InMemoryFixture() public IStore Attachments { get; } - public void Verify( - IEmailAddress sender = null, - List recipients = null, - List ccRecipients = null, - List bccRecipients = null, - string subject = null, - string bodyText = null, - string bodyHtml = null, - List attachments = null, - IEmailAddress replyTo = null) + public void Verify(IEmail email) { IOptions options = this.Services.GetRequiredService>(); - sender ??= options.Value.DefaultSender; - recipients ??= new(); - ccRecipients ??= new(); - bccRecipients ??= new(); - attachments ??= new(); + email.From ??= options.Value.DefaultSender; + email.Recipients ??= new List(); + email.CcRecipients ??= new List(); + email.BccRecipients ??= new List(); + email.Attachments ??= new List(); EmailAddressStrictEqualityComparer emailComparer = new(); EmailAttachmentEqualityComparer attachmentComparer = new(); @@ -63,15 +54,15 @@ bool attachmentsEqual(List expected, IEnumerable emailComparer.Equals(sender, e.From)) - .Where(e => emailsEqual(recipients, e.To)) - .Where(e => emailsEqual(ccRecipients, e.Cc)) - .Where(e => emailsEqual(bccRecipients, e.Bcc)) - .Where(e => subject == null || subject == e.Subject) - .Where(e => bodyText == null || bodyText == e.MessageText) - .Where(e => bodyHtml == null || bodyHtml == e.MessageHtml) - .Where(e => attachmentsEqual(attachments, e.Attachments)) - .Where(e => replyTo == null || emailComparer.Equals(replyTo, e.ReplyTo)) + .Where(e => emailComparer.Equals(email.From, e.From)) + .Where(e => emailsEqual(email.Recipients.ToList(), e.To)) + .Where(e => emailsEqual(email.CcRecipients.ToList(), e.Cc)) + .Where(e => emailsEqual(email.BccRecipients.ToList(), e.Bcc)) + .Where(e => email.Subject == null || email.Subject == e.Subject) + .Where(e => email.BodyText == null || email.BodyText == e.MessageText) + .Where(e => email.BodyHtml == null || email.BodyHtml == e.MessageHtml) + .Where(e => attachmentsEqual(email.Attachments.ToList(), e.Attachments)) + .Where(e => email.ReplyTo == null || emailComparer.Equals(email.ReplyTo, e.ReplyTo)) .Any(); Assert.True(emailWasStored); diff --git a/tests/Proffer.Email.SendGrid.Tests/SendSimpleEmailTests.cs b/tests/Proffer.Email.SendGrid.Tests/SendSimpleEmailTests.cs index d1099e3..3d99803 100644 --- a/tests/Proffer.Email.SendGrid.Tests/SendSimpleEmailTests.cs +++ b/tests/Proffer.Email.SendGrid.Tests/SendSimpleEmailTests.cs @@ -29,74 +29,91 @@ public SendSimpleEmailTests(SendGridFixture fixture) [Fact] public async Task Should_SendEmail_With_SimpleArguments() { - await this.emailSender.SendEmailAsync( - "Simple mail", - "Hello, it's a simple mail", - new EmailAddress + IEmailBuilder emailBuilder = new EmailBuilder( + this.storeFixture.DefaultSender, + new List() { - DisplayName = "test user", - Email = "tests@getproffer.net" - }); + new EmailAddress + { + DisplayName = "test user", + Email = "tests@getproffer.net" + } + }) + .AddSubject("Simple mail") + .AddBodyText("Hello, it's a simple mail"); + await this.emailSender.SendEmailAsync(emailBuilder.Build()); } [Fact] public async Task Should_SendEmail_With_ReplyTo() { - await this.emailSender.SendEmailAsync( + IEmailBuilder emailBuilder = new EmailBuilder( this.storeFixture.DefaultSender, - new EmailAddress + new List() + { + new EmailAddress + { + DisplayName = "test user", + Email = "tests@getproffer.net" + } + }) + .AddSubject("SendEmail with reply") + .AddBodyText("Hello, it's a email with reply") + .AddReplyTo(new EmailAddress { DisplayName = "Reply Address", Email = "tests@getproffer.net" - }, - "Simple mail", "Hello, it's a simple mail", false, - new EmailAddress - { - DisplayName = "test user", - Email = "hello@getproffer.net" }); + + await this.emailSender.SendEmailAsync(emailBuilder.Build()); } [Fact] public async Task Should_SendEmail_With_CarbonCopyRecipients() { - await this.emailSender.SendEmailAsync( + IEmailBuilder emailBuilder = new EmailBuilder( this.storeFixture.DefaultSender, - "Cc test", - "Hello, this is an email with cc recipients", - Enumerable.Empty(), - new EmailAddress + new List() { - DisplayName = "recipient user", - Email = SendGridFixture.FirstRecipient - }.Yield(), - new EmailAddress + new EmailAddress + { + DisplayName = "test user", + Email = "tests@getproffer.net" + } + }) + .AddSubject("Cc test") + .AddBodyText("Hello, it's a cc test") + .AddCarbonCopyRecipient(new EmailAddress { DisplayName = "cc user", Email = SendGridFixture.SecondRecipient - }.Yield(), - Array.Empty()); + }.Yield()); + + await this.emailSender.SendEmailAsync(emailBuilder.Build()); } [Fact] public async Task Should_SendEmail_With_BlackCarbonCopyRecipients() { - await this.emailSender.SendEmailAsync( + IEmailBuilder emailBuilder = new EmailBuilder( this.storeFixture.DefaultSender, - "Bcc test", - "Hello, this is an email with bcc recipients", - Enumerable.Empty(), - new EmailAddress + new List() { - DisplayName = "recipient user", - Email = SendGridFixture.FirstRecipient - }.Yield(), - Array.Empty(), - new EmailAddress + new EmailAddress + { + DisplayName = "test user", + Email = "tests@getproffer.net" + } + }) + .AddSubject("Bcc test") + .AddBodyText("Hello, it's bcc test") + .AddBlackCarbonCopyRecipient(new EmailAddress { - DisplayName = "test user", + DisplayName = "bcc user", Email = SendGridFixture.SecondRecipient }.Yield()); + + await this.emailSender.SendEmailAsync(emailBuilder.Build()); } [Fact] @@ -108,38 +125,42 @@ public async Task Should_SendEmail_With_Attachments() data = System.IO.File.ReadAllBytes(@"Stores/Attachments/sample.pdf"); var pdf = new EmailAttachment("Sample.pdf", data, "application", "pdf"); - await this.emailSender.SendEmailAsync( + IEmailBuilder emailBuilder = new EmailBuilder( this.storeFixture.DefaultSender, - "Test mail with attachments", - "Hello, this is an email with attachments", - new List { image, pdf }, - new EmailAddress + new List() { - DisplayName = "test user", - Email = SendGridFixture.FirstRecipient - }); + new EmailAddress + { + DisplayName = "test user", + Email = "tests@getproffer.net" + } + }) + .AddSubject("Attachment test") + .AddBodyText("Hello, it's attachment test") + .AddAttachment(new List { image, pdf }); + + await this.emailSender.SendEmailAsync(emailBuilder.Build()); } [Fact] public async Task Should_Throw_With_CarbonCopyRecipientsDuplicates() { - await Assert.ThrowsAsync(() => - this.emailSender.SendEmailAsync( - this.storeFixture.DefaultSender, - "Cc test", - "Hello, this is an email with cc recipients", - Enumerable.Empty(), - new EmailAddress - { - DisplayName = "recipient user", - Email = SendGridFixture.SecondRecipient - }.Yield(), - new EmailAddress - { - DisplayName = "cc user", - Email = SendGridFixture.SecondRecipient - }.Yield(), - Array.Empty())); + IEmailBuilder emailBuilder = new EmailBuilder( + this.storeFixture.DefaultSender, + new EmailAddress + { + DisplayName = "recipient user", + Email = SendGridFixture.SecondRecipient + }.Yield()) + .AddSubject("Cc test") + .AddBodyText("Hello, this is an email with cc recipients") + .AddCarbonCopyRecipient(new EmailAddress + { + DisplayName = "cc user", + Email = SendGridFixture.SecondRecipient + }.Yield()); + + await this.emailSender.SendEmailAsync(emailBuilder.Build()); } } } diff --git a/tests/Proffer.Email.SendGrid.Tests/SendTemplatedEmailTests.cs b/tests/Proffer.Email.SendGrid.Tests/SendTemplatedEmailTests.cs index df63c2d..5627e4d 100644 --- a/tests/Proffer.Email.SendGrid.Tests/SendTemplatedEmailTests.cs +++ b/tests/Proffer.Email.SendGrid.Tests/SendTemplatedEmailTests.cs @@ -29,56 +29,53 @@ public SendTemplatedEmailTests(SendGridFixture fixture) [Fact] public async Task Should_SendTemplatedEmail_With_SimpleArguments() { - await this.emailSender.SendTemplatedEmailAsync( - "Notification1", - new { }, + IEmailBuilder emailBuilder = new EmailBuilder(this.storeFixture.DefaultSender, new EmailAddress { DisplayName = "test user", Email = SendGridFixture.FirstRecipient - }); + }.Yield()) + .AddSubject("Notification1"); + + await this.emailSender.SendTemplatedEmailAsync(emailBuilder.Build(), new { }); } [Fact] public async Task Should_SendTemplatedEmail_With_CarbonCopyRecipients() { - await this.emailSender.SendTemplatedEmailAsync( - this.storeFixture.DefaultSender, - "Notification1", - new { }, - Enumerable.Empty(), + IEmailBuilder emailBuilder = new EmailBuilder(this.storeFixture.DefaultSender, new EmailAddress { - DisplayName = "recipient user", + DisplayName = "recipent user", Email = SendGridFixture.FirstRecipient - }.Yield(), - new EmailAddress + }.Yield()) + .AddSubject("Notification1") + .AddCarbonCopyRecipient(new EmailAddress { - DisplayName = "cc user", + DisplayName = "test user", Email = SendGridFixture.SecondRecipient - }.Yield(), - Array.Empty()); + }.Yield()); + + await this.emailSender.SendTemplatedEmailAsync(emailBuilder.Build(), new { }); } [Fact] public async Task Should_SendTemplatedEmail_With_BlackCarbonCopyRecipients() { - await this.emailSender.SendTemplatedEmailAsync( - this.storeFixture.DefaultSender, - "Notification1", - new { }, - Enumerable.Empty(), + IEmailBuilder emailBuilder = new EmailBuilder(this.storeFixture.DefaultSender, new EmailAddress { - DisplayName = "recipient user", + DisplayName = "recipent user", Email = SendGridFixture.FirstRecipient - }.Yield(), - Array.Empty(), - new EmailAddress + }.Yield()) + .AddSubject("Notification1") + .AddBlackCarbonCopyRecipient(new EmailAddress { DisplayName = "test user", Email = SendGridFixture.SecondRecipient }.Yield()); + + await this.emailSender.SendTemplatedEmailAsync(emailBuilder.Build(), new { }); } [Fact] @@ -90,16 +87,16 @@ public async Task Should_SendTemplatedEmail_With_Attachments() data = System.IO.File.ReadAllBytes(@"Stores/Attachments/sample.pdf"); var pdf = new EmailAttachment("Sample.pdf", data, "application", "pdf"); - await this.emailSender.SendTemplatedEmailAsync( - this.storeFixture.DefaultSender, - "Notification1", - new { }, - new List { image, pdf }, + IEmailBuilder emailBuilder = new EmailBuilder(this.storeFixture.DefaultSender, new EmailAddress { DisplayName = "test user", Email = SendGridFixture.FirstRecipient - }); + }.Yield()) + .AddSubject("Notification1") + .AddAttachment(new List { image, pdf }); + + await this.emailSender.SendTemplatedEmailAsync(emailBuilder.Build(), new { }); } } } diff --git a/tests/Proffer.Email.Smtp.Tests/SmtpEmailProviderTests.cs b/tests/Proffer.Email.Smtp.Tests/SmtpEmailProviderTests.cs index 0f1cfbb..2d4bb33 100644 --- a/tests/Proffer.Email.Smtp.Tests/SmtpEmailProviderTests.cs +++ b/tests/Proffer.Email.Smtp.Tests/SmtpEmailProviderTests.cs @@ -41,148 +41,118 @@ public async Task InitializeAsync() [Fact] public async Task Should_SendEmailAsync() { - string subject = "Hello!"; - string message = "Message in plain text"; var recipient = new EmailAddress("recipient-1@getproffer.net", "Recipient"); + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, new List() { recipient }) + .AddSubject("Hello!") + .AddBodyText("Message in plain text"); - await this.emailSender.SendEmailAsync(subject, message, recipient); + await this.emailSender.SendEmailAsync(emailBuilder.Build()); - this.fixture.Verify( - subject: subject, - bodyText: message, - bodyHtml: $"{subject}{message}", - recipients: new() { recipient }); + emailBuilder.AddBodyHtml($"{emailBuilder.Build().Subject}{emailBuilder.Build().BodyText}"); + this.fixture.Verify(emailBuilder.Build()); } [Fact] public async Task Should_SendEmailAsync_With_Attachments() { - string subject = "Hello!"; - string message = "Message in plain text"; var recipient = new EmailAddress("recipient-1@getproffer.net", "Recipient"); - IFileReference beach = await this.fixture.Attachments.GetAsync("beach.jpeg", withMetadata: true); IFileReference sample = await this.fixture.Attachments.GetAsync("sample.pdf", withMetadata: true); - var attachments = new List - { - new EmailAttachment(beach.Path, await beach.ReadAllBytesAsync(), beach.Properties.ContentType), - new EmailAttachment(sample.Path, await sample.ReadAllBytesAsync(), sample.Properties.ContentType.Split('/')[0], sample.Properties.ContentType.Split('/')[1]), - }; + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, new List() { recipient }) + .AddSubject("Hello!") + .AddBodyText("Message in plain text") + .AddAttachment(new List + { + new EmailAttachment(beach.Path, await beach.ReadAllBytesAsync(), beach.Properties.ContentType), + new EmailAttachment(sample.Path, await sample.ReadAllBytesAsync(), sample.Properties.ContentType.Split('/')[0], sample.Properties.ContentType.Split('/')[1]), + }); - await this.emailSender.SendEmailAsync(this.options.DefaultSender, subject, message, attachments, recipient); - this.fixture.Verify( - subject: subject, - bodyText: message, - bodyHtml: $"{subject}{message}", - recipients: new() { recipient }, - attachments: attachments); + await this.emailSender.SendEmailAsync(emailBuilder.Build()); + emailBuilder.AddBodyHtml($"{emailBuilder.Build().Subject}{emailBuilder.Build().BodyText}"); + + this.fixture.Verify(emailBuilder.Build()); } [Fact] public async Task Should_SendEmailAsync_With_CarbonCopyRecipients() { - string subject = "Hello!"; - string message = "Message in plain text"; var recipient = new EmailAddress("recipient-1@getproffer.net", "Recipient"); var carbonCopyRecipient = new EmailAddress("cc-recipient@getproffer.net", "Carbon-Copy Recipient"); - await this.emailSender.SendEmailAsync( - this.options.DefaultSender, - subject, - message, - Enumerable.Empty(), - new IEmailAddress[] { recipient }, - new IEmailAddress[] { carbonCopyRecipient }, - Array.Empty()); - - this.fixture.Verify( - subject: subject, - bodyText: message, - bodyHtml: $"{subject}{message}", - recipients: new() { recipient }, - ccRecipients: new() { carbonCopyRecipient }); + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, new List() { recipient }) + .AddCarbonCopyRecipient(new List() { carbonCopyRecipient }) + .AddSubject("Hello!") + .AddBodyText("Message in plain text"); + + await this.emailSender.SendEmailAsync(emailBuilder.Build()); + + emailBuilder.AddBodyHtml($"{emailBuilder.Build().Subject}{emailBuilder.Build().BodyText}"); + + this.fixture.Verify(emailBuilder.Build()); } [Fact] public async Task Should_SendEmailAsync_With_BlackCarbonCopyRecipients() { - string subject = "Hello!"; - string message = "Message in plain text"; var recipient = new EmailAddress("recipient-1@getproffer.net", "Recipient"); var blackCarbonCopyRecipient = new EmailAddress("cc-recipient@getproffer.net", "Carbon-Copy Recipient"); - await this.emailSender.SendEmailAsync( - this.options.DefaultSender, - subject, - message, - Enumerable.Empty(), - new IEmailAddress[] { recipient }, - Array.Empty(), - new IEmailAddress[] { blackCarbonCopyRecipient }); - - this.fixture.Verify( - subject: subject, - bodyText: message, - bodyHtml: $"{subject}{message}", - recipients: new() { recipient }, - bccRecipients: new() { blackCarbonCopyRecipient }); + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, new List() { recipient }) + .AddBlackCarbonCopyRecipient(new List() { blackCarbonCopyRecipient }) + .AddSubject("Hello!") + .AddBodyText("Message in plain text"); + + await this.emailSender.SendEmailAsync(emailBuilder.Build()); + + emailBuilder.AddBodyHtml($"{emailBuilder.Build().Subject}{emailBuilder.Build().BodyText}"); + + this.fixture.Verify(emailBuilder.Build()); } [Fact] public async Task Should_SendEmailAsync_With_PlainTextOnly() { - string subject = "Hello!"; - string message = "Message in plain text"; var recipient = new EmailAddress("recipient-1@getproffer.net", "Recipient"); + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, new List() { recipient }) + .AddSubject("Hello!") + .AddBodyText("Message in plain text"); + + await this.emailSender.SendEmailAsync(emailBuilder.Build()); - await this.emailSender.SendEmailAsync( - this.options.DefaultSender, - this.options.DefaultSender, - subject, - message, - plainTextOnly: true, - recipient); - - this.fixture.Verify( - subject: subject, - bodyText: message, - recipients: new() { recipient }); + this.fixture.Verify(emailBuilder.Build()); } [Fact] public async Task Should_SendEmailAsync_With_ReplyTo() { - string subject = "Hello!"; - string message = "Message in plain text"; var recipient = new EmailAddress("recipient-1@getproffer.net", "Recipient"); var replyTo = new EmailAddress("custom-reply-to@getproffer.net", "Custom Reply-To"); - await this.emailSender.SendEmailAsync(this.options.DefaultSender, replyTo, subject, message, true, recipient); + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, new List() { recipient }) + .AddSubject("Hello!") + .AddBodyText("Message in plain text") + .AddReplyTo(replyTo); - this.fixture.Verify( - subject: subject, - bodyText: message, - recipients: new() { recipient }, - replyTo: replyTo); + await this.emailSender.SendEmailAsync(emailBuilder.Build()); + + this.fixture.Verify(emailBuilder.Build()); } [Fact] public async Task Should_SendEmailAsync_With_Sender() { - string subject = "Hello!"; - string message = "Message in plain text"; var recipient = new EmailAddress("recipient-1@getproffer.net", "Recipient"); var sender = new EmailAddress("custom-sender@getproffer.net", "Custom Sender"); - await this.emailSender.SendEmailAsync(sender, subject, message, recipient); + IEmailBuilder emailBuilder = new EmailBuilder(sender, new List() { recipient }) + .AddSubject("Hello!") + .AddBodyText("Message in plain text"); + + await this.emailSender.SendEmailAsync(emailBuilder.Build()); - this.fixture.Verify( - subject: subject, - bodyText: message, - recipients: new() { recipient }, - sender: sender); + this.fixture.Verify(emailBuilder.Build()); } [Fact] @@ -199,13 +169,16 @@ public async Task Should_SendTemplatedEmailAsync_With_KeyAndContext() var recipient = new EmailAddress("recipient-1@getproffer.net", context.Name); - await this.emailSender.SendTemplatedEmailAsync(templateKey, context, recipient); + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, new List() { recipient }) + .AddTemplate(templateKey); - this.fixture.Verify( - subject: $"Hello {context.Name}!", - bodyHtml: $"

{WebUtility.HtmlEncode(context.Title)}

{Environment.NewLine}{context.RawHtml}", - bodyText: $"{context.Title}{Environment.NewLine}{Environment.NewLine}{context.Message}", - recipients: new() { recipient }); + await this.emailSender.SendTemplatedEmailAsync(emailBuilder.Build(), context); + + emailBuilder.AddSubject($"Hello {context.Name}!") + .AddBodyHtml($"

{WebUtility.HtmlEncode(context.Title)}

{Environment.NewLine}{context.RawHtml}") + .AddBodyText($"{context.Title}{Environment.NewLine}{Environment.NewLine}{context.Message}"); + + this.fixture.Verify(emailBuilder.Build()); } [Fact] @@ -224,15 +197,17 @@ public async Task Should_SendTemplatedEmailAsync_With_SenderAndReplyTo() var replyTo = new EmailAddress("hello@getproffer.net", "Proffer"); var recipient = new EmailAddress("recipient-1@getproffer.net", context.Name); - await this.emailSender.SendTemplatedEmailAsync(sender, replyTo, templateKey, context, recipient); + IEmailBuilder emailBuilder = new EmailBuilder(sender, new List() { recipient }) + .AddTemplate(templateKey) + .AddReplyTo(replyTo); + + await this.emailSender.SendTemplatedEmailAsync(emailBuilder.Build(), context); + + emailBuilder.AddSubject($"Hello {context.Name}!") + .AddBodyHtml($"

{WebUtility.HtmlEncode(context.Title)}

{Environment.NewLine}{context.RawHtml}") + .AddBodyText($"{context.Title}{Environment.NewLine}{Environment.NewLine}{context.Message}"); - this.fixture.Verify( - subject: $"Hello {context.Name}!", - bodyHtml: $"

{WebUtility.HtmlEncode(context.Title)}

{Environment.NewLine}{context.RawHtml}", - bodyText: $"{context.Title}{Environment.NewLine}{Environment.NewLine}{context.Message}", - recipients: new() { recipient }, - sender: sender, - replyTo: replyTo); + this.fixture.Verify(emailBuilder.Build()); } public async Task DisposeAsync() diff --git a/tests/Proffer.Email.Smtp.Tests/SmtpFixture.cs b/tests/Proffer.Email.Smtp.Tests/SmtpFixture.cs index 6646373..06510a0 100644 --- a/tests/Proffer.Email.Smtp.Tests/SmtpFixture.cs +++ b/tests/Proffer.Email.Smtp.Tests/SmtpFixture.cs @@ -44,24 +44,15 @@ public SmtpFixture() public IStore Attachments { get; } - public void Verify( - IEmailAddress sender = null, - List recipients = null, - List ccRecipients = null, - List bccRecipients = null, - string subject = null, - string bodyText = null, - string bodyHtml = null, - List attachments = null, - IEmailAddress replyTo = null) + public void Verify(IEmail email) { IOptions options = this.Services.GetRequiredService>(); - sender ??= options.Value.DefaultSender; - recipients ??= new(); - ccRecipients ??= new(); - bccRecipients ??= new(); - attachments ??= new(); + email.From ??= options.Value.DefaultSender; + email.Recipients ??= new List(); + email.CcRecipients ??= new List(); + email.BccRecipients ??= new List(); + email.Attachments ??= new List(); EmailAddressStrictEqualityComparer emailStrictComparer = new(); EmailAddressEqualityComparer emailComparer = new(); @@ -84,15 +75,15 @@ bool attachmentsEqual(List expected, IEnumerable ToEmailAttachment(a)).ToList(); bool emailWasStored = this.emails - .Where(e => emailStrictComparer.Equals(sender, ToEmailAddress(e.From.FirstOrDefault()))) - .Where(e => emailsEqual(recipients, e.To.Select(t => ToEmailAddress(t)).ToList())) - .Where(e => emailsEqual(ccRecipients, e.Cc.Select(t => ToEmailAddress(t)).ToList())) - .Where(e => emailsEqual(bccRecipients, e.Bcc.Select(t => ToEmailAddress(t)).ToList(), emailComparer)) - .Where(e => subject == null || subject == e.Subject) - .Where(e => bodyText == null || bodyText == e.TextBody) - .Where(e => bodyHtml == null || bodyHtml == e.HtmlBody) - .Where(e => attachmentsEqual(attachments, e.Attachments.Select(a => ToEmailAttachment(a)).ToList())) - .Where(e => replyTo == null || emailStrictComparer.Equals(replyTo, ToEmailAddress(e.ReplyTo.FirstOrDefault()))) + .Where(e => emailStrictComparer.Equals(email.From, ToEmailAddress(e.From.FirstOrDefault()))) + .Where(e => emailsEqual(email.Recipients.ToList(), e.To.Select(t => ToEmailAddress(t)).ToList())) + .Where(e => emailsEqual(email.CcRecipients.ToList(), e.Cc.Select(t => ToEmailAddress(t)).ToList())) + .Where(e => emailsEqual(email.BccRecipients.ToList(), e.Bcc.Select(t => ToEmailAddress(t)).ToList(), emailComparer)) + .Where(e => email.Subject == null || email.Subject == e.Subject) + .Where(e => email.BodyText == null || email.BodyText == e.TextBody) + .Where(e => email.BodyHtml == null || email.BodyHtml == e.HtmlBody) + .Where(e => attachmentsEqual(email.Attachments.ToList(), e.Attachments.Select(a => ToEmailAttachment(a)).ToList())) + .Where(e => email.ReplyTo == null || emailStrictComparer.Equals(email.ReplyTo, ToEmailAddress(e.ReplyTo.FirstOrDefault()))) .Any(); Assert.True(emailWasStored); diff --git a/tests/Proffer.Email.Tests/EmailFixture.cs b/tests/Proffer.Email.Tests/EmailFixture.cs index 25a2bb3..9fb5f17 100644 --- a/tests/Proffer.Email.Tests/EmailFixture.cs +++ b/tests/Proffer.Email.Tests/EmailFixture.cs @@ -38,23 +38,15 @@ public EmailFixture(Dictionary inMemoryConfiguration = null) public IStore Attachments { get; private set; } public void Verify( - IEmailAddress sender = null, - List recipients = null, - List ccRecipients = null, - List bccRecipients = null, - string subject = null, - string bodyText = null, - string bodyHtml = null, - List attachments = null, - IEmailAddress replyTo = null) + IEmail email) { IOptions options = this.Services.GetRequiredService>(); - sender ??= options.Value.DefaultSender; - recipients ??= new(); - ccRecipients ??= new(); - bccRecipients ??= new(); - attachments ??= new(); + email.From ??= options.Value.DefaultSender; + email.Recipients ??= new List(); + email.CcRecipients ??= new List(); + email.BccRecipients ??= new List(); + email.Attachments ??= new List(); EmailAddressStrictEqualityComparer emailComparer = new(); EmailAttachmentEqualityComparer attachmentComparer = new(); @@ -75,17 +67,22 @@ public void Verify( return !firstNotSecond.Any() && !secondNotFirst.Any(); }; + IEmail compareEmail = new Email + { + Attachments = It.Is>(a => attachmentsEqual(email.Attachments.ToList(), a)), + BccRecipients = It.Is>(e => emailsEqual(email.BccRecipients.ToList(), e)), + BodyHtml = It.Is(bh => email.BodyHtml == null || email.BodyHtml == bh), + BodyText = It.Is(bt => email.BodyText == null || email.BodyText == bt), + CcRecipients = It.Is>(e => emailsEqual(email.CcRecipients.ToList(), e)), + From = It.Is(email.From, emailComparer), + Recipients = It.Is>(e => emailsEqual(email.Recipients.ToList(), e)), + ReplyTo = It.Is(e => email.ReplyTo == null || emailComparer.Equals(email.ReplyTo, e)), + Subject = It.Is(s => email.Subject == null || email.Subject == s) + }; + this.ProviderMock.Verify( p => p.SendEmailAsync( - It.Is(sender, emailComparer), - It.Is>(e => emailsEqual(recipients, e)), - It.Is>(e => emailsEqual(ccRecipients, e)), - It.Is>(e => emailsEqual(bccRecipients, e)), - It.Is(s => subject == null || subject == s), - It.Is(bt => bodyText == null || bodyText == bt), - It.Is(bh => bodyHtml == null || bodyHtml == bh), - It.Is>(a => attachmentsEqual(attachments, a)), - It.Is(e => replyTo == null || emailComparer.Equals(replyTo, e))), + It.Is(c => compareEmail == null || compareEmail == c)), Times.Once); } diff --git a/tests/Proffer.Email.Tests/EmailSenderTests.cs b/tests/Proffer.Email.Tests/EmailSenderTests.cs index d1e10d4..6a4c04b 100644 --- a/tests/Proffer.Email.Tests/EmailSenderTests.cs +++ b/tests/Proffer.Email.Tests/EmailSenderTests.cs @@ -83,148 +83,118 @@ public void Should_Throw_When_ResolvingUnknowTemplatesStore() [Fact] public async Task Should_SendEmailAsync() { - string subject = "Hello!"; - string message = "Message in plain text"; var recipient = new EmailAddress("recipient-1@getproffer.net", "Recipient"); + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, new List() { recipient }) + .AddSubject("Hello!") + .AddBodyText("Message in plain text"); - await this.emailSender.SendEmailAsync(subject, message, recipient); + await this.emailSender.SendEmailAsync(emailBuilder.Build()); - this.fixture.Verify( - subject: subject, - bodyText: message, - bodyHtml: $"{subject}{message}", - recipients: new() { recipient }); + emailBuilder.AddBodyHtml($"{emailBuilder.Build().Subject}{emailBuilder.Build().BodyText}"); + this.fixture.Verify(emailBuilder.Build()); } [Fact] public async Task Should_SendEmailAsync_With_Attachments() { - string subject = "Hello!"; - string message = "Message in plain text"; var recipient = new EmailAddress("recipient-1@getproffer.net", "Recipient"); - IFileReference beach = await this.fixture.Attachments.GetAsync("beach.jpeg", withMetadata: true); IFileReference sample = await this.fixture.Attachments.GetAsync("sample.pdf", withMetadata: true); - var attachments = new List - { - new EmailAttachment(beach.Path, await beach.ReadAllBytesAsync(), beach.Properties.ContentType), - new EmailAttachment(sample.Path, await sample.ReadAllBytesAsync(), sample.Properties.ContentType.Split('/')[0], sample.Properties.ContentType.Split('/')[1]), - }; + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, new List() { recipient }) + .AddSubject("Hello!") + .AddBodyText("Message in plain text") + .AddAttachment(new List + { + new EmailAttachment(beach.Path, await beach.ReadAllBytesAsync(), beach.Properties.ContentType), + new EmailAttachment(sample.Path, await sample.ReadAllBytesAsync(), sample.Properties.ContentType.Split('/')[0], sample.Properties.ContentType.Split('/')[1]), + }); + - await this.emailSender.SendEmailAsync(this.options.DefaultSender, subject, message, attachments, recipient); + await this.emailSender.SendEmailAsync(emailBuilder.Build()); + emailBuilder.AddBodyHtml($"{emailBuilder.Build().Subject}{emailBuilder.Build().BodyText}"); - this.fixture.Verify( - subject: subject, - bodyText: message, - bodyHtml: $"{subject}{message}", - recipients: new() { recipient }, - attachments: attachments); + this.fixture.Verify(emailBuilder.Build()); } [Fact] public async Task Should_SendEmailAsync_With_CarbonCopyRecipients() { - string subject = "Hello!"; - string message = "Message in plain text"; var recipient = new EmailAddress("recipient-1@getproffer.net", "Recipient"); var carbonCopyRecipient = new EmailAddress("cc-recipient@getproffer.net", "Carbon-Copy Recipient"); - await this.emailSender.SendEmailAsync( - this.options.DefaultSender, - subject, - message, - Enumerable.Empty(), - new IEmailAddress[] { recipient }, - new IEmailAddress[] { carbonCopyRecipient }, - Array.Empty()); - - this.fixture.Verify( - subject: subject, - bodyText: message, - bodyHtml: $"{subject}{message}", - recipients: new() { recipient }, - ccRecipients: new() { carbonCopyRecipient }); + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, new List() { recipient }) + .AddCarbonCopyRecipient(new List() { carbonCopyRecipient }) + .AddSubject("Hello!") + .AddBodyText("Message in plain text"); + + await this.emailSender.SendEmailAsync(emailBuilder.Build()); + + emailBuilder.AddBodyHtml($"{emailBuilder.Build().Subject}{emailBuilder.Build().BodyText}"); + + this.fixture.Verify(emailBuilder.Build()); } [Fact] public async Task Should_SendEmailAsync_With_BlackCarbonCopyRecipients() { - string subject = "Hello!"; - string message = "Message in plain text"; var recipient = new EmailAddress("recipient-1@getproffer.net", "Recipient"); var blackCarbonCopyRecipient = new EmailAddress("cc-recipient@getproffer.net", "Carbon-Copy Recipient"); - await this.emailSender.SendEmailAsync( - this.options.DefaultSender, - subject, - message, - Enumerable.Empty(), - new IEmailAddress[] { recipient }, - Array.Empty(), - new IEmailAddress[] { blackCarbonCopyRecipient }); - - this.fixture.Verify( - subject: subject, - bodyText: message, - bodyHtml: $"{subject}{message}", - recipients: new() { recipient }, - bccRecipients: new() { blackCarbonCopyRecipient }); + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, new List() { recipient }) + .AddBlackCarbonCopyRecipient(new List() { blackCarbonCopyRecipient }) + .AddSubject("Hello!") + .AddBodyText("Message in plain text"); + + await this.emailSender.SendEmailAsync(emailBuilder.Build()); + + emailBuilder.AddBodyHtml($"{emailBuilder.Build().Subject}{emailBuilder.Build().BodyText}"); + + this.fixture.Verify(emailBuilder.Build()); } [Fact] public async Task Should_SendEmailAsync_With_PlainTextOnly() { - string subject = "Hello!"; - string message = "Message in plain text"; var recipient = new EmailAddress("recipient-1@getproffer.net", "Recipient"); + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, new List() { recipient }) + .AddSubject("Hello!") + .AddBodyText("Message in plain text"); + + await this.emailSender.SendEmailAsync(emailBuilder.Build()); - await this.emailSender.SendEmailAsync( - this.options.DefaultSender, - this.options.DefaultSender, - subject, - message, - plainTextOnly: true, - recipient); - - this.fixture.Verify( - subject: subject, - bodyText: message, - recipients: new() { recipient }); + this.fixture.Verify(emailBuilder.Build()); } [Fact] public async Task Should_SendEmailAsync_With_ReplyTo() { - string subject = "Hello!"; - string message = "Message in plain text"; var recipient = new EmailAddress("recipient-1@getproffer.net", "Recipient"); var replyTo = new EmailAddress("custom-reply-to@getproffer.net", "Custom Reply-To"); - await this.emailSender.SendEmailAsync(this.options.DefaultSender, replyTo, subject, message, true, recipient); + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, new List() { recipient }) + .AddSubject("Hello!") + .AddBodyText("Message in plain text") + .AddReplyTo(replyTo); - this.fixture.Verify( - subject: subject, - bodyText: message, - recipients: new() { recipient }, - replyTo: replyTo); + await this.emailSender.SendEmailAsync(emailBuilder.Build()); + + this.fixture.Verify(emailBuilder.Build()); } [Fact] public async Task Should_SendEmailAsync_With_Sender() { - string subject = "Hello!"; - string message = "Message in plain text"; var recipient = new EmailAddress("recipient-1@getproffer.net", "Recipient"); var sender = new EmailAddress("custom-sender@getproffer.net", "Custom Sender"); - await this.emailSender.SendEmailAsync(sender, subject, message, recipient); + IEmailBuilder emailBuilder = new EmailBuilder(sender, new List() { recipient }) + .AddSubject("Hello!") + .AddBodyText("Message in plain text"); - this.fixture.Verify( - subject: subject, - bodyText: message, - recipients: new() { recipient }, - sender: sender); + await this.emailSender.SendEmailAsync(emailBuilder.Build()); + + this.fixture.Verify(emailBuilder.Build()); } [Fact] @@ -241,13 +211,16 @@ public async Task Should_SendTemplatedEmailAsync_With_KeyAndContext() var recipient = new EmailAddress("recipient-1@getproffer.net", context.Name); - await this.emailSender.SendTemplatedEmailAsync(templateKey, context, recipient); + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, new List() { recipient }) + .AddTemplate(templateKey); + + await this.emailSender.SendTemplatedEmailAsync(emailBuilder.Build(), context); - this.fixture.Verify( - subject: $"Hello {context.Name}!", - bodyHtml: $"

{WebUtility.HtmlEncode(context.Title)}

{Environment.NewLine}{context.RawHtml}", - bodyText: $"{context.Title}{Environment.NewLine}{Environment.NewLine}{context.Message}", - recipients: new() { recipient }); + emailBuilder.AddSubject($"Hello {context.Name}!") + .AddBodyHtml($"

{WebUtility.HtmlEncode(context.Title)}

{Environment.NewLine}{context.RawHtml}") + .AddBodyText($"{context.Title}{Environment.NewLine}{Environment.NewLine}{context.Message}"); + + this.fixture.Verify(emailBuilder.Build()); } [Fact] @@ -266,15 +239,17 @@ public async Task Should_SendTemplatedEmailAsync_With_SenderAndReplyTo() var replyTo = new EmailAddress("hello@getproffer.net", "Proffer"); var recipient = new EmailAddress("recipient-1@getproffer.net", context.Name); - await this.emailSender.SendTemplatedEmailAsync(sender, replyTo, templateKey, context, recipient); + IEmailBuilder emailBuilder = new EmailBuilder(sender, new List() { recipient }) + .AddTemplate(templateKey) + .AddReplyTo(replyTo); + + await this.emailSender.SendTemplatedEmailAsync(emailBuilder.Build(), context); + + emailBuilder.AddSubject($"Hello {context.Name}!") + .AddBodyHtml($"

{WebUtility.HtmlEncode(context.Title)}

{Environment.NewLine}{context.RawHtml}") + .AddBodyText($"{context.Title}{Environment.NewLine}{Environment.NewLine}{context.Message}"); - this.fixture.Verify( - subject: $"Hello {context.Name}!", - bodyHtml: $"

{WebUtility.HtmlEncode(context.Title)}

{Environment.NewLine}{context.RawHtml}", - bodyText: $"{context.Title}{Environment.NewLine}{Environment.NewLine}{context.Message}", - recipients: new() { recipient }, - sender: sender, - replyTo: replyTo); + this.fixture.Verify(emailBuilder.Build()); } [Fact] @@ -295,15 +270,17 @@ public async Task Should_SendEmailAsync_With_Mockup() string message = "Message in plain text"; var recipient = new EmailAddress("recipient-1@getproffer.net", "Recipient"); - await emailSender.SendEmailAsync(subject, message, recipient); + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, recipient.Yield()) + .AddSubject(subject) + .AddBodyText(message); + + await emailSender.SendEmailAsync(emailBuilder.Build()); + + emailBuilder.AddBodyText($"{message}{Environment.NewLine}{defaultDisclaimer}{Environment.NewLine}{recipient.DisplayName} ({recipient.Email})") + .AddBodyHtml($"{subject}{message}
{defaultDisclaimer}
{recipient.DisplayName} ({recipient.Email})
") + .AddRecipient(new EmailAddress(mockupEmail, "Mockup Recipient").Yield()); - fixture.Verify( - subject: subject, - bodyText: $"{message}{Environment.NewLine}{defaultDisclaimer}{Environment.NewLine}{recipient.DisplayName} ({recipient.Email})", - bodyHtml: $"{subject}{message}
{defaultDisclaimer}
{recipient.DisplayName} ({recipient.Email})
", - // TODO: [https://github.com/asiffermann/proffer/issues/102] Replace with the following - // bodyHtml: $"{subject}{message}
{defaultDisclaimer}
{recipient.DisplayName} ({recipient.Email})
", - recipients: new() { new EmailAddress(mockupEmail, "Mockup Recipient") }); + fixture.Verify(emailBuilder.Build()); } [Theory] @@ -329,7 +306,11 @@ public async Task Should_Throw_With_BadEmail(string badEmail) string message = "Message in plain text"; var recipient = new EmailAddress(badEmail, "Recipient"); - await Assert.ThrowsAsync(() => emailSender.SendEmailAsync(subject, message, recipient)); + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, recipient.Yield()) + .AddSubject(subject) + .AddBodyText(message); + + await Assert.ThrowsAsync(() => emailSender.SendEmailAsync(emailBuilder.Build())); } [Fact] @@ -349,10 +330,13 @@ public async Task Should_SendEmailAsync_With_MockupDomainException() string message = "Message in plain text"; var recipient = new EmailAddress("recipient-1@getproffer.net", "Recipient"); - await emailSender.SendEmailAsync(subject, message, recipient); + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, recipient.Yield()) + .AddSubject(subject) + .AddBodyText(message); + + await emailSender.SendEmailAsync(emailBuilder.Build()); - fixture.Verify( - recipients: new() { recipient }); + fixture.Verify(emailBuilder.Build()); } [Fact] @@ -374,10 +358,15 @@ public async Task Should_SendEmailAsync_With_MockupEmailException() string subject = "Hello!"; string message = "Message in plain text"; - await emailSender.SendEmailAsync(subject, message, firstRecipient, secondRecipient); + IEmailBuilder emailBuilder = new EmailBuilder(this.options.DefaultSender, new List { firstRecipient , secondRecipient}) + .AddSubject(subject) + .AddBodyText(message); + + await emailSender.SendEmailAsync(emailBuilder.Build()); + + emailBuilder.AddRecipient(new List { firstRecipient, new EmailAddress(mockupEmail, "Mockup Recipient") }); - fixture.Verify( - recipients: new() { firstRecipient, new EmailAddress(mockupEmail, "Mockup Recipient") }); + fixture.Verify(emailBuilder.Build()); } } } diff --git a/tests/Proffer.Email.Tests/Stubs/StubEmailProvider.cs b/tests/Proffer.Email.Tests/Stubs/StubEmailProvider.cs index 1c6849f..53c3cd0 100644 --- a/tests/Proffer.Email.Tests/Stubs/StubEmailProvider.cs +++ b/tests/Proffer.Email.Tests/Stubs/StubEmailProvider.cs @@ -1,18 +1,12 @@ namespace Proffer.Email.Tests.Stubs { using System; - using System.Collections.Generic; using System.Threading.Tasks; public class StubEmailProvider : IEmailProvider { - public Task SendEmailAsync(IEmailAddress from, IEnumerable recipients, string subject, string bodyText, string bodyHtml) - => throw new NotImplementedException(); - - public Task SendEmailAsync(IEmailAddress from, IEnumerable recipients, string subject, string bodyText, string bodyHtml, IEnumerable attachments) - => throw new NotImplementedException(); - public Task SendEmailAsync(IEmailAddress from, IEnumerable recipients, IEnumerable ccRecipients, IEnumerable bccRecipients, string subject, string bodyText, string bodyHtml, IEnumerable attachments, IEmailAddress replyTo = null) + public Task SendEmailAsync(IEmail email) => throw new NotImplementedException(); } }