diff --git a/Source/StrongGrid.IntegrationTests/Tests/Mail.cs b/Source/StrongGrid.IntegrationTests/Tests/Mail.cs index c52a1b07..980d200b 100644 --- a/Source/StrongGrid.IntegrationTests/Tests/Mail.cs +++ b/Source/StrongGrid.IntegrationTests/Tests/Mail.cs @@ -111,6 +111,7 @@ public async Task RunAsync(IBaseClient client, TextWriter log, CancellationToken customArgs: customArgs, mailSettings: mailSettings, trackingSettings: trackingSettings, + priority: MailPriority.High, cancellationToken: cancellationToken ).ConfigureAwait(false); await log.WriteLineAsync($"Email has been sent. Message Id: {messageId}").ConfigureAwait(false); diff --git a/Source/StrongGrid.UnitTests/StrongGrid.UnitTests.csproj b/Source/StrongGrid.UnitTests/StrongGrid.UnitTests.csproj index f7be1be2..028f2ba5 100644 --- a/Source/StrongGrid.UnitTests/StrongGrid.UnitTests.csproj +++ b/Source/StrongGrid.UnitTests/StrongGrid.UnitTests.csproj @@ -1,7 +1,7 @@ - net461;net472;net5.0 + net48;netcoreapp3.1;net5.0 StrongGrid.UnitTests StrongGrid.UnitTests diff --git a/Source/StrongGrid/Extensions/Public.cs b/Source/StrongGrid/Extensions/Public.cs index ba81e0e0..dd86bfa2 100644 --- a/Source/StrongGrid/Extensions/Public.cs +++ b/Source/StrongGrid/Extensions/Public.cs @@ -15,6 +15,608 @@ namespace StrongGrid /// public static class Public { + /// + /// Send an email to a single recipient without using a template (which means you must provide the subject, html content and text content). + /// + /// The mail resource. + /// To. + /// From. + /// The subject. + /// Content of the HTML. + /// Content of the text. + /// if set to true [track opens]. + /// if set to true [track clicks]. + /// The subscription tracking. + /// The reply to. + /// The attachments. + /// The sections. + /// The headers. + /// The categories. + /// The custom arguments. + /// The send at. + /// The batch identifier. + /// The unsubscribe options. + /// Name of the ip pool. + /// The mail settings. + /// The priority. + /// The cancellation token. + /// + /// The message id. + /// + /// + /// This overload is ideal when sending an email without using a template. + /// This is a convenience method with simplified parameters. + /// If you need more options, use the method. + /// + /// Too many recipients. + /// Email exceeds the size limit. + public static Task SendToSingleRecipientAsync( + this IMail mailResource, + MailAddress to, + MailAddress from, + string subject, + string htmlContent, + string textContent, + bool trackOpens = true, + bool trackClicks = true, + SubscriptionTrackingSettings subscriptionTracking = null, + MailAddress replyTo = null, + IEnumerable attachments = null, + IEnumerable> sections = null, + IEnumerable> headers = null, + IEnumerable categories = null, + IEnumerable> customArgs = null, + DateTime? sendAt = null, + string batchId = null, + UnsubscribeOptions unsubscribeOptions = null, + string ipPoolName = null, + MailSettings mailSettings = null, + MailPriority priority = MailPriority.Normal, + CancellationToken cancellationToken = default) + { + var recipients = new[] { to }; + return mailResource.SendToMultipleRecipientsAsync(recipients, from, subject, htmlContent, textContent, trackOpens, trackClicks, subscriptionTracking, replyTo, attachments, sections, headers, categories, customArgs, sendAt, batchId, unsubscribeOptions, ipPoolName, mailSettings, priority, cancellationToken); + } + + /// + /// Send an email to a single recipient using a legacy template. + /// + /// The mail resource. + /// To. + /// From. + /// The subject. + /// Content of the HTML. + /// Content of the text. + /// The template identifier. + /// Data to be merged in the content. + /// if set to true [track opens]. + /// if set to true [track clicks]. + /// The subscription tracking. + /// The reply to. + /// The attachments. + /// The sections. + /// The headers. + /// The categories. + /// The custom arguments. + /// The send at. + /// The batch identifier. + /// The unsubscribe options. + /// Name of the ip pool. + /// The mail settings. + /// The priority. + /// The cancellation token. + /// + /// The message id. + /// + /// + /// This is a convenience method with simplified parameters. + /// If you need more options, use the method. + /// + /// Too many recipients. + /// Email exceeds the size limit. + public static Task SendToSingleRecipientAsync( + this IMail mailResource, + MailAddress to, + MailAddress from, + string subject, + string htmlContent, + string textContent, + string templateId, + IEnumerable> substitutions = null, + bool trackOpens = true, + bool trackClicks = true, + SubscriptionTrackingSettings subscriptionTracking = null, + MailAddress replyTo = null, + IEnumerable attachments = null, + IEnumerable> sections = null, + IEnumerable> headers = null, + IEnumerable categories = null, + IEnumerable> customArgs = null, + DateTime? sendAt = null, + string batchId = null, + UnsubscribeOptions unsubscribeOptions = null, + string ipPoolName = null, + MailSettings mailSettings = null, + MailPriority priority = MailPriority.Normal, + CancellationToken cancellationToken = default) + { + var recipients = new[] { to }; + return mailResource.SendToMultipleRecipientsAsync(recipients, from, subject, htmlContent, textContent, templateId, substitutions, trackOpens, trackClicks, subscriptionTracking, replyTo, attachments, sections, headers, categories, customArgs, sendAt, batchId, unsubscribeOptions, ipPoolName, mailSettings, priority, cancellationToken); + } + + /// + /// Send an email to a single recipient using a dynamic template. + /// + /// The mail resource. + /// To. + /// From. + /// The identifier of the template. + /// The data to be merged in the content. + /// if set to true [track opens]. + /// if set to true [track clicks]. + /// The subscription tracking. + /// The reply to. + /// The attachments. + /// The sections. + /// The headers. + /// The categories. + /// The custom arguments. + /// The send at. + /// The batch identifier. + /// The unsubscribe options. + /// Name of the ip pool. + /// The mail settings. + /// The priority. + /// The cancellation token. + /// + /// The message id. + /// + /// + /// This is a convenience method with simplified parameters. + /// If you need more options, use the method. + /// + /// Too many recipients. + /// Email exceeds the size limit. + public static Task SendToSingleRecipientAsync( + this IMail mailResource, + MailAddress to, + MailAddress from, + string dynamicTemplateId, + object dynamicData = null, + bool trackOpens = true, + bool trackClicks = true, + SubscriptionTrackingSettings subscriptionTracking = null, + MailAddress replyTo = null, + IEnumerable attachments = null, + IEnumerable> sections = null, + IEnumerable> headers = null, + IEnumerable categories = null, + IEnumerable> customArgs = null, + DateTime? sendAt = null, + string batchId = null, + UnsubscribeOptions unsubscribeOptions = null, + string ipPoolName = null, + MailSettings mailSettings = null, + MailPriority priority = MailPriority.Normal, + CancellationToken cancellationToken = default) + { + var recipients = new[] { to }; + return mailResource.SendToMultipleRecipientsAsync(recipients, from, dynamicTemplateId, dynamicData, trackOpens, trackClicks, subscriptionTracking, replyTo, attachments, sections, headers, categories, customArgs, sendAt, batchId, unsubscribeOptions, ipPoolName, mailSettings, priority, cancellationToken); + } + + /// + /// Send an AMP email to a single recipient without using a template (which means you must provide the subject, html content and text content). + /// + /// The mail resource. + /// To. + /// From. + /// The subject. + /// Content of the AMP. + /// Content of the HTML. + /// Content of the text. + /// if set to true [track opens]. + /// if set to true [track clicks]. + /// The subscription tracking. + /// The reply to. + /// The attachments. + /// The sections. + /// The headers. + /// The categories. + /// The custom arguments. + /// The send at. + /// The batch identifier. + /// The unsubscribe options. + /// Name of the ip pool. + /// The mail settings. + /// The priority. + /// The cancellation token. + /// + /// The message id. + /// + /// + /// This overload is ideal when sending an email without using a template. + /// This is a convenience method with simplified parameters. + /// If you need more options, use the method. + /// + /// Too many recipients. + /// Email exceeds the size limit. + public static Task SendAmpEmailToSingleRecipientAsync( + this IMail mailResource, + MailAddress to, + MailAddress from, + string subject, + string ampContent, + string htmlContent, + string textContent, + bool trackOpens = true, + bool trackClicks = true, + SubscriptionTrackingSettings subscriptionTracking = null, + MailAddress replyTo = null, + IEnumerable attachments = null, + IEnumerable> sections = null, + IEnumerable> headers = null, + IEnumerable categories = null, + IEnumerable> customArgs = null, + DateTime? sendAt = null, + string batchId = null, + UnsubscribeOptions unsubscribeOptions = null, + string ipPoolName = null, + MailSettings mailSettings = null, + MailPriority priority = MailPriority.Normal, + CancellationToken cancellationToken = default) + { + var recipients = new[] { to }; + return mailResource.SendAmpEmailToMultipleRecipientsAsync(recipients, from, subject, ampContent, htmlContent, textContent, trackOpens, trackClicks, subscriptionTracking, replyTo, attachments, sections, headers, categories, customArgs, sendAt, batchId, unsubscribeOptions, ipPoolName, mailSettings, priority, cancellationToken); + } + + /// + /// Send the same email to multiple recipients without using a template (which means you must provide the subject, html content and text content). + /// + /// The mail resource. + /// The recipients. + /// From. + /// The subject. + /// Content of the HTML. + /// Content of the text. + /// if set to true [track opens]. + /// if set to true [track clicks]. + /// The subscription tracking. + /// The reply to. + /// The attachments. + /// The sections. + /// The headers. + /// The categories. + /// The custom arguments. + /// The send at. + /// The batch identifier. + /// The unsubscribe options. + /// Name of the ip pool. + /// The mail settings. + /// The priority. + /// The cancellation token. + /// + /// The message id. + /// + /// + /// This is a convenience method with simplified parameters. + /// If you need more options, use the method. + /// + /// Too many recipients. + /// Email exceeds the size limit. + public static Task SendToMultipleRecipientsAsync( + this IMail mailResource, + IEnumerable recipients, + MailAddress from, + string subject, + string htmlContent, + string textContent, + bool trackOpens = true, + bool trackClicks = true, + SubscriptionTrackingSettings subscriptionTracking = null, + MailAddress replyTo = null, + IEnumerable attachments = null, + IEnumerable> sections = null, + IEnumerable> headers = null, + IEnumerable categories = null, + IEnumerable> customArgs = null, + DateTime? sendAt = null, + string batchId = null, + UnsubscribeOptions unsubscribeOptions = null, + string ipPoolName = null, + MailSettings mailSettings = null, + MailPriority priority = MailPriority.Normal, + CancellationToken cancellationToken = default) + { + var personalizations = new[] + { + new MailPersonalization + { + To = recipients.ToArray() + } + }; + + var contents = new List(); + if (!string.IsNullOrEmpty(textContent)) contents.Add(new MailContent("text/plain", textContent)); + if (!string.IsNullOrEmpty(htmlContent)) contents.Add(new MailContent("text/html", htmlContent)); + + var trackingSettings = new TrackingSettings + { + ClickTracking = new ClickTrackingSettings + { + EnabledInHtmlContent = trackClicks, + EnabledInTextContent = trackClicks + }, + OpenTracking = new OpenTrackingSettings { Enabled = trackOpens }, + GoogleAnalytics = new GoogleAnalyticsSettings { Enabled = false }, + SubscriptionTracking = subscriptionTracking + }; + + return mailResource.SendAsync(personalizations, subject, contents, from, replyTo, attachments, null, sections, headers, categories, customArgs, sendAt, batchId, unsubscribeOptions, ipPoolName, mailSettings, trackingSettings, priority, cancellationToken); + } + + /// + /// Send the same email to multiple recipients using a legacy template. + /// + /// The mail resource. + /// The recipients. + /// From. + /// The subject. + /// Content of the HTML. + /// Content of the text. + /// The template identifier. + /// Data to be merged in the content. + /// if set to true [track opens]. + /// if set to true [track clicks]. + /// The subscription tracking. + /// The reply to. + /// The attachments. + /// The sections. + /// The headers. + /// The categories. + /// The custom arguments. + /// The send at. + /// The batch identifier. + /// The unsubscribe options. + /// Name of the ip pool. + /// The mail settings. + /// The priority. + /// The cancellation token. + /// + /// The message id. + /// + /// + /// This is a convenience method with simplified parameters. + /// If you need more options, use the method. + /// + /// Too many recipients. + /// Email exceeds the size limit. + public static Task SendToMultipleRecipientsAsync( + this IMail mailResource, + IEnumerable recipients, + MailAddress from, + string subject, + string htmlContent, + string textContent, + string templateId, + IEnumerable> substitutions = null, + bool trackOpens = true, + bool trackClicks = true, + SubscriptionTrackingSettings subscriptionTracking = null, + MailAddress replyTo = null, + IEnumerable attachments = null, + IEnumerable> sections = null, + IEnumerable> headers = null, + IEnumerable categories = null, + IEnumerable> customArgs = null, + DateTime? sendAt = null, + string batchId = null, + UnsubscribeOptions unsubscribeOptions = null, + string ipPoolName = null, + MailSettings mailSettings = null, + MailPriority priority = MailPriority.Normal, + CancellationToken cancellationToken = default) + { + var personalizations = new[] + { + new MailPersonalization + { + To = recipients.ToArray(), + Substitutions = substitutions?.ToArray() + } + }; + + var contents = new List(); + if (!string.IsNullOrEmpty(textContent)) contents.Add(new MailContent("text/plain", textContent)); + if (!string.IsNullOrEmpty(htmlContent)) contents.Add(new MailContent("text/html", htmlContent)); + + var trackingSettings = new TrackingSettings + { + ClickTracking = new ClickTrackingSettings + { + EnabledInHtmlContent = trackClicks, + EnabledInTextContent = trackClicks + }, + OpenTracking = new OpenTrackingSettings { Enabled = trackOpens }, + GoogleAnalytics = new GoogleAnalyticsSettings { Enabled = false }, + SubscriptionTracking = subscriptionTracking + }; + + return mailResource.SendAsync(personalizations, subject, contents, from, replyTo, attachments, templateId, sections, headers, categories, customArgs, sendAt, batchId, unsubscribeOptions, ipPoolName, mailSettings, trackingSettings, priority, cancellationToken); + } + + /// + /// Send the same email to multiple recipients. + /// + /// The mail resource. + /// The recipients. + /// From. + /// The identifier of the template. + /// The data to be merged in the content. + /// if set to true [track opens]. + /// if set to true [track clicks]. + /// The subscription tracking. + /// The reply to. + /// The attachments. + /// The sections. + /// The headers. + /// The categories. + /// The custom arguments. + /// The send at. + /// The batch identifier. + /// The unsubscribe options. + /// Name of the ip pool. + /// The mail settings. + /// The priority. + /// The cancellation token. + /// + /// The message id. + /// + /// + /// This is a convenience method with simplified parameters. + /// If you need more options, use the method. + /// + /// Too many recipients. + /// Email exceeds the size limit. + public static Task SendToMultipleRecipientsAsync( + this IMail mailResource, + IEnumerable recipients, + MailAddress from, + string dynamicTemplateId, + object dynamicData = null, + bool trackOpens = true, + bool trackClicks = true, + SubscriptionTrackingSettings subscriptionTracking = null, + MailAddress replyTo = null, + IEnumerable attachments = null, + IEnumerable> sections = null, + IEnumerable> headers = null, + IEnumerable categories = null, + IEnumerable> customArgs = null, + DateTime? sendAt = null, + string batchId = null, + UnsubscribeOptions unsubscribeOptions = null, + string ipPoolName = null, + MailSettings mailSettings = null, + MailPriority priority = MailPriority.Normal, + CancellationToken cancellationToken = default) + { + if (!Template.IsDynamic(dynamicTemplateId)) + { + throw new ArgumentException($"{dynamicTemplateId} is not a valid dynamic template identifier.", nameof(dynamicTemplateId)); + } + + var personalizations = new[] + { + new MailPersonalization + { + To = recipients.ToArray(), + DynamicData = dynamicData + } + }; + + var trackingSettings = new TrackingSettings + { + ClickTracking = new ClickTrackingSettings + { + EnabledInHtmlContent = trackClicks, + EnabledInTextContent = trackClicks + }, + OpenTracking = new OpenTrackingSettings { Enabled = trackOpens }, + GoogleAnalytics = new GoogleAnalyticsSettings { Enabled = false }, + SubscriptionTracking = subscriptionTracking + }; + + return mailResource.SendAsync(personalizations, null, null, from, replyTo, attachments, dynamicTemplateId, sections, headers, categories, customArgs, sendAt, batchId, unsubscribeOptions, ipPoolName, mailSettings, trackingSettings, priority, cancellationToken); + } + + /// + /// Send the same AMP email to multiple recipients. + /// + /// The mail resource. + /// The recipients. + /// From. + /// The subject. + /// Content of the AMP. + /// Content of the HTML. + /// Content of the text. + /// if set to true [track opens]. + /// if set to true [track clicks]. + /// The subscription tracking. + /// The reply to. + /// The attachments. + /// The sections. + /// The headers. + /// The categories. + /// The custom arguments. + /// The send at. + /// The batch identifier. + /// The unsubscribe options. + /// Name of the ip pool. + /// The mail settings. + /// The priority. + /// The cancellation token. + /// + /// The message id. + /// + /// + /// This is a convenience method with simplified parameters. + /// If you need more options, use the method. + /// + /// Too many recipients. + /// Email exceeds the size limit. + public static Task SendAmpEmailToMultipleRecipientsAsync( + this IMail mailResource, + IEnumerable recipients, + MailAddress from, + string subject, + string ampContent, + string htmlContent, + string textContent, + bool trackOpens = true, + bool trackClicks = true, + SubscriptionTrackingSettings subscriptionTracking = null, + MailAddress replyTo = null, + IEnumerable attachments = null, + IEnumerable> sections = null, + IEnumerable> headers = null, + IEnumerable categories = null, + IEnumerable> customArgs = null, + DateTime? sendAt = null, + string batchId = null, + UnsubscribeOptions unsubscribeOptions = null, + string ipPoolName = null, + MailSettings mailSettings = null, + MailPriority priority = MailPriority.Normal, + CancellationToken cancellationToken = default) + { + var personalizations = new[] + { + new MailPersonalization + { + To = recipients.ToArray() + } + }; + + var contents = new List(); + if (!string.IsNullOrEmpty(textContent)) contents.Add(new MailContent("text/plain", textContent)); + if (!string.IsNullOrEmpty(ampContent)) contents.Add(new MailContent("text/x-amp-html", ampContent)); + if (!string.IsNullOrEmpty(htmlContent)) contents.Add(new MailContent("text/html", htmlContent)); + + var trackingSettings = new TrackingSettings + { + ClickTracking = new ClickTrackingSettings + { + EnabledInHtmlContent = trackClicks, + EnabledInTextContent = trackClicks + }, + OpenTracking = new OpenTrackingSettings { Enabled = trackOpens }, + GoogleAnalytics = new GoogleAnalyticsSettings { Enabled = false }, + SubscriptionTracking = subscriptionTracking + }; + + return mailResource.SendAsync(personalizations, subject, contents, from, replyTo, attachments, null, sections, headers, categories, customArgs, sendAt, batchId, unsubscribeOptions, ipPoolName, mailSettings, trackingSettings, priority, cancellationToken); + } + /// /// Get all of the details about the messages matching the criteria. /// diff --git a/Source/StrongGrid/Resources/IMail.cs b/Source/StrongGrid/Resources/IMail.cs index fc93766c..3d111918 100644 --- a/Source/StrongGrid/Resources/IMail.cs +++ b/Source/StrongGrid/Resources/IMail.cs @@ -14,464 +14,6 @@ namespace StrongGrid.Resources /// public interface IMail { - /// - /// Send an email to a single recipient without using a template (which means you must provide the subject, html content and text content). - /// - /// To. - /// From. - /// The subject. - /// Content of the HTML. - /// Content of the text. - /// if set to true [track opens]. - /// if set to true [track clicks]. - /// The subscription tracking. - /// The reply to. - /// The attachments. - /// The sections. - /// The headers. - /// The categories. - /// The custom arguments. - /// The send at. - /// The batch identifier. - /// The unsubscribe options. - /// Name of the ip pool. - /// The mail settings. - /// The priority. - /// The cancellation token. - /// - /// The message id. - /// - /// - /// This overload is ideal when sending an email without using a template. - /// This is a convenience method with simplified parameters. - /// If you need more options, use the method. - /// - /// Too many recipients. - /// Email exceeds the size limit. - Task SendToSingleRecipientAsync( - MailAddress to, - MailAddress from, - string subject, - string htmlContent, - string textContent, - bool trackOpens = true, - bool trackClicks = true, - SubscriptionTrackingSettings subscriptionTracking = null, - MailAddress replyTo = null, - IEnumerable attachments = null, - IEnumerable> sections = null, - IEnumerable> headers = null, - IEnumerable categories = null, - IEnumerable> customArgs = null, - DateTime? sendAt = null, - string batchId = null, - UnsubscribeOptions unsubscribeOptions = null, - string ipPoolName = null, - MailSettings mailSettings = null, - MailPriority priority = MailPriority.Normal, - CancellationToken cancellationToken = default); - - /// - /// Send an email to a single recipient using a legacy template. - /// - /// To. - /// From. - /// The subject. - /// Content of the HTML. - /// Content of the text. - /// The template identifier. - /// Data to be merged in the content. - /// if set to true [track opens]. - /// if set to true [track clicks]. - /// The subscription tracking. - /// The reply to. - /// The attachments. - /// The sections. - /// The headers. - /// The categories. - /// The custom arguments. - /// The send at. - /// The batch identifier. - /// The unsubscribe options. - /// Name of the ip pool. - /// The mail settings. - /// The priority. - /// The cancellation token. - /// - /// The message id. - /// - /// - /// This is a convenience method with simplified parameters. - /// If you need more options, use the method. - /// - /// Too many recipients. - /// Email exceeds the size limit. - Task SendToSingleRecipientAsync( - MailAddress to, - MailAddress from, - string subject, - string htmlContent, - string textContent, - string templateId, - IEnumerable> substitutions = null, - bool trackOpens = true, - bool trackClicks = true, - SubscriptionTrackingSettings subscriptionTracking = null, - MailAddress replyTo = null, - IEnumerable attachments = null, - IEnumerable> sections = null, - IEnumerable> headers = null, - IEnumerable categories = null, - IEnumerable> customArgs = null, - DateTime? sendAt = null, - string batchId = null, - UnsubscribeOptions unsubscribeOptions = null, - string ipPoolName = null, - MailSettings mailSettings = null, - MailPriority priority = MailPriority.Normal, - CancellationToken cancellationToken = default); - - /// - /// Send an email to a single recipient using a dynamic template. - /// - /// To. - /// From. - /// The identifier of the template. - /// The data to be merged in the content. - /// if set to true [track opens]. - /// if set to true [track clicks]. - /// The subscription tracking. - /// The reply to. - /// The attachments. - /// The sections. - /// The headers. - /// The categories. - /// The custom arguments. - /// The send at. - /// The batch identifier. - /// The unsubscribe options. - /// Name of the ip pool. - /// The mail settings. - /// The priority. - /// The cancellation token. - /// - /// The message id. - /// - /// - /// This is a convenience method with simplified parameters. - /// If you need more options, use the method. - /// - /// Too many recipients. - /// Email exceeds the size limit. - Task SendToSingleRecipientAsync( - MailAddress to, - MailAddress from, - string dynamicTemplateId, - object dynamicData = null, - bool trackOpens = true, - bool trackClicks = true, - SubscriptionTrackingSettings subscriptionTracking = null, - MailAddress replyTo = null, - IEnumerable attachments = null, - IEnumerable> sections = null, - IEnumerable> headers = null, - IEnumerable categories = null, - IEnumerable> customArgs = null, - DateTime? sendAt = null, - string batchId = null, - UnsubscribeOptions unsubscribeOptions = null, - string ipPoolName = null, - MailSettings mailSettings = null, - MailPriority priority = MailPriority.Normal, - CancellationToken cancellationToken = default); - - /// - /// Send an AMP email to a single recipient without using a template (which means you must provide the subject, html content and text content). - /// - /// To. - /// From. - /// The subject. - /// Content of the AMP. - /// Content of the HTML. - /// Content of the text. - /// if set to true [track opens]. - /// if set to true [track clicks]. - /// The subscription tracking. - /// The reply to. - /// The attachments. - /// The sections. - /// The headers. - /// The categories. - /// The custom arguments. - /// The send at. - /// The batch identifier. - /// The unsubscribe options. - /// Name of the ip pool. - /// The mail settings. - /// The priority. - /// The cancellation token. - /// - /// The message id. - /// - /// - /// This overload is ideal when sending an email without using a template. - /// This is a convenience method with simplified parameters. - /// If you need more options, use the method. - /// - /// Too many recipients. - /// Email exceeds the size limit. - Task SendAmpEmailToSingleRecipientAsync( - MailAddress to, - MailAddress from, - string subject, - string ampContent, - string htmlContent, - string textContent, - bool trackOpens = true, - bool trackClicks = true, - SubscriptionTrackingSettings subscriptionTracking = null, - MailAddress replyTo = null, - IEnumerable attachments = null, - IEnumerable> sections = null, - IEnumerable> headers = null, - IEnumerable categories = null, - IEnumerable> customArgs = null, - DateTime? sendAt = null, - string batchId = null, - UnsubscribeOptions unsubscribeOptions = null, - string ipPoolName = null, - MailSettings mailSettings = null, - MailPriority priority = MailPriority.Normal, - CancellationToken cancellationToken = default); - - /// - /// Send the same email to multiple recipients without using a template (which means you must provide the subject, html content and text content). - /// - /// The recipients. - /// From. - /// The subject. - /// Content of the HTML. - /// Content of the text. - /// if set to true [track opens]. - /// if set to true [track clicks]. - /// The subscription tracking. - /// The reply to. - /// The attachments. - /// The sections. - /// The headers. - /// The categories. - /// The custom arguments. - /// The send at. - /// The batch identifier. - /// The unsubscribe options. - /// Name of the ip pool. - /// The mail settings. - /// The priority. - /// The cancellation token. - /// - /// The message id. - /// - /// - /// This is a convenience method with simplified parameters. - /// If you need more options, use the method. - /// - /// Too many recipients. - /// Email exceeds the size limit. - Task SendToMultipleRecipientsAsync( - IEnumerable recipients, - MailAddress from, - string subject, - string htmlContent, - string textContent, - bool trackOpens = true, - bool trackClicks = true, - SubscriptionTrackingSettings subscriptionTracking = null, - MailAddress replyTo = null, - IEnumerable attachments = null, - IEnumerable> sections = null, - IEnumerable> headers = null, - IEnumerable categories = null, - IEnumerable> customArgs = null, - DateTime? sendAt = null, - string batchId = null, - UnsubscribeOptions unsubscribeOptions = null, - string ipPoolName = null, - MailSettings mailSettings = null, - MailPriority priority = MailPriority.Normal, - CancellationToken cancellationToken = default); - - /// - /// Send the same email to multiple recipients using a legacy template. - /// - /// The recipients. - /// From. - /// The subject. - /// Content of the HTML. - /// Content of the text. - /// The template identifier. - /// Data to be merged in the content. - /// if set to true [track opens]. - /// if set to true [track clicks]. - /// The subscription tracking. - /// The reply to. - /// The attachments. - /// The sections. - /// The headers. - /// The categories. - /// The custom arguments. - /// The send at. - /// The batch identifier. - /// The unsubscribe options. - /// Name of the ip pool. - /// The mail settings. - /// The priority. - /// The cancellation token. - /// - /// The message id. - /// - /// - /// This is a convenience method with simplified parameters. - /// If you need more options, use the method. - /// - /// Too many recipients. - /// Email exceeds the size limit. - Task SendToMultipleRecipientsAsync( - IEnumerable recipients, - MailAddress from, - string subject, - string htmlContent, - string textContent, - string templateId, - IEnumerable> substitutions = null, - bool trackOpens = true, - bool trackClicks = true, - SubscriptionTrackingSettings subscriptionTracking = null, - MailAddress replyTo = null, - IEnumerable attachments = null, - IEnumerable> sections = null, - IEnumerable> headers = null, - IEnumerable categories = null, - IEnumerable> customArgs = null, - DateTime? sendAt = null, - string batchId = null, - UnsubscribeOptions unsubscribeOptions = null, - string ipPoolName = null, - MailSettings mailSettings = null, - MailPriority priority = MailPriority.Normal, - CancellationToken cancellationToken = default); - - /// - /// Send the same email to multiple recipients. - /// - /// The recipients. - /// From. - /// The identifier of the template. - /// The data to be merged in the content. - /// if set to true [track opens]. - /// if set to true [track clicks]. - /// The subscription tracking. - /// The reply to. - /// The attachments. - /// The sections. - /// The headers. - /// The categories. - /// The custom arguments. - /// The send at. - /// The batch identifier. - /// The unsubscribe options. - /// Name of the ip pool. - /// The mail settings. - /// The priority. - /// The cancellation token. - /// - /// The message id. - /// - /// - /// This is a convenience method with simplified parameters. - /// If you need more options, use the method. - /// - /// Too many recipients. - /// Email exceeds the size limit. - Task SendToMultipleRecipientsAsync( - IEnumerable recipients, - MailAddress from, - string dynamicTemplateId, - object dynamicData = null, - bool trackOpens = true, - bool trackClicks = true, - SubscriptionTrackingSettings subscriptionTracking = null, - MailAddress replyTo = null, - IEnumerable attachments = null, - IEnumerable> sections = null, - IEnumerable> headers = null, - IEnumerable categories = null, - IEnumerable> customArgs = null, - DateTime? sendAt = null, - string batchId = null, - UnsubscribeOptions unsubscribeOptions = null, - string ipPoolName = null, - MailSettings mailSettings = null, - MailPriority priority = MailPriority.Normal, - CancellationToken cancellationToken = default); - - /// - /// Send the same AMP email to multiple recipients without using a template (which means you must provide the subject, html content and text content). - /// - /// The recipients. - /// From. - /// The subject. - /// Content of the AMP. - /// Content of the HTML. - /// Content of the text. - /// if set to true [track opens]. - /// if set to true [track clicks]. - /// The subscription tracking. - /// The reply to. - /// The attachments. - /// The sections. - /// The headers. - /// The categories. - /// The custom arguments. - /// The send at. - /// The batch identifier. - /// The unsubscribe options. - /// Name of the ip pool. - /// The mail settings. - /// The priority. - /// The cancellation token. - /// - /// The message id. - /// - /// - /// This is a convenience method with simplified parameters. - /// If you need more options, use the method. - /// - /// Too many recipients. - /// Email exceeds the size limit. - Task SendAmpEmailToMultipleRecipientsAsync( - IEnumerable recipients, - MailAddress from, - string subject, - string ampContent, - string htmlContent, - string textContent, - bool trackOpens = true, - bool trackClicks = true, - SubscriptionTrackingSettings subscriptionTracking = null, - MailAddress replyTo = null, - IEnumerable attachments = null, - IEnumerable> sections = null, - IEnumerable> headers = null, - IEnumerable categories = null, - IEnumerable> customArgs = null, - DateTime? sendAt = null, - string batchId = null, - UnsubscribeOptions unsubscribeOptions = null, - string ipPoolName = null, - MailSettings mailSettings = null, - MailPriority priority = MailPriority.Normal, - CancellationToken cancellationToken = default); - /// /// Send email(s) over SendGrid’s v3 Web API. /// diff --git a/Source/StrongGrid/Resources/Mail.cs b/Source/StrongGrid/Resources/Mail.cs index b833fbc6..8493433b 100644 --- a/Source/StrongGrid/Resources/Mail.cs +++ b/Source/StrongGrid/Resources/Mail.cs @@ -24,601 +24,65 @@ public class Mail : IMail private const int MAX_EMAIL_SIZE = 30 * 1024 * 1024; private const string _endpoint = "mail"; - private readonly Pathoschild.Http.Client.IClient _client; - /// - /// Initializes a new instance of the class. - /// - /// The HTTP client. - internal Mail(Pathoschild.Http.Client.IClient client) + // The following values are documented here: https://docs.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxcmail/2bb19f1b-b35e-4966-b1cb-1afd044e83ab + // X-Priority: + // - a number from 1 to 5 where 1 corresponds to "high" and 5 corresponds to "low" + // Priority: + // - Urgent + // - Normal + // - Non-Urgent + // Importance: + // - High + // - Normal + // - Low + // X-MSMail-Priority: + // - High + // - Normal + // - Low + private static readonly IDictionary[]> _priorityHeaders = new Dictionary[]>() { - _client = client; - } - - /// - /// Send an email to a single recipient without using a template (which means you must provide the subject, html content and text content). - /// - /// To. - /// From. - /// The subject. - /// Content of the HTML. - /// Content of the text. - /// if set to true [track opens]. - /// if set to true [track clicks]. - /// The subscription tracking. - /// The reply to. - /// The attachments. - /// The sections. - /// The headers. - /// The categories. - /// The custom arguments. - /// The send at. - /// The batch identifier. - /// The unsubscribe options. - /// Name of the ip pool. - /// The mail settings. - /// The priority. - /// The cancellation token. - /// - /// The message id. - /// - /// - /// This overload is ideal when sending an email without using a template. - /// This is a convenience method with simplified parameters. - /// If you need more options, use the method. - /// - /// Too many recipients. - /// Email exceeds the size limit. - public Task SendToSingleRecipientAsync( - MailAddress to, - MailAddress from, - string subject, - string htmlContent, - string textContent, - bool trackOpens = true, - bool trackClicks = true, - SubscriptionTrackingSettings subscriptionTracking = null, - MailAddress replyTo = null, - IEnumerable attachments = null, - IEnumerable> sections = null, - IEnumerable> headers = null, - IEnumerable categories = null, - IEnumerable> customArgs = null, - DateTime? sendAt = null, - string batchId = null, - UnsubscribeOptions unsubscribeOptions = null, - string ipPoolName = null, - MailSettings mailSettings = null, - MailPriority priority = MailPriority.Normal, - CancellationToken cancellationToken = default) - { - var recipients = new[] { to }; - return SendToMultipleRecipientsAsync(recipients, from, subject, htmlContent, textContent, trackOpens, trackClicks, subscriptionTracking, replyTo, attachments, sections, headers, categories, customArgs, sendAt, batchId, unsubscribeOptions, ipPoolName, mailSettings, priority, cancellationToken); - } - - /// - /// Send an email to a single recipient using a legacy template. - /// - /// To. - /// From. - /// The subject. - /// Content of the HTML. - /// Content of the text. - /// The template identifier. - /// Data to be merged in the content. - /// if set to true [track opens]. - /// if set to true [track clicks]. - /// The subscription tracking. - /// The reply to. - /// The attachments. - /// The sections. - /// The headers. - /// The categories. - /// The custom arguments. - /// The send at. - /// The batch identifier. - /// The unsubscribe options. - /// Name of the ip pool. - /// The mail settings. - /// The priority. - /// The cancellation token. - /// - /// The message id. - /// - /// - /// This is a convenience method with simplified parameters. - /// If you need more options, use the method. - /// - /// Too many recipients. - /// Email exceeds the size limit. - public Task SendToSingleRecipientAsync( - MailAddress to, - MailAddress from, - string subject, - string htmlContent, - string textContent, - string templateId, - IEnumerable> substitutions = null, - bool trackOpens = true, - bool trackClicks = true, - SubscriptionTrackingSettings subscriptionTracking = null, - MailAddress replyTo = null, - IEnumerable attachments = null, - IEnumerable> sections = null, - IEnumerable> headers = null, - IEnumerable categories = null, - IEnumerable> customArgs = null, - DateTime? sendAt = null, - string batchId = null, - UnsubscribeOptions unsubscribeOptions = null, - string ipPoolName = null, - MailSettings mailSettings = null, - MailPriority priority = MailPriority.Normal, - CancellationToken cancellationToken = default) - { - var recipients = new[] { to }; - return SendToMultipleRecipientsAsync(recipients, from, subject, htmlContent, textContent, templateId, substitutions, trackOpens, trackClicks, subscriptionTracking, replyTo, attachments, sections, headers, categories, customArgs, sendAt, batchId, unsubscribeOptions, ipPoolName, mailSettings, priority, cancellationToken); - } - - /// - /// Send an email to a single recipient using a dynamic template. - /// - /// To. - /// From. - /// The identifier of the template. - /// The data to be merged in the content. - /// if set to true [track opens]. - /// if set to true [track clicks]. - /// The subscription tracking. - /// The reply to. - /// The attachments. - /// The sections. - /// The headers. - /// The categories. - /// The custom arguments. - /// The send at. - /// The batch identifier. - /// The unsubscribe options. - /// Name of the ip pool. - /// The mail settings. - /// The priority. - /// The cancellation token. - /// - /// The message id. - /// - /// - /// This is a convenience method with simplified parameters. - /// If you need more options, use the method. - /// - /// Too many recipients. - /// Email exceeds the size limit. - public Task SendToSingleRecipientAsync( - MailAddress to, - MailAddress from, - string dynamicTemplateId, - object dynamicData = null, - bool trackOpens = true, - bool trackClicks = true, - SubscriptionTrackingSettings subscriptionTracking = null, - MailAddress replyTo = null, - IEnumerable attachments = null, - IEnumerable> sections = null, - IEnumerable> headers = null, - IEnumerable categories = null, - IEnumerable> customArgs = null, - DateTime? sendAt = null, - string batchId = null, - UnsubscribeOptions unsubscribeOptions = null, - string ipPoolName = null, - MailSettings mailSettings = null, - MailPriority priority = MailPriority.Normal, - CancellationToken cancellationToken = default) - { - var recipients = new[] { to }; - return SendToMultipleRecipientsAsync(recipients, from, dynamicTemplateId, dynamicData, trackOpens, trackClicks, subscriptionTracking, replyTo, attachments, sections, headers, categories, customArgs, sendAt, batchId, unsubscribeOptions, ipPoolName, mailSettings, priority, cancellationToken); - } - - /// - /// Send an AMP email to a single recipient without using a template (which means you must provide the subject, html content and text content). - /// - /// To. - /// From. - /// The subject. - /// Content of the AMP. - /// Content of the HTML. - /// Content of the text. - /// if set to true [track opens]. - /// if set to true [track clicks]. - /// The subscription tracking. - /// The reply to. - /// The attachments. - /// The sections. - /// The headers. - /// The categories. - /// The custom arguments. - /// The send at. - /// The batch identifier. - /// The unsubscribe options. - /// Name of the ip pool. - /// The mail settings. - /// The priority. - /// The cancellation token. - /// - /// The message id. - /// - /// - /// This overload is ideal when sending an email without using a template. - /// This is a convenience method with simplified parameters. - /// If you need more options, use the method. - /// - /// Too many recipients. - /// Email exceeds the size limit. - public Task SendAmpEmailToSingleRecipientAsync( - MailAddress to, - MailAddress from, - string subject, - string ampContent, - string htmlContent, - string textContent, - bool trackOpens = true, - bool trackClicks = true, - SubscriptionTrackingSettings subscriptionTracking = null, - MailAddress replyTo = null, - IEnumerable attachments = null, - IEnumerable> sections = null, - IEnumerable> headers = null, - IEnumerable categories = null, - IEnumerable> customArgs = null, - DateTime? sendAt = null, - string batchId = null, - UnsubscribeOptions unsubscribeOptions = null, - string ipPoolName = null, - MailSettings mailSettings = null, - MailPriority priority = MailPriority.Normal, - CancellationToken cancellationToken = default) - { - var recipients = new[] { to }; - return SendAmpEmailToMultipleRecipientsAsync(recipients, from, subject, ampContent, htmlContent, textContent, trackOpens, trackClicks, subscriptionTracking, replyTo, attachments, sections, headers, categories, customArgs, sendAt, batchId, unsubscribeOptions, ipPoolName, mailSettings, priority, cancellationToken); - } - - /// - /// Send the same email to multiple recipients without using a template (which means you must provide the subject, html content and text content). - /// - /// The recipients. - /// From. - /// The subject. - /// Content of the HTML. - /// Content of the text. - /// if set to true [track opens]. - /// if set to true [track clicks]. - /// The subscription tracking. - /// The reply to. - /// The attachments. - /// The sections. - /// The headers. - /// The categories. - /// The custom arguments. - /// The send at. - /// The batch identifier. - /// The unsubscribe options. - /// Name of the ip pool. - /// The mail settings. - /// The priority. - /// The cancellation token. - /// - /// The message id. - /// - /// - /// This is a convenience method with simplified parameters. - /// If you need more options, use the method. - /// - /// Too many recipients. - /// Email exceeds the size limit. - public Task SendToMultipleRecipientsAsync( - IEnumerable recipients, - MailAddress from, - string subject, - string htmlContent, - string textContent, - bool trackOpens = true, - bool trackClicks = true, - SubscriptionTrackingSettings subscriptionTracking = null, - MailAddress replyTo = null, - IEnumerable attachments = null, - IEnumerable> sections = null, - IEnumerable> headers = null, - IEnumerable categories = null, - IEnumerable> customArgs = null, - DateTime? sendAt = null, - string batchId = null, - UnsubscribeOptions unsubscribeOptions = null, - string ipPoolName = null, - MailSettings mailSettings = null, - MailPriority priority = MailPriority.Normal, - CancellationToken cancellationToken = default) - { - var personalizations = new[] { - new MailPersonalization + MailPriority.High, + new[] { - To = recipients.ToArray() + new KeyValuePair("X-Priority", "1"), + new KeyValuePair("Priority", "urgent"), + new KeyValuePair("Importance", "high"), + new KeyValuePair("X-MSMail-Priority", "high") } - }; - - var contents = new List(); - if (!string.IsNullOrEmpty(textContent)) contents.Add(new MailContent("text/plain", textContent)); - if (!string.IsNullOrEmpty(htmlContent)) contents.Add(new MailContent("text/html", htmlContent)); - - var trackingSettings = new TrackingSettings - { - ClickTracking = new ClickTrackingSettings - { - EnabledInHtmlContent = trackClicks, - EnabledInTextContent = trackClicks - }, - OpenTracking = new OpenTrackingSettings { Enabled = trackOpens }, - GoogleAnalytics = new GoogleAnalyticsSettings { Enabled = false }, - SubscriptionTracking = subscriptionTracking - }; - - return SendAsync(personalizations, subject, contents, from, replyTo, attachments, null, sections, headers, categories, customArgs, sendAt, batchId, unsubscribeOptions, ipPoolName, mailSettings, trackingSettings, priority, cancellationToken); - } - - /// - /// Send the same email to multiple recipients using a legacy template. - /// - /// The recipients. - /// From. - /// The subject. - /// Content of the HTML. - /// Content of the text. - /// The template identifier. - /// Data to be merged in the content. - /// if set to true [track opens]. - /// if set to true [track clicks]. - /// The subscription tracking. - /// The reply to. - /// The attachments. - /// The sections. - /// The headers. - /// The categories. - /// The custom arguments. - /// The send at. - /// The batch identifier. - /// The unsubscribe options. - /// Name of the ip pool. - /// The mail settings. - /// The priority. - /// The cancellation token. - /// - /// The message id. - /// - /// - /// This is a convenience method with simplified parameters. - /// If you need more options, use the method. - /// - /// Too many recipients. - /// Email exceeds the size limit. - public Task SendToMultipleRecipientsAsync( - IEnumerable recipients, - MailAddress from, - string subject, - string htmlContent, - string textContent, - string templateId, - IEnumerable> substitutions = null, - bool trackOpens = true, - bool trackClicks = true, - SubscriptionTrackingSettings subscriptionTracking = null, - MailAddress replyTo = null, - IEnumerable attachments = null, - IEnumerable> sections = null, - IEnumerable> headers = null, - IEnumerable categories = null, - IEnumerable> customArgs = null, - DateTime? sendAt = null, - string batchId = null, - UnsubscribeOptions unsubscribeOptions = null, - string ipPoolName = null, - MailSettings mailSettings = null, - MailPriority priority = MailPriority.Normal, - CancellationToken cancellationToken = default) - { - var personalizations = new[] + }, { - new MailPersonalization + MailPriority.Normal, + new[] { - To = recipients.ToArray(), - Substitutions = substitutions?.ToArray() + new KeyValuePair("X-Priority", "3"), + new KeyValuePair("Priority", "normal"), + new KeyValuePair("Importance", "normal"), + new KeyValuePair("X-MSMail-Priority", "normal") } - }; - - var contents = new List(); - if (!string.IsNullOrEmpty(textContent)) contents.Add(new MailContent("text/plain", textContent)); - if (!string.IsNullOrEmpty(htmlContent)) contents.Add(new MailContent("text/html", htmlContent)); - - var trackingSettings = new TrackingSettings - { - ClickTracking = new ClickTrackingSettings - { - EnabledInHtmlContent = trackClicks, - EnabledInTextContent = trackClicks - }, - OpenTracking = new OpenTrackingSettings { Enabled = trackOpens }, - GoogleAnalytics = new GoogleAnalyticsSettings { Enabled = false }, - SubscriptionTracking = subscriptionTracking - }; - - return SendAsync(personalizations, subject, contents, from, replyTo, attachments, templateId, sections, headers, categories, customArgs, sendAt, batchId, unsubscribeOptions, ipPoolName, mailSettings, trackingSettings, priority, cancellationToken); - } - - /// - /// Send the same email to multiple recipients. - /// - /// The recipients. - /// From. - /// The identifier of the template. - /// The data to be merged in the content. - /// if set to true [track opens]. - /// if set to true [track clicks]. - /// The subscription tracking. - /// The reply to. - /// The attachments. - /// The sections. - /// The headers. - /// The categories. - /// The custom arguments. - /// The send at. - /// The batch identifier. - /// The unsubscribe options. - /// Name of the ip pool. - /// The mail settings. - /// The priority. - /// The cancellation token. - /// - /// The message id. - /// - /// - /// This is a convenience method with simplified parameters. - /// If you need more options, use the method. - /// - /// Too many recipients. - /// Email exceeds the size limit. - public Task SendToMultipleRecipientsAsync( - IEnumerable recipients, - MailAddress from, - string dynamicTemplateId, - object dynamicData = null, - bool trackOpens = true, - bool trackClicks = true, - SubscriptionTrackingSettings subscriptionTracking = null, - MailAddress replyTo = null, - IEnumerable attachments = null, - IEnumerable> sections = null, - IEnumerable> headers = null, - IEnumerable categories = null, - IEnumerable> customArgs = null, - DateTime? sendAt = null, - string batchId = null, - UnsubscribeOptions unsubscribeOptions = null, - string ipPoolName = null, - MailSettings mailSettings = null, - MailPriority priority = MailPriority.Normal, - CancellationToken cancellationToken = default) - { - if (!Template.IsDynamic(dynamicTemplateId)) - { - throw new ArgumentException($"{dynamicTemplateId} is not a valid dynamic template identifier.", nameof(dynamicTemplateId)); - } - - var personalizations = new[] + }, { - new MailPersonalization + MailPriority.Low, + new[] { - To = recipients.ToArray(), - DynamicData = dynamicData + new KeyValuePair("X-Priority", "5"), + new KeyValuePair("Priority", "non-urgent"), + new KeyValuePair("Importance", "low"), + new KeyValuePair("X-MSMail-Priority", "low") } - }; - - var trackingSettings = new TrackingSettings - { - ClickTracking = new ClickTrackingSettings - { - EnabledInHtmlContent = trackClicks, - EnabledInTextContent = trackClicks - }, - OpenTracking = new OpenTrackingSettings { Enabled = trackOpens }, - GoogleAnalytics = new GoogleAnalyticsSettings { Enabled = false }, - SubscriptionTracking = subscriptionTracking - }; + } + }; - return SendAsync(personalizations, null, null, from, replyTo, attachments, dynamicTemplateId, sections, headers, categories, customArgs, sendAt, batchId, unsubscribeOptions, ipPoolName, mailSettings, trackingSettings, priority, cancellationToken); - } + private readonly Pathoschild.Http.Client.IClient _client; /// - /// Send the same AMP email to multiple recipients. + /// Initializes a new instance of the class. /// - /// The recipients. - /// From. - /// The subject. - /// Content of the AMP. - /// Content of the HTML. - /// Content of the text. - /// if set to true [track opens]. - /// if set to true [track clicks]. - /// The subscription tracking. - /// The reply to. - /// The attachments. - /// The sections. - /// The headers. - /// The categories. - /// The custom arguments. - /// The send at. - /// The batch identifier. - /// The unsubscribe options. - /// Name of the ip pool. - /// The mail settings. - /// The priority. - /// The cancellation token. - /// - /// The message id. - /// - /// - /// This is a convenience method with simplified parameters. - /// If you need more options, use the method. - /// - /// Too many recipients. - /// Email exceeds the size limit. - public Task SendAmpEmailToMultipleRecipientsAsync( - IEnumerable recipients, - MailAddress from, - string subject, - string ampContent, - string htmlContent, - string textContent, - bool trackOpens = true, - bool trackClicks = true, - SubscriptionTrackingSettings subscriptionTracking = null, - MailAddress replyTo = null, - IEnumerable attachments = null, - IEnumerable> sections = null, - IEnumerable> headers = null, - IEnumerable categories = null, - IEnumerable> customArgs = null, - DateTime? sendAt = null, - string batchId = null, - UnsubscribeOptions unsubscribeOptions = null, - string ipPoolName = null, - MailSettings mailSettings = null, - MailPriority priority = MailPriority.Normal, - CancellationToken cancellationToken = default) + /// The HTTP client. + internal Mail(Pathoschild.Http.Client.IClient client) { - var personalizations = new[] - { - new MailPersonalization - { - To = recipients.ToArray() - } - }; - - var contents = new List(); - if (!string.IsNullOrEmpty(textContent)) contents.Add(new MailContent("text/plain", textContent)); - if (!string.IsNullOrEmpty(ampContent)) contents.Add(new MailContent("text/x-amp-html", ampContent)); - if (!string.IsNullOrEmpty(htmlContent)) contents.Add(new MailContent("text/html", htmlContent)); - - var trackingSettings = new TrackingSettings - { - ClickTracking = new ClickTrackingSettings - { - EnabledInHtmlContent = trackClicks, - EnabledInTextContent = trackClicks - }, - OpenTracking = new OpenTrackingSettings { Enabled = trackOpens }, - GoogleAnalytics = new GoogleAnalyticsSettings { Enabled = false }, - SubscriptionTracking = subscriptionTracking - }; - - return SendAsync(personalizations, subject, contents, from, replyTo, attachments, null, sections, headers, categories, customArgs, sendAt, batchId, unsubscribeOptions, ipPoolName, mailSettings, trackingSettings, priority, cancellationToken); + _client = client; } /// @@ -724,7 +188,7 @@ public async Task SendAsync( var numberOfRecipients = personalizationsCopy.Sum(p => p.To?.Count(r => r != null) ?? 0); numberOfRecipients += personalizationsCopy.Sum(p => p.Cc?.Count(r => r != null) ?? 0); numberOfRecipients += personalizationsCopy.Sum(p => p.Bcc?.Count(r => r != null) ?? 0); - if (numberOfRecipients >= 1000) throw new ArgumentOutOfRangeException("The total number of recipients must be less than 1000"); + if (numberOfRecipients >= 1000) throw new ArgumentOutOfRangeException(nameof(numberOfRecipients), numberOfRecipients, "The total number of recipients must be less than 1000"); // SendGrid throws an unhelpful error when the Bcc email address is an empty string if (mailSettings?.Bcc != null && string.IsNullOrWhiteSpace(mailSettings.Bcc.EmailAddress)) @@ -762,25 +226,13 @@ public async Task SendAsync( data.Add("sections", sctns); } - if (priority == MailPriority.Low) + if (_priorityHeaders.TryGetValue(priority, out KeyValuePair[] priorityHeaders)) { - var lowPriorityHeaders = new KeyValuePair[] - { - new KeyValuePair("X-Priority", "5"), - new KeyValuePair("Priority", "non-urgent"), - new KeyValuePair("Importance", "low") - }; - headers = headers == null ? lowPriorityHeaders : headers.Concat(lowPriorityHeaders); + headers = (headers ?? Array.Empty>()).Concat(priorityHeaders); } - else if (priority == MailPriority.High) + else { - var highPriorityHeaders = new KeyValuePair[] - { - new KeyValuePair("X-Priority", "1"), - new KeyValuePair("Priority", "urgent"), - new KeyValuePair("Importance", "high") - }; - headers = headers == null ? highPriorityHeaders : headers.Concat(highPriorityHeaders); + throw new Exception($"{priority} is an unknown priority"); } if (headers != null && headers.Any()) diff --git a/Source/StrongGrid/StrongGrid.csproj b/Source/StrongGrid/StrongGrid.csproj index 3657ffb8..dc0ec3a3 100644 --- a/Source/StrongGrid/StrongGrid.csproj +++ b/Source/StrongGrid/StrongGrid.csproj @@ -1,7 +1,7 @@ - net461;net472;netstandard2.0;net5.0 + net48;netstandard2.1;net5.0 anycpu true Library @@ -53,7 +53,6 @@ - diff --git a/Source/StrongGrid/Utilities/Utils.cs b/Source/StrongGrid/Utilities/Utils.cs index 8d02f510..88a05a84 100644 --- a/Source/StrongGrid/Utilities/Utils.cs +++ b/Source/StrongGrid/Utilities/Utils.cs @@ -10,35 +10,9 @@ namespace StrongGrid.Utilities internal static class Utils { private static readonly byte[] Secp256R1Prefix = Convert.FromBase64String("MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE"); - private static readonly byte[] CngBlobPrefix = { 0x45, 0x43, 0x53, 0x31, 0x20, 0, 0, 0 }; public static RecyclableMemoryStreamManager MemoryStreamManager { get; } = new RecyclableMemoryStreamManager(); - /// - /// Converts a secp256r1/NIST P-256 public key. - /// - /// The public key. - /// The converted public key. - /// - /// From https://stackoverflow.com/questions/44502331/c-sharp-get-cngkey-object-from-public-key-in-text-file/44527439#44527439 . - /// - public static byte[] ConvertSecp256R1PublicKeyToEccPublicBlob(byte[] subjectPublicKeyInfo) - { - if (subjectPublicKeyInfo.Length != 91) - throw new InvalidOperationException(); - - var prefix = Secp256R1Prefix; - - if (!subjectPublicKeyInfo.Take(prefix.Length).SequenceEqual(prefix)) - throw new InvalidOperationException(); - - var cngBlob = new byte[CngBlobPrefix.Length + 64]; - Buffer.BlockCopy(CngBlobPrefix, 0, cngBlob, 0, CngBlobPrefix.Length); - Buffer.BlockCopy(subjectPublicKeyInfo, Secp256R1Prefix.Length, cngBlob, CngBlobPrefix.Length, 64); - - return cngBlob; - } - /// /// Get the 'x' and 'y' values from a secp256r1/NIST P-256 public key. /// diff --git a/Source/StrongGrid/WebhookParser.cs b/Source/StrongGrid/WebhookParser.cs index 9699f4da..817fb24d 100644 --- a/Source/StrongGrid/WebhookParser.cs +++ b/Source/StrongGrid/WebhookParser.cs @@ -109,9 +109,6 @@ public Event[] ParseSignedEventsWebhook(string requestBody, string publicKey, st The 'ECDsa.ImportSubjectPublicKeyInfo' method was introduced in .NET core 3.0 and the DSASignatureFormat enum was introduced in .NET 5.0. - We can get rid of the code that relies on ECDsaCng and remove reference to - System.Security.Cryptography.Cng in csproj when we drop support for net461. - We can get rid of the 'ConvertECDSASignature' class and the Utils methods that convert public keys when we stop suporting .NET framework and .NET standard. @@ -120,10 +117,6 @@ NET5_0_OR_GREATER was added to the NET SDK very recently and works fine on on their Ubuntu image because it's still on NET SDK 5.0.101. That's why I added the seemingly redundant "NET5_0" in the conditional block below. It will be safe to remove it when the SDK in AppVeyor's Ubuntu image is upgraded. - - Note: - ECDsa is cross-platform and can be used on Windows and Linux/Ubuntu. - ECDsaCng is Windows only. */ #if NET5_0 || NET5_0_OR_GREATER @@ -131,7 +124,7 @@ ECDsaCng is Windows only. var eCDsa = ECDsa.Create(); eCDsa.ImportSubjectPublicKeyInfo(publicKeyBytes, out _); var verified = eCDsa.VerifyData(data, signatureBytes, HashAlgorithmName.SHA256, DSASignatureFormat.Rfc3279DerSequence); -#elif NET472_OR_GREATER || NETSTANDARD2_0 +#elif NET48_OR_GREATER || NETSTANDARD2_1 // Convert the signature and public key provided by SendGrid into formats usable by the ECDsa .net crypto class var sig = ConvertECDSASignature.LightweightConvertSignatureFromX9_62ToISO7816_8(256, signatureBytes); var (x, y) = Utils.GetXYFromSecp256r1PublicKey(publicKeyBytes); @@ -148,15 +141,6 @@ ECDsaCng is Windows only. } }); var verified = eCDsa.VerifyData(data, sig, HashAlgorithmName.SHA256); -#elif NETFRAMEWORK - // Convert the signature and public key provided by SendGrid into formats usable by the ECDsaCng .net crypto class - var sig = ConvertECDSASignature.LightweightConvertSignatureFromX9_62ToISO7816_8(256, signatureBytes); - var cngBlob = Utils.ConvertSecp256R1PublicKeyToEccPublicBlob(publicKeyBytes); - - // Verify the signature - var cngKey = CngKey.Import(cngBlob, CngKeyBlobFormat.EccPublicBlob); - var eCDsaCng = new ECDsaCng(cngKey); - var verified = eCDsaCng.VerifyData(data, sig); #else #error Unhandled TFM #endif