Skip to content

Commit 9f9d451

Browse files
Merge pull request #66 from mailjet/complex-variables
Complex variables - fixes the case with
2 parents bfe9c70 + d9a6556 commit 9f9d451

File tree

10 files changed

+267
-8
lines changed

10 files changed

+267
-8
lines changed

Mailjet.Client/Mailjet.Client.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
<TargetFrameworks>net45;netstandard1.1</TargetFrameworks>
55
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
66

7-
<Version>2.0.0</Version>
8-
<PackageVersion>2.0.0</PackageVersion>
7+
<Version>2.0.1</Version>
8+
<PackageVersion>2.0.1</PackageVersion>
99

1010
<Authors>Mailjet, Dimitar Kostov</Authors>
1111
<PackageLicenseUrl>https://github.com/mailjet/mailjet-apiv3-dotnet/blob/master/LICENSE</PackageLicenseUrl>

Mailjet.Client/MailjetConstants.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
public static class MailjetConstants
44
{
55
public const string DefaultBaseAdress = "https://api.mailjet.com";
6-
public const string UserAgent = "mailjet-api-v3-net/2.0.0";
6+
public const string UserAgent = "mailjet-api-v3-net/2.0.1";
77
public const string JsonMediaType = "application/json";
88
public const string ApiVersionPathV3 = "v3";
99
public const string ApiVersionPathV3_1 = "v3.1";

Mailjet.Client/Resources/Template.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,21 @@ public static class Template
2121
public const string APIKey = "APIKey";
2222
public const string CategoriesSelectionMethod = "CategoriesSelectionMethod";
2323
public const string PurposesSelectionMethod = "PurposesSelectionMethod";
24+
public const string IsTextPartGenerationEnabled = "IsTextPartGenerationEnabled";
2425
public const string User = "User";
2526
public const string Limit = "Limit";
2627
public const string Offset = "Offset";
2728
public const string Sort = "Sort";
2829
public const string CountOnly = "CountOnly";
30+
31+
public const long EditModeValue_DNDBuilder = 1;
32+
public const long EditModeValue_HTMLBuilder = 2;
33+
public const long EditModeValue_SavedSectionBuilder = 3;
34+
public const long EditModeValue_MJMLBuilder = 4;
35+
36+
public const string OwnerTypeValue_Apikey = "apikey";
37+
public const string OwnerTypeValue_User = "user";
38+
public const string OwnerTypeValue_Global = "global";
2939
}
3040
}
3141

Mailjet.Client/Resources/TemplateDetailcontent.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ public static class TemplateDetailcontent
88
public const string Htmlpart = "Html-part";
99
public const string MJMLContent = "MJMLContent";
1010
public const string Headers = "Headers";
11+
public const string From = "From";
12+
public const string Subject = "Subject";
13+
public const string ReplyTo = "Reply-to";
1114
}
1215
}
13-
14-

Mailjet.Client/TransactionalEmails/Models/TransactionalEmail.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,6 @@ public class TransactionalEmail
3232
public string URLTags { get; set; }
3333

3434
public Dictionary<string, string> Headers { get; set; }
35-
public Dictionary<string, object> Variables { get; set; }
35+
public IDictionary<string, object> Variables { get; set; }
3636
}
3737
}

Mailjet.Client/TransactionalEmails/TransactionalEmailBuilder.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public class TransactionalEmailBuilder
3434
private string _urlTags;
3535

3636
private Dictionary<string, string> _headers;
37-
private Dictionary<string, object> _variables;
37+
private IDictionary<string, object> _variables;
3838

3939
/// <summary>
4040
/// The email subject line
@@ -393,6 +393,18 @@ public TransactionalEmailBuilder WithVariable(string variableName, object variab
393393
return this;
394394
}
395395

396+
/// <summary>
397+
/// Adds dictionary with variables used to modify the content of your email.
398+
/// Enter the information in the template text / HTML part by using the [[var:{var_name}]] format.
399+
/// Equivalent of using X-MJ-Vars header through SMTP.
400+
/// </summary>
401+
public TransactionalEmailBuilder WithVariables(IDictionary<string, object> variables)
402+
{
403+
_variables = variables;
404+
405+
return this;
406+
}
407+
396408
/// <summary>
397409
/// Builds the mail message
398410
/// </summary>
@@ -435,6 +447,7 @@ public TransactionalEmail Build()
435447
/// with single preconfigured builder instance
436448
/// performs the deep clone of the current builder instance
437449
/// </summary>
450+
/// <remarks>Clone creates a deep clone of the builder itself, but does not clone passed variables</remarks>
438451
public TransactionalEmailBuilder Clone()
439452
{
440453
var result = (TransactionalEmailBuilder) MemberwiseClone();
@@ -459,7 +472,8 @@ public TransactionalEmailBuilder Clone()
459472

460473
private void Validate()
461474
{
462-
if (_from == null)
475+
// template could have a default sender, so in case of using template we should allow sending w/o sender specified
476+
if (_from == null && _templateId == null)
463477
throw new MailjetClientConfigurationException("From field should be specified");
464478

465479
if (string.IsNullOrEmpty(_textPart) &&
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Threading.Tasks;
6+
using Mailjet.Client;
7+
using Mailjet.Client.Resources;
8+
using Mailjet.Client.TransactionalEmails;
9+
using Microsoft.VisualStudio.TestTools.UnitTesting;
10+
using Newtonsoft.Json.Linq;
11+
12+
namespace Mailjet.Tests.Integration
13+
{
14+
[TestClass]
15+
public class TemplateIntegrationTests
16+
{
17+
private MailjetClient _client;
18+
private string _senderEmail;
19+
20+
[TestInitialize]
21+
public async Task TestInitialize()
22+
{
23+
_client = new MailjetClient(Environment.GetEnvironmentVariable("MJ_APIKEY_PUBLIC"),
24+
Environment.GetEnvironmentVariable("MJ_APIKEY_PRIVATE"));
25+
26+
_senderEmail = await GetValidSenderEmail(_client);
27+
}
28+
29+
[TestMethod]
30+
public async Task SendTransactionalEmailAsync_SendsEmail()
31+
{
32+
long templateId = await CreateTemplate();
33+
34+
Assert.IsTrue(templateId > 0);
35+
36+
await FillTemplateContent(templateId);
37+
38+
await SendEmailWithTemplate(templateId);
39+
40+
await DeleteTemplate(templateId);
41+
}
42+
43+
private async Task DeleteTemplate(long templateId)
44+
{
45+
// arrange
46+
MailjetRequest request = new MailjetRequest
47+
{
48+
Resource = Template.Resource,
49+
ResourceId = ResourceId.Numeric(templateId)
50+
};
51+
52+
// act
53+
MailjetResponse response = await _client.DeleteAsync(request);
54+
55+
// assert
56+
Assert.AreEqual(204, response.StatusCode);
57+
}
58+
59+
private async Task FillTemplateContent(long templateId)
60+
{
61+
// arrange
62+
var content = File.ReadAllText(Path.Combine("Resources", "MJMLTemplate.mjml"));
63+
64+
MailjetRequest request = new MailjetRequest
65+
{
66+
Resource = TemplateDetailcontent.Resource,
67+
ResourceId = ResourceId.Numeric(templateId)
68+
}
69+
.Property(TemplateDetailcontent.MJMLContent, content)
70+
.Property(TemplateDetailcontent.Headers, JObject.FromObject(new Dictionary<string, string>()
71+
{
72+
{"Subject", "Test transactional template subject " + DateTime.UtcNow},
73+
{"SenderName", "Test transactional template"},
74+
{"SenderEmail", _senderEmail},
75+
{"From", _senderEmail},
76+
}));
77+
78+
// act
79+
MailjetResponse response = await _client.PostAsync(request);
80+
81+
// assert
82+
Assert.IsTrue(response.IsSuccessStatusCode);
83+
Assert.AreEqual(1, response.GetTotal());
84+
Assert.AreEqual(content, response.GetData().Single().Value<string>("MJMLContent"));
85+
}
86+
87+
private async Task<long> CreateTemplate()
88+
{
89+
// arrange
90+
var templateName = "C# integration test template " + DateTime.UtcNow;
91+
92+
MailjetRequest request = new MailjetRequest
93+
{
94+
Resource = Template.Resource,
95+
}
96+
.Property(Template.Author, "Mailjet team")
97+
.Property(Template.Copyright, "Mailjet")
98+
.Property(Template.Description, "Used to send templated emails in C# SDK integration test")
99+
.Property(Template.EditMode, Template.EditModeValue_MJMLBuilder)
100+
.Property(Template.IsTextPartGenerationEnabled, true)
101+
.Property(Template.Locale, "en_US")
102+
.Property(Template.Name, templateName)
103+
.Property(Template.OwnerType, Template.OwnerTypeValue_Apikey)
104+
.Property(Template.Purposes, JArray.FromObject(new[]{ "transactional" }));
105+
106+
// act
107+
MailjetResponse response = await _client.PostAsync(request);
108+
109+
// assert
110+
Assert.IsTrue(response.IsSuccessStatusCode);
111+
112+
Assert.AreEqual(1, response.GetTotal());
113+
Assert.AreEqual(templateName, response.GetData().Single().Value<string>("Name"));
114+
115+
long templateId = response.GetData().Single().Value<long>("ID");
116+
return templateId;
117+
}
118+
119+
public async Task SendEmailWithTemplate(long templateId)
120+
{
121+
// arrange
122+
var testArrayWithValues = new []
123+
{
124+
new {title = "testTitle1"},
125+
new {title = "testTitle2"},
126+
};
127+
128+
var variables = new Dictionary<string, object>
129+
{
130+
{"testVariableName", "testVariableValue"},
131+
{"items", testArrayWithValues}
132+
};
133+
134+
var email = new TransactionalEmailBuilder()
135+
.WithTo(new SendContact(_senderEmail))
136+
.WithFrom(new SendContact(_senderEmail))
137+
.WithSubject("Test subject " + DateTime.UtcNow)
138+
.WithTemplateId(templateId)
139+
.WithVariables(variables)
140+
.WithTemplateLanguage(true)
141+
.WithTemplateErrorDeliver(true)
142+
.WithTemplateErrorReporting(new SendContact(_senderEmail))
143+
.Build();
144+
145+
// act
146+
var response = await _client.SendTransactionalEmailAsync(email);
147+
148+
// assert
149+
Assert.AreEqual(1, response.Messages.Length);
150+
var message = response.Messages[0];
151+
152+
Assert.AreEqual("success", message.Status);
153+
Assert.AreEqual(_senderEmail, message.To.Single().Email);
154+
}
155+
156+
public static async Task<string> GetValidSenderEmail(MailjetClient client)
157+
{
158+
MailjetRequest request = new MailjetRequest
159+
{
160+
Resource = Sender.Resource
161+
};
162+
163+
MailjetResponse response = await client.GetAsync(request);
164+
165+
Assert.AreEqual(200, response.StatusCode);
166+
167+
foreach (var emailObject in response.GetData())
168+
{
169+
if (emailObject.Type != JTokenType.Object)
170+
continue;
171+
172+
if (emailObject.Value<string>("Status") == "Active")
173+
return emailObject.Value<string>("Email");
174+
}
175+
176+
Assert.Fail("Cannot find Active sender address under given account");
177+
throw new AssertFailedException();
178+
}
179+
}
180+
}

Mailjet.Tests/Mailjet.Tests.csproj

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@
44
<TargetFramework>netcoreapp1.1</TargetFramework>
55
</PropertyGroup>
66

7+
<ItemGroup>
8+
<None Remove="Resources\MJMLTemplate.mjml" />
9+
</ItemGroup>
10+
11+
<ItemGroup>
12+
<Content Include="Resources\MJMLTemplate.mjml">
13+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
14+
</Content>
15+
</ItemGroup>
16+
717
<ItemGroup>
818
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
919
<PackageReference Include="MSTest.TestAdapter" Version="1.1.11" />
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<mjml owa="desktop" version="4.3.0">
2+
<mj-head>
3+
<mj-font href="https://fonts.googleapis.com/css?family=Montserrat" name="Montserrat"></mj-font>
4+
<mj-font href="https://fonts.googleapis.com/css?family=Raleway" name="Raleway"></mj-font>
5+
<mj-font href="https://fonts.googleapis.com/css?family=Open Sans" name="Open Sans"></mj-font>
6+
<mj-preview></mj-preview>
7+
</mj-head>
8+
<mj-body background-color="#f8f8f8" color="#797e82" font-family="Open Sans, Helvetica, Arial, sans-serif">
9+
<mj-section background-repeat="repeat" background-size="auto" padding-bottom="0px" padding-top="0px" padding="20px 0px 20px 0px" text-align="center" >
10+
<mj-column>
11+
<mj-text align="left" color="#797e82" font-family="Open Sans, Helvetica, Arial, sans-serif" font-size="11px" line-height="22px" padding-bottom="0px" padding-top="0px" padding="0px 0px 0px 25px">
12+
<p style="text-align: center; margin: 10px 0;">
13+
{{var:testVariableName:""}}
14+
</p>
15+
</mj-text>
16+
</mj-column>
17+
</mj-section>
18+
<mj-section background-color="#ffffff" background-repeat="repeat" padding-bottom="0px" padding-left="0px" padding-right="0px" padding-top="0px" padding="20px 0" text-align="center" >
19+
<mj-column>
20+
<mj-divider border-color="#fcac24" border-style="solid" border-width="7px" padding-bottom="40px" padding-left="0px" padding-right="0px" padding-top="0px" padding="10px 25px" width="100%"></mj-divider>
21+
</mj-column>
22+
</mj-section>
23+
24+
<mj-raw>
25+
{% for item in var:items %}
26+
</mj-raw>
27+
28+
<mj-section background-color="#ffffff" background-repeat="repeat" background-size="auto" padding-bottom="70px" padding-top="30px" padding="20px 0px 20px 0px" text-align="center" >
29+
<mj-column>
30+
<mj-text align="left" color="#797e82" font-family="Open Sans, Helvetica, Arial, sans-serif" font-size="13px" line-height="22px" padding-bottom="0px" padding-left="50px" padding-right="50px" padding-top="0px" padding="0px 25px 0px 25px">
31+
<h1 style="text-align:center; color: #000000; line-height:32px">Hey {{ item.title }}</h1>
32+
</mj-text>
33+
</mj-column>
34+
</mj-section>
35+
36+
<mj-raw>
37+
{% endfor %}
38+
</mj-raw>
39+
40+
</mj-body>
41+
</mjml>

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Check out all the resources and .NET code examples in the official [Mailjet Docu
2828
- [Overview](#overview)
2929
- [Table of contents](#table-of-contents)
3030
- [Release notes](#release-notes)
31+
- [v 2.0.1](#v-201)
3132
- [v 2.0.0](#v-200)
3233
- [Compatibility](#compatibility)
3334
- [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
5859

5960
## Release notes
6061

62+
### v 2.0.1
63+
- TransactionalEmailBuidler now accepts variables of any type (previously only strings)
6164
### v 2.0.0
6265
- 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)
6366
- Added Contacts delete API - now you can support [GDPR delete contacts](https://dev.mailjet.com/email/guides/contact-management/#gdpr-delete-contacts) easily

0 commit comments

Comments
 (0)