From 51ec090c19f484faf97dcd43c2adab6c12b9a45f Mon Sep 17 00:00:00 2001
From: Francisco Molina <1440851+ur3an0@users.noreply.github.com>
Date: Wed, 27 May 2020 01:12:32 -0400
Subject: [PATCH 1/2] add support to mailgun templates
---
.gitignore | 1 +
src/FluentEmail.Core/Email.cs | 73 ++++++++++--
src/FluentEmail.Core/IFluentEmail.cs | 24 +++-
src/FluentEmail.Core/Models/EmailData.cs | 6 +
.../FluentEmail.Mailgun/MailgunSender.cs | 104 +++++++++++-------
5 files changed, 158 insertions(+), 50 deletions(-)
diff --git a/.gitignore b/.gitignore
index 83443355..e704f070 100644
--- a/.gitignore
+++ b/.gitignore
@@ -242,3 +242,4 @@ ModelManifest.xml
# FAKE - F# Make
.fake/
.vs
+/.idea/
diff --git a/src/FluentEmail.Core/Email.cs b/src/FluentEmail.Core/Email.cs
index fb20eab0..06c69a6e 100644
--- a/src/FluentEmail.Core/Email.cs
+++ b/src/FluentEmail.Core/Email.cs
@@ -41,8 +41,10 @@ public Email(ITemplateRenderer renderer, ISender sender)
///
/// Email address to send from
/// Name to send from
- public Email(string emailAddress, string name = "")
- : this(DefaultRenderer, DefaultSender, emailAddress, name) { }
+ public Email(string emailAddress, string name = "")
+ : this(DefaultRenderer, DefaultSender, emailAddress, name)
+ {
+ }
///
/// Creates a new Email instance using the given engines and mailing address.
@@ -57,6 +59,7 @@ public Email(ITemplateRenderer renderer, ISender sender, string emailAddress, st
{
FromAddress = new Address() {EmailAddress = emailAddress, Name = name}
};
+
Renderer = renderer;
Sender = sender;
}
@@ -86,6 +89,7 @@ public static IFluentEmail From(string emailAddress, string name = null)
public IFluentEmail SetFrom(string emailAddress, string name = null)
{
Data.FromAddress = new Address(emailAddress, name ?? "");
+
return this;
}
@@ -102,13 +106,16 @@ public IFluentEmail To(string emailAddress, string name = null)
//email address has semi-colon, try split
var nameSplit = name?.Split(';') ?? new string [0];
var addressSplit = emailAddress.Split(';');
+
for (int i = 0; i < addressSplit.Length; i++)
{
var currentName = string.Empty;
+
if ((nameSplit.Length - 1) >= i)
{
currentName = nameSplit[i];
}
+
Data.ToAddresses.Add(new Address(addressSplit[i].Trim(), currentName.Trim()));
}
}
@@ -116,6 +123,7 @@ public IFluentEmail To(string emailAddress, string name = null)
{
Data.ToAddresses.Add(new Address(emailAddress.Trim(), name?.Trim()));
}
+
return this;
}
@@ -152,6 +160,7 @@ public IFluentEmail To(IList mailAddresses)
{
Data.ToAddresses.Add(address);
}
+
return this;
}
@@ -164,6 +173,7 @@ public IFluentEmail To(IList mailAddresses)
public IFluentEmail CC(string emailAddress, string name = "")
{
Data.CcAddresses.Add(new Address(emailAddress, name));
+
return this;
}
@@ -178,6 +188,7 @@ public IFluentEmail CC(IList mailAddresses)
{
Data.CcAddresses.Add(address);
}
+
return this;
}
@@ -190,6 +201,7 @@ public IFluentEmail CC(IList mailAddresses)
public IFluentEmail BCC(string emailAddress, string name = "")
{
Data.BccAddresses.Add(new Address(emailAddress, name));
+
return this;
}
@@ -204,6 +216,7 @@ public IFluentEmail BCC(IList mailAddresses)
{
Data.BccAddresses.Add(address);
}
+
return this;
}
@@ -240,6 +253,7 @@ public IFluentEmail ReplyTo(string address, string name)
public IFluentEmail Subject(string subject)
{
Data.Subject = subject;
+
return this;
}
@@ -252,9 +266,10 @@ public IFluentEmail Body(string body, bool isHtml = false)
{
Data.IsHtml = isHtml;
Data.Body = body;
+
return this;
- }
-
+ }
+
///
/// Adds a Plaintext alternative Body to the Email. Used in conjunction with an HTML email,
/// this allows for email readers without html capability, and also helps avoid spam filters.
@@ -263,6 +278,7 @@ public IFluentEmail Body(string body, bool isHtml = false)
public IFluentEmail PlaintextAlternativeBody(string body)
{
Data.PlaintextAlternativeBody = body;
+
return this;
}
@@ -272,6 +288,7 @@ public IFluentEmail PlaintextAlternativeBody(string body)
public IFluentEmail HighPriority()
{
Data.Priority = Priority.High;
+
return this;
}
@@ -281,6 +298,7 @@ public IFluentEmail HighPriority()
public IFluentEmail LowPriority()
{
Data.Priority = Priority.Low;
+
return this;
}
@@ -290,6 +308,7 @@ public IFluentEmail LowPriority()
public IFluentEmail UsingTemplateEngine(ITemplateRenderer renderer)
{
Renderer = renderer;
+
return this;
}
@@ -329,7 +348,6 @@ public IFluentEmail PlaintextAlternativeUsingTemplateFromEmbedded(string path
return this;
}
-
///
/// Adds the template file to the email
///
@@ -385,6 +403,7 @@ public IFluentEmail PlaintextAlternativeUsingTemplateFromFile(string filename
public IFluentEmail UsingCultureTemplateFromFile(string filename, T model, CultureInfo culture, bool isHtml = true)
{
var cultureFile = GetCultureFileName(filename, culture);
+
return UsingTemplateFromFile(cultureFile, model, isHtml);
}
@@ -398,6 +417,7 @@ public IFluentEmail UsingCultureTemplateFromFile(string filename, T model, Cu
public IFluentEmail PlaintextAlternativeUsingCultureTemplateFromFile(string filename, T model, CultureInfo culture)
{
var cultureFile = GetCultureFileName(filename, culture);
+
return PlaintextAlternativeUsingTemplateFromFile(cultureFile, model);
}
@@ -457,18 +477,22 @@ public IFluentEmail Attach(IList attachments)
{
Data.Attachments.Add(attachment);
}
+
return this;
}
- public IFluentEmail AttachFromFilename(string filename, string contentType = null, string attachmentName = null)
+ public IFluentEmail AttachFromFilename(string filename, string contentType = null, string attachmentName = null)
{
var stream = File.OpenRead(filename);
- Attach(new Attachment()
- {
- Data = stream,
- Filename = attachmentName ?? filename,
- ContentType = contentType
- });
+
+ Attach(
+ new Attachment()
+ {
+ Data = stream,
+ Filename = attachmentName ?? filename,
+ ContentType = contentType
+ }
+ );
return this;
}
@@ -492,6 +516,30 @@ public IFluentEmail Header(string header, string body)
return this;
}
+ public IFluentEmail MailGunTemplate(string mailGunTemplate)
+ {
+ Data.MailGunTemplate = mailGunTemplate;
+
+ return this;
+ }
+
+ public IFluentEmail MailGunTemplateVar(string key, string value)
+ {
+ Data.MailGunTemplateVars.Add(key, value);
+
+ return this;
+ }
+
+ public IFluentEmail MailGunTemplateVar(Dictionary vars)
+ {
+ foreach (var var in vars)
+ {
+ Data.MailGunTemplateVars.Add(var.Key, var.Value);
+ }
+
+ return this;
+ }
+
///
/// Sends email synchronously
///
@@ -512,6 +560,7 @@ private static string GetCultureFileName(string fileName, CultureInfo culture)
var cultureExtension = string.Format("{0}{1}", culture.Name, extension);
var cultureFile = Path.ChangeExtension(fileName, cultureExtension);
+
if (File.Exists(cultureFile))
return cultureFile;
else
diff --git a/src/FluentEmail.Core/IFluentEmail.cs b/src/FluentEmail.Core/IFluentEmail.cs
index d0dfc65e..2ad14efe 100644
--- a/src/FluentEmail.Core/IFluentEmail.cs
+++ b/src/FluentEmail.Core/IFluentEmail.cs
@@ -241,5 +241,27 @@ public interface IFluentEmail: IHideObjectMembers
/// value of the header
/// Instance of the Email class
IFluentEmail Header(string header, string body);
- }
+
+ ///
+ /// Define mailgun template to use. Use this option, cause ignore body defined.
+ ///
+ /// Name of template to use.
+ /// Instance of the Email class
+ IFluentEmail MailGunTemplate(string mailGunTemplate);
+
+ ///
+ /// Adds mailgun template vars.
+ ///
+ /// Name of template var.
+ /// Value of template var.
+ /// Instance of the Email class
+ IFluentEmail MailGunTemplateVar(string key, string value);
+
+ ///
+ /// Adds mailgun template vars.
+ ///
+ /// List of template vars.
+ /// Instance of the Email class
+ IFluentEmail MailGunTemplateVar(Dictionary vars);
+ }
}
diff --git a/src/FluentEmail.Core/Models/EmailData.cs b/src/FluentEmail.Core/Models/EmailData.cs
index f1a4fb8c..42513b74 100644
--- a/src/FluentEmail.Core/Models/EmailData.cs
+++ b/src/FluentEmail.Core/Models/EmailData.cs
@@ -16,9 +16,13 @@ public class EmailData
public Priority Priority { get; set; }
public List Tags { get; set; }
+ public string MailGunTemplate { get; set; }
+
public bool IsHtml { get; set; }
public Dictionary Headers { get; set; }
+ public Dictionary MailGunTemplateVars { get; set; }
+
public EmailData()
{
ToAddresses = new List();
@@ -28,6 +32,8 @@ public EmailData()
Attachments = new List();
Tags = new List();
Headers = new Dictionary();
+ MailGunTemplate = string.Empty;
+ MailGunTemplateVars = new Dictionary();
}
}
}
diff --git a/src/Senders/FluentEmail.Mailgun/MailgunSender.cs b/src/Senders/FluentEmail.Mailgun/MailgunSender.cs
index 0c42044e..cb474158 100644
--- a/src/Senders/FluentEmail.Mailgun/MailgunSender.cs
+++ b/src/Senders/FluentEmail.Mailgun/MailgunSender.cs
@@ -24,18 +24,22 @@ public MailgunSender(string domainName, string apiKey, MailGunRegion mailGunRegi
_domainName = domainName;
_apiKey = apiKey;
string url = string.Empty;
- switch(mailGunRegion)
+
+ switch (mailGunRegion)
{
case MailGunRegion.USA:
url = $"https://api.mailgun.net/v3/{_domainName}/";
+
break;
case MailGunRegion.EU:
url = $"https://api.eu.mailgun.net/v3/{_domainName}/";
+
break;
default:
throw new ArgumentException($"'{mailGunRegion}' is not a valid value for {nameof(mailGunRegion)}");
}
+
_httpClient = new HttpClient()
{
BaseAddress = new Uri(url)
@@ -54,71 +58,97 @@ public async Task SendAsync(IFluentEmail email, CancellationToken?
var parameters = new List>();
parameters.Add(new KeyValuePair("from", $"{email.Data.FromAddress.Name} <{email.Data.FromAddress.EmailAddress}>"));
- email.Data.ToAddresses.ForEach(x => {
- parameters.Add(new KeyValuePair("to", $"{x.Name} <{x.EmailAddress}>"));
- });
- email.Data.CcAddresses.ForEach(x => {
- parameters.Add(new KeyValuePair("cc", $"{x.Name} <{x.EmailAddress}>"));
- });
- email.Data.BccAddresses.ForEach(x => {
- parameters.Add(new KeyValuePair("bcc", $"{x.Name} <{x.EmailAddress}>"));
- });
- email.Data.ReplyToAddresses.ForEach(x => {
- parameters.Add(new KeyValuePair("h:Reply-To", $"{x.Name} <{x.EmailAddress}>"));
- });
+ email.Data.ToAddresses.ForEach(x => { parameters.Add(new KeyValuePair("to", $"{x.Name} <{x.EmailAddress}>")); });
+ email.Data.CcAddresses.ForEach(x => { parameters.Add(new KeyValuePair("cc", $"{x.Name} <{x.EmailAddress}>")); });
+ email.Data.BccAddresses.ForEach(x => { parameters.Add(new KeyValuePair("bcc", $"{x.Name} <{x.EmailAddress}>")); });
+ email.Data.ReplyToAddresses.ForEach(x => { parameters.Add(new KeyValuePair("h:Reply-To", $"{x.Name} <{x.EmailAddress}>")); });
parameters.Add(new KeyValuePair("subject", email.Data.Subject));
- parameters.Add(new KeyValuePair(email.Data.IsHtml ? "html" : "text", email.Data.Body));
-
- if (!string.IsNullOrEmpty(email.Data.PlaintextAlternativeBody))
+ if (!string.IsNullOrEmpty(email.Data.MailGunTemplate))
{
- parameters.Add(new KeyValuePair("text", email.Data.PlaintextAlternativeBody));
+ parameters.Add(new KeyValuePair("template", email.Data.MailGunTemplate));
}
-
- email.Data.Tags.ForEach(x =>
+ else
{
- parameters.Add(new KeyValuePair("o:tag", x));
- });
+ parameters.Add(
+ new KeyValuePair(
+ email.Data.IsHtml ?
+ "html" :
+ "text",
+ email.Data.Body
+ )
+ );
+
+ if (!string.IsNullOrEmpty(email.Data.PlaintextAlternativeBody))
+ {
+ parameters.Add(new KeyValuePair("text", email.Data.PlaintextAlternativeBody));
+ }
+ }
+
+ email.Data.Tags.ForEach(x => { parameters.Add(new KeyValuePair("o:tag", x)); });
foreach (var emailHeader in email.Data.Headers)
{
var key = emailHeader.Key;
+
if (!key.StartsWith("h:"))
{
key = "h:" + emailHeader.Key;
}
- parameters.Add(new KeyValuePair(key, emailHeader.Value));
+ parameters.Add(new KeyValuePair(key, emailHeader.Value));
}
- var files = new List();
- email.Data.Attachments.ForEach(x =>
+ if (email.Data.MailGunTemplateVars.Any())
{
- string param;
+ var builder = new StringBuilder();
- if (x.IsInline)
- param = "inline";
- else
- param = "attachment";
+ builder.Append("{");
- files.Add(new HttpFile()
+ foreach (var var in email.Data.MailGunTemplateVars)
{
- ParameterName = param,
- Data = x.Data,
- Filename = x.Filename,
- ContentType = x.ContentType
- });
- });
+ builder.Append($"\"{var.Key}\":\"{var.Value}\"");
+ }
+
+ builder.Append("}");
+ parameters.Add(new KeyValuePair("h:X-Mailgun-Variables", builder.ToString()));
+ }
+
+ var files = new List();
+
+ email.Data.Attachments.ForEach(
+ x =>
+ {
+ string param;
+
+ if (x.IsInline)
+ param = "inline";
+ else
+ param = "attachment";
+
+ files.Add(
+ new HttpFile()
+ {
+ ParameterName = param,
+ Data = x.Data,
+ Filename = x.Filename,
+ ContentType = x.ContentType
+ }
+ );
+ }
+ );
var response = await _httpClient.PostMultipart("messages", parameters, files).ConfigureAwait(false);
var result = new SendResponse {MessageId = response.Data?.Id};
+
if (!response.Success)
{
result.ErrorMessages.AddRange(response.Errors.Select(x => x.ErrorMessage));
+
return result;
}
-
+
return result;
}
}
From d2ccbb905ab5dea57d7108d49d7b14cebcf9b2c9 Mon Sep 17 00:00:00 2001
From: Francisco Molina <1440851+ur3an0@users.noreply.github.com>
Date: Fri, 31 Jul 2020 22:30:16 -0400
Subject: [PATCH 2/2] mejora
---
src/Senders/FluentEmail.Mailgun/MailgunSender.cs | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/Senders/FluentEmail.Mailgun/MailgunSender.cs b/src/Senders/FluentEmail.Mailgun/MailgunSender.cs
index cb474158..a96ec0f8 100644
--- a/src/Senders/FluentEmail.Mailgun/MailgunSender.cs
+++ b/src/Senders/FluentEmail.Mailgun/MailgunSender.cs
@@ -103,15 +103,15 @@ public async Task SendAsync(IFluentEmail email, CancellationToken?
{
var builder = new StringBuilder();
- builder.Append("{");
-
foreach (var var in email.Data.MailGunTemplateVars)
{
builder.Append($"\"{var.Key}\":\"{var.Value}\"");
+ builder.Append(",");
}
- builder.Append("}");
- parameters.Add(new KeyValuePair("h:X-Mailgun-Variables", builder.ToString()));
+ var variables = $"{{{builder.ToString().Trim(',')}}}";
+
+ parameters.Add(new KeyValuePair("h:X-Mailgun-Variables", variables));
}
var files = new List();