From 4f646be0ee66067a1d8feec4a0aa90400dae9bc2 Mon Sep 17 00:00:00 2001 From: Stanislav Diakovskyi Date: Fri, 18 Dec 2020 08:12:59 +0200 Subject: [PATCH 1/5] adds missing properties for the template and templatedetailcontent resources --- Mailjet.Client/Resources/Template.cs | 10 ++++++++++ Mailjet.Client/Resources/TemplateDetailcontent.cs | 5 +++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Mailjet.Client/Resources/Template.cs b/Mailjet.Client/Resources/Template.cs index 619ece4..ada039e 100644 --- a/Mailjet.Client/Resources/Template.cs +++ b/Mailjet.Client/Resources/Template.cs @@ -21,11 +21,21 @@ public static class Template public const string APIKey = "APIKey"; public const string CategoriesSelectionMethod = "CategoriesSelectionMethod"; public const string PurposesSelectionMethod = "PurposesSelectionMethod"; + public const string IsTextPartGenerationEnabled = "IsTextPartGenerationEnabled"; public const string User = "User"; public const string Limit = "Limit"; public const string Offset = "Offset"; public const string Sort = "Sort"; public const string CountOnly = "CountOnly"; + + public const long EditModeValue_DNDBuilder = 1; + public const long EditModeValue_HTMLBuilder = 2; + public const long EditModeValue_SavedSectionBuilder = 3; + public const long EditModeValue_MJMLBuilder = 4; + + public const string OwnerTypeValue_Apikey = "apikey"; + public const string OwnerTypeValue_User = "user"; + public const string OwnerTypeValue_Global = "global"; } } diff --git a/Mailjet.Client/Resources/TemplateDetailcontent.cs b/Mailjet.Client/Resources/TemplateDetailcontent.cs index 2fba99a..e309fb1 100644 --- a/Mailjet.Client/Resources/TemplateDetailcontent.cs +++ b/Mailjet.Client/Resources/TemplateDetailcontent.cs @@ -8,7 +8,8 @@ public static class TemplateDetailcontent public const string Htmlpart = "Html-part"; public const string MJMLContent = "MJMLContent"; public const string Headers = "Headers"; + public const string From = "From"; + public const string Subject = "Subject"; + public const string ReplyTo = "Reply-to"; } } - - From 9b42f5388ede95b8c7faac233b831120434e435c Mon Sep 17 00:00:00 2001 From: Stanislav Diakovskyi Date: Fri, 18 Dec 2020 08:14:19 +0200 Subject: [PATCH 2/5] Fixes sending a templated email with the default sender from the template. Adds possibility to set the whole variables dictionary directly. --- .../Models/TransactionalEmail.cs | 2 +- .../TransactionalEmailBuilder.cs | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Mailjet.Client/TransactionalEmails/Models/TransactionalEmail.cs b/Mailjet.Client/TransactionalEmails/Models/TransactionalEmail.cs index 4b39be9..db86861 100644 --- a/Mailjet.Client/TransactionalEmails/Models/TransactionalEmail.cs +++ b/Mailjet.Client/TransactionalEmails/Models/TransactionalEmail.cs @@ -32,6 +32,6 @@ public class TransactionalEmail public string URLTags { get; set; } public Dictionary Headers { get; set; } - public Dictionary Variables { get; set; } + public IDictionary Variables { get; set; } } } \ No newline at end of file diff --git a/Mailjet.Client/TransactionalEmails/TransactionalEmailBuilder.cs b/Mailjet.Client/TransactionalEmails/TransactionalEmailBuilder.cs index 5214538..4f22ec0 100644 --- a/Mailjet.Client/TransactionalEmails/TransactionalEmailBuilder.cs +++ b/Mailjet.Client/TransactionalEmails/TransactionalEmailBuilder.cs @@ -34,7 +34,7 @@ public class TransactionalEmailBuilder private string _urlTags; private Dictionary _headers; - private Dictionary _variables; + private IDictionary _variables; /// /// The email subject line @@ -393,6 +393,18 @@ public TransactionalEmailBuilder WithVariable(string variableName, object variab return this; } + /// + /// Adds dictionary with variables used to modify the content of your email. + /// Enter the information in the template text / HTML part by using the [[var:{var_name}]] format. + /// Equivalent of using X-MJ-Vars header through SMTP. + /// + public TransactionalEmailBuilder WithVariables(IDictionary variables) + { + _variables = variables; + + return this; + } + /// /// Builds the mail message /// @@ -435,6 +447,7 @@ public TransactionalEmail Build() /// with single preconfigured builder instance /// performs the deep clone of the current builder instance /// + /// Clone creates a deep clone of the builder itself, but does not clone passed variables public TransactionalEmailBuilder Clone() { var result = (TransactionalEmailBuilder) MemberwiseClone(); @@ -459,7 +472,8 @@ public TransactionalEmailBuilder Clone() private void Validate() { - if (_from == null) + // template could have a default sender, so in case of using template we should allow sending w/o sender specified + if (_from == null && _templateId == null) throw new MailjetClientConfigurationException("From field should be specified"); if (string.IsNullOrEmpty(_textPart) && From 4b90e05525f62ac95b69c7be649c1159ca293b04 Mon Sep 17 00:00:00 2001 From: Stanislav Diakovskyi Date: Fri, 18 Dec 2020 08:14:51 +0200 Subject: [PATCH 3/5] Adds integration test for sending an email from the template with variables --- .../Integration/TemplateIntegrationTests.cs | 191 ++++++++++++++++++ Mailjet.Tests/Mailjet.Tests.csproj | 10 + Mailjet.Tests/Resources/MJMLTemplate.mjml | 41 ++++ 3 files changed, 242 insertions(+) create mode 100644 Mailjet.Tests/Integration/TemplateIntegrationTests.cs create mode 100644 Mailjet.Tests/Resources/MJMLTemplate.mjml diff --git a/Mailjet.Tests/Integration/TemplateIntegrationTests.cs b/Mailjet.Tests/Integration/TemplateIntegrationTests.cs new file mode 100644 index 0000000..64699dd --- /dev/null +++ b/Mailjet.Tests/Integration/TemplateIntegrationTests.cs @@ -0,0 +1,191 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Mailjet.Client; +using Mailjet.Client.Resources; +using Mailjet.Client.TransactionalEmails; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Newtonsoft.Json.Linq; + +namespace Mailjet.Tests.Integration +{ + [TestClass] + public class TemplateIntegrationTests + { + private MailjetClient _client; + private string _senderEmail; + + [TestInitialize] + public async Task TestInitialize() + { + _client = new MailjetClient(Environment.GetEnvironmentVariable("MJ_APIKEY_PUBLIC"), + Environment.GetEnvironmentVariable("MJ_APIKEY_PRIVATE")); + + _senderEmail = await GetValidSenderEmail(_client); + } + + [TestMethod] + public async Task SendTransactionalEmailAsync_SendsEmail() + { + + MailjetRequest request = new MailjetRequest + { + Resource = TemplateDetailcontent.Resource, + ResourceId = ResourceId.Numeric(2095787) + }; + + var resp = await _client.GetAsync(request); + + + + long templateId = await CreateTemplate(); + + Assert.IsTrue(templateId > 0); + + await FillTemplateContent(templateId); + + await SendEmailWithTemplate(templateId); + + await DeleteTemplate(templateId); + } + + private async Task DeleteTemplate(long templateId) + { + // arrange + MailjetRequest request = new MailjetRequest + { + Resource = Template.Resource, + ResourceId = ResourceId.Numeric(templateId) + }; + + // act + MailjetResponse response = await _client.DeleteAsync(request); + + // assert + Assert.AreEqual(204, response.StatusCode); + } + + private async Task FillTemplateContent(long templateId) + { + // arrange + var content = File.ReadAllText(@"Resources\MJMLTemplate.mjml"); + + MailjetRequest request = new MailjetRequest + { + Resource = TemplateDetailcontent.Resource, + ResourceId = ResourceId.Numeric(templateId) + } + .Property(TemplateDetailcontent.MJMLContent, content) + .Property(TemplateDetailcontent.Headers, JObject.FromObject(new Dictionary() + { + {"Subject", "Test transactional template subject " + DateTime.UtcNow}, + {"SenderName", "Test transactional template"}, + {"SenderEmail", _senderEmail}, + {"From", _senderEmail}, + })); + + // act + MailjetResponse response = await _client.PostAsync(request); + + // assert + Assert.IsTrue(response.IsSuccessStatusCode); + Assert.AreEqual(1, response.GetTotal()); + Assert.AreEqual(content, response.GetData().Single().Value("MJMLContent")); + } + + private async Task CreateTemplate() + { + // arrange + var templateName = "C# integration test template " + DateTime.UtcNow; + + MailjetRequest request = new MailjetRequest + { + Resource = Template.Resource, + } + .Property(Template.Author, "Mailjet team") + .Property(Template.Copyright, "Mailjet") + .Property(Template.Description, "Used to send templated emails in C# SDK integration test") + .Property(Template.EditMode, Template.EditModeValue_MJMLBuilder) + .Property(Template.IsTextPartGenerationEnabled, true) + .Property(Template.Locale, "en_US") + .Property(Template.Name, templateName) + .Property(Template.OwnerType, Template.OwnerTypeValue_Apikey) + .Property(Template.Purposes, JArray.FromObject(new[]{ "transactional" })); + + // act + MailjetResponse response = await _client.PostAsync(request); + + // assert + Assert.IsTrue(response.IsSuccessStatusCode); + + Assert.AreEqual(1, response.GetTotal()); + Assert.AreEqual(templateName, response.GetData().Single().Value("Name")); + + long templateId = response.GetData().Single().Value("ID"); + return templateId; + } + + public async Task SendEmailWithTemplate(long templateId) + { + // arrange + var testArrayWithValues = new [] + { + new {title = "testTitle1"}, + new {title = "testTitle2"}, + }; + + var variables = new Dictionary + { + {"testVariableName", "testVariableValue"}, + {"items", testArrayWithValues} + }; + + var email = new TransactionalEmailBuilder() + .WithTo(new SendContact(_senderEmail)) + .WithFrom(new SendContact(_senderEmail)) + .WithSubject("Test subject " + DateTime.UtcNow) + .WithTemplateId(templateId) + .WithVariables(variables) + .WithTemplateLanguage(true) + .WithTemplateErrorDeliver(true) + .WithTemplateErrorReporting(new SendContact(_senderEmail)) + .Build(); + + // act + var response = await _client.SendTransactionalEmailAsync(email); + + // assert + Assert.AreEqual(1, response.Messages.Length); + var message = response.Messages[0]; + + Assert.AreEqual("success", message.Status); + Assert.AreEqual(_senderEmail, message.To.Single().Email); + } + + public static async Task GetValidSenderEmail(MailjetClient client) + { + MailjetRequest request = new MailjetRequest + { + Resource = Sender.Resource + }; + + MailjetResponse response = await client.GetAsync(request); + + Assert.AreEqual(200, response.StatusCode); + + foreach (var emailObject in response.GetData()) + { + if (emailObject.Type != JTokenType.Object) + continue; + + if (emailObject.Value("Status") == "Active") + return emailObject.Value("Email"); + } + + Assert.Fail("Cannot find Active sender address under given account"); + throw new AssertFailedException(); + } + } +} diff --git a/Mailjet.Tests/Mailjet.Tests.csproj b/Mailjet.Tests/Mailjet.Tests.csproj index bd3144b..b3d8e40 100644 --- a/Mailjet.Tests/Mailjet.Tests.csproj +++ b/Mailjet.Tests/Mailjet.Tests.csproj @@ -4,6 +4,16 @@ netcoreapp1.1 + + + + + + + PreserveNewest + + + diff --git a/Mailjet.Tests/Resources/MJMLTemplate.mjml b/Mailjet.Tests/Resources/MJMLTemplate.mjml new file mode 100644 index 0000000..d2a35da --- /dev/null +++ b/Mailjet.Tests/Resources/MJMLTemplate.mjml @@ -0,0 +1,41 @@ + + + + + + + + + + + +

+ {{var:testVariableName:""}} +

+
+
+
+ + + + + + + + {% for item in var:items %} + + + + + +

Hey {{ item.title }}

+
+
+
+ + + {% endfor %} + + +
+
From 21702dbc2011fdbb937d0be2141cb5e235db760a Mon Sep 17 00:00:00 2001 From: Stanislav Diakovskyi Date: Fri, 18 Dec 2020 08:22:14 +0200 Subject: [PATCH 4/5] updates version to v2.0.1 --- Mailjet.Client/Mailjet.Client.csproj | 4 ++-- Mailjet.Client/MailjetConstants.cs | 2 +- README.md | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Mailjet.Client/Mailjet.Client.csproj b/Mailjet.Client/Mailjet.Client.csproj index 2aa6e4b..2c48a15 100644 --- a/Mailjet.Client/Mailjet.Client.csproj +++ b/Mailjet.Client/Mailjet.Client.csproj @@ -4,8 +4,8 @@ net45;netstandard1.1 False - 2.0.0 - 2.0.0 + 2.0.1 + 2.0.1 Mailjet, Dimitar Kostov https://github.com/mailjet/mailjet-apiv3-dotnet/blob/master/LICENSE diff --git a/Mailjet.Client/MailjetConstants.cs b/Mailjet.Client/MailjetConstants.cs index 099cee8..bfdbc01 100644 --- a/Mailjet.Client/MailjetConstants.cs +++ b/Mailjet.Client/MailjetConstants.cs @@ -3,7 +3,7 @@ public static class MailjetConstants { public const string DefaultBaseAdress = "https://api.mailjet.com"; - public const string UserAgent = "mailjet-api-v3-net/2.0.0"; + public const string UserAgent = "mailjet-api-v3-net/2.0.1"; public const string JsonMediaType = "application/json"; public const string ApiVersionPathV3 = "v3"; public const string ApiVersionPathV3_1 = "v3.1"; diff --git a/README.md b/README.md index 8b0482f..e86dcdb 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ Check out all the resources and .NET code examples in the official [Mailjet Docu - [Overview](#overview) - [Table of contents](#table-of-contents) - [Release notes](#release-notes) + - [v 2.0.1](#v-201) - [v 2.0.0](#v-200) - [Compatibility](#compatibility) - [Dependencies .NETStandard 1.1](#dependencies-netstandard-11) @@ -58,6 +59,8 @@ Check out all the resources and .NET code examples in the official [Mailjet Docu ## Release notes +### v 2.0.1 + - TransactionalEmailBuidler now accepts variables of any type (previously only strings) ### v 2.0.0 - Added TransactionalEmailBuidler and TransactionalEmail strongly typed models - now you can send transactional emails more easily! Please, check [tests for more information](Mailjet.Tests/Integration/SendTransactionalEmailIntegrationTests.cs) - Added Contacts delete API - now you can support [GDPR delete contacts](https://dev.mailjet.com/email/guides/contact-management/#gdpr-delete-contacts) easily From d9a65563254324833e1908481d7b1ad99d5cc05c Mon Sep 17 00:00:00 2001 From: Stanislav Diakovskyi Date: Fri, 18 Dec 2020 08:25:39 +0200 Subject: [PATCH 5/5] fixes test to pass on unix machines as well --- .../Integration/TemplateIntegrationTests.cs | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/Mailjet.Tests/Integration/TemplateIntegrationTests.cs b/Mailjet.Tests/Integration/TemplateIntegrationTests.cs index 64699dd..33079c7 100644 --- a/Mailjet.Tests/Integration/TemplateIntegrationTests.cs +++ b/Mailjet.Tests/Integration/TemplateIntegrationTests.cs @@ -29,17 +29,6 @@ public async Task TestInitialize() [TestMethod] public async Task SendTransactionalEmailAsync_SendsEmail() { - - MailjetRequest request = new MailjetRequest - { - Resource = TemplateDetailcontent.Resource, - ResourceId = ResourceId.Numeric(2095787) - }; - - var resp = await _client.GetAsync(request); - - - long templateId = await CreateTemplate(); Assert.IsTrue(templateId > 0); @@ -70,7 +59,7 @@ private async Task DeleteTemplate(long templateId) private async Task FillTemplateContent(long templateId) { // arrange - var content = File.ReadAllText(@"Resources\MJMLTemplate.mjml"); + var content = File.ReadAllText(Path.Combine("Resources", "MJMLTemplate.mjml")); MailjetRequest request = new MailjetRequest {