diff --git a/Source/StrongGrid.UnitTests/Models/SingleSendTests.cs b/Source/StrongGrid.UnitTests/Models/SingleSendTests.cs
new file mode 100644
index 00000000..8097d4de
--- /dev/null
+++ b/Source/StrongGrid.UnitTests/Models/SingleSendTests.cs
@@ -0,0 +1,67 @@
+using Shouldly;
+using StrongGrid.Json;
+using StrongGrid.Models;
+using System;
+using System.Text.Json;
+using Xunit;
+
+namespace StrongGrid.UnitTests.Models
+{
+ public class SingleSendTests
+ {
+ private const string SINGLE_SEND_JSON = @"{
+ ""id"":""5e0555c5-cb50-11ee-a09e-6aa2ee6dcd4d"",
+ ""name"":""StrongGrid Unit Testing: single send"",
+ ""status"":""draft"",
+ ""categories"":[""category1"",""category2""],
+ ""send_at"":null,
+ ""send_to"":{
+ ""list_ids"":[""a21d5383-1f7c-4e7a-bf2e-511467f58e7d""],
+ ""segment_ids"":[],
+ ""all"":false
+ },
+ ""updated_at"":""2024-02-14T15:47:34Z"",
+ ""created_at"":""2024-02-14T15:47:33Z"",
+ ""email_config"":{
+ ""subject"":""This is the subject"",
+ ""html_content"":""
This is the HTML conytent"",
+ ""plain_content"":""This is the text content"",
+ ""generate_plain_content"":false,
+ ""editor"":""code"",
+ ""suppression_group_id"":54321,
+ ""custom_unsubscribe_url"":null,
+ ""sender_id"":12345,
+ ""ip_pool"":null
+ }
+ }";
+
+ [Fact]
+ public void Parse_processed_JSON()
+ {
+ // Arrange
+
+ // Act
+ var result = JsonSerializer.Deserialize(SINGLE_SEND_JSON, JsonFormatter.DeserializerOptions);
+
+ // Assert
+ result.Categories.ShouldBe(new[] { "category1", "category2" });
+ result.EmailConfig.HtmlContent.ShouldBe("This is the HTML conytent");
+ result.EmailConfig.IpPool.ShouldBeNull();
+ result.EmailConfig.Subject.ShouldBe("This is the subject");
+ result.EmailConfig.TextContent.ShouldBe("This is the text content");
+ result.EmailConfig.CustomUnsubscribeUrl.ShouldBeNull();
+ result.EmailConfig.EditorType.ShouldBe(EditorType.Code);
+ result.EmailConfig.GeneratePlainContent.ShouldBeFalse();
+ result.EmailConfig.SenderId.ShouldBe(12345);
+ result.EmailConfig.SuppressionGroupId.ShouldBe(54321);
+ result.CreatedOn.ShouldBe(new DateTime(2024, 2, 14, 15, 47, 33, DateTimeKind.Utc));
+ result.Id.ShouldBe("5e0555c5-cb50-11ee-a09e-6aa2ee6dcd4d");
+ result.Recipients.Lists.ShouldBe(new[] { "a21d5383-1f7c-4e7a-bf2e-511467f58e7d" });
+ result.Recipients.Segments.ShouldBe(Array.Empty());
+ result.Name.ShouldBe("StrongGrid Unit Testing: single send");
+ result.SendOn.ShouldBeNull();
+ result.Status.ShouldBe(SingleSendStatus.Draft);
+ result.UpdatedOn.ShouldBe(new DateTime(2024, 2, 14, 15, 47, 34, DateTimeKind.Utc));
+ }
+ }
+}
diff --git a/Source/StrongGrid/Json/EpochConverter.cs b/Source/StrongGrid/Json/EpochConverter.cs
index 7f798b5d..ec0a4431 100644
--- a/Source/StrongGrid/Json/EpochConverter.cs
+++ b/Source/StrongGrid/Json/EpochConverter.cs
@@ -12,8 +12,14 @@ internal class EpochConverter : BaseJsonConverter
{
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
- var secondsSinceEpoch = reader.GetInt64();
- return secondsSinceEpoch.FromUnixTime();
+ switch (reader.TokenType)
+ {
+ case JsonTokenType.Number:
+ var secondsSinceEpoch = reader.GetInt64();
+ return secondsSinceEpoch.FromUnixTime();
+ default:
+ throw new Exception($"Unable to convert {reader.TokenType.ToEnumString()} to DateTime");
+ }
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
diff --git a/Source/StrongGrid/Json/StrongGridJsonSerializerContext.cs b/Source/StrongGrid/Json/StrongGridJsonSerializerContext.cs
index 26e2979c..0bcb9cdb 100644
--- a/Source/StrongGrid/Json/StrongGridJsonSerializerContext.cs
+++ b/Source/StrongGrid/Json/StrongGridJsonSerializerContext.cs
@@ -170,7 +170,7 @@ namespace StrongGrid.Json
[JsonSerializable(typeof(StrongGrid.Models.SenderReputation))]
[JsonSerializable(typeof(StrongGrid.Models.SingleSend))]
[JsonSerializable(typeof(StrongGrid.Models.SingleSendEmailConfig))]
- [JsonSerializable(typeof(StrongGrid.Models.SingleSendSendTo))]
+ [JsonSerializable(typeof(StrongGrid.Models.SingleSendRecipients))]
[JsonSerializable(typeof(StrongGrid.Models.SingleSendStatus))]
[JsonSerializable(typeof(StrongGrid.Models.SpamCheckingSettings))]
[JsonSerializable(typeof(StrongGrid.Models.SpamCheckSettings))]
@@ -378,7 +378,7 @@ namespace StrongGrid.Json
[JsonSerializable(typeof(StrongGrid.Models.SenderReputation[]))]
[JsonSerializable(typeof(StrongGrid.Models.SingleSend[]))]
[JsonSerializable(typeof(StrongGrid.Models.SingleSendEmailConfig[]))]
- [JsonSerializable(typeof(StrongGrid.Models.SingleSendSendTo[]))]
+ [JsonSerializable(typeof(StrongGrid.Models.SingleSendRecipients[]))]
[JsonSerializable(typeof(StrongGrid.Models.SingleSendStatus[]))]
[JsonSerializable(typeof(StrongGrid.Models.SpamCheckingSettings[]))]
[JsonSerializable(typeof(StrongGrid.Models.SpamCheckSettings[]))]
diff --git a/Source/StrongGrid/Models/SingleSend.cs b/Source/StrongGrid/Models/SingleSend.cs
index 64072f1f..19d128d7 100644
--- a/Source/StrongGrid/Models/SingleSend.cs
+++ b/Source/StrongGrid/Models/SingleSend.cs
@@ -72,152 +72,15 @@ public class SingleSend
public DateTime? CreatedOn { get; set; }
///
- /// Gets or sets the subject.
+ /// Gets or sets the configuration about the email that will be sent to the recipients.
///
- ///
- /// The subject.
- ///
- [JsonIgnore]
- public string Subject
- {
- get => EmailConfig.Subject;
- set => EmailConfig.Subject = value;
- }
-
- ///
- /// Gets or sets the HTML content.
- ///
- ///
- /// The HTML content.
- ///
- [JsonIgnore]
- public string HtmlContent
- {
- get => EmailConfig.HtmlContent;
- set => EmailConfig.HtmlContent = value;
- }
-
- ///
- /// Gets or sets the plain text content.
- ///
- ///
- /// The plain text content.
- ///
- [JsonIgnore]
- public string TextContent
- {
- get => EmailConfig.TextContent;
- set => EmailConfig.TextContent = value;
- }
-
- ///
- /// Gets or sets a value indicating whether the plain content should be generated.
- ///
- ///
- /// The generate_plain_content.
- ///
- [JsonIgnore]
- public bool GeneratePlainContent
- {
- get => EmailConfig.GeneratePlainContent;
- set => EmailConfig.GeneratePlainContent = value;
- }
-
- ///
- /// Gets or sets the type of editor used in the UI.
- ///
- ///
- /// The type of editor.
- ///
- [JsonIgnore]
- public EditorType EditorType
- {
- get => EmailConfig.EditorType;
- set => EmailConfig.EditorType = value;
- }
-
- ///
- /// Gets or sets the sender identifier.
- ///
- ///
- /// The sender identifier.
- ///
- [JsonIgnore]
- public long SenderId
- {
- get => EmailConfig.SenderId;
- set => EmailConfig.SenderId = value;
- }
-
- ///
- /// Gets or sets the custom unsubscribe URL.
- ///
- ///
- /// The custom unsubscribe URL.
- ///
- [JsonIgnore]
- public string CustomUnsubscribeUrl
- {
- get => EmailConfig.CustomUnsubscribeUrl;
- set => EmailConfig.CustomUnsubscribeUrl = value;
- }
-
- ///
- /// Gets or sets the suppression group identifier.
- ///
- ///
- /// The suppression group identifier.
- ///
- [JsonIgnore]
- public long? SuppressionGroupId
- {
- get => EmailConfig.SuppressionGroupId;
- set => EmailConfig.SuppressionGroupId = value;
- }
-
- ///
- /// Gets or sets the ip pool.
- ///
- ///
- /// The ip pool.
- ///
- [JsonIgnore]
- public string IpPool
- {
- get => EmailConfig.IpPool;
- set => EmailConfig.IpPool = value;
- }
-
- ///
- /// Gets or sets the lists.
- ///
- ///
- /// The lists.
- ///
- [JsonIgnore]
- public string[] Lists
- {
- get => SendTo.Lists;
- set => SendTo.Lists = value;
- }
+ [JsonPropertyName("email_config")]
+ public SingleSendEmailConfig EmailConfig { get; set; }
///
- /// Gets or sets the segments.
+ /// Gets or sets the information about who will receive this Single Send.
///
- ///
- /// The segments.
- ///
- [JsonIgnore]
- public string[] Segments
- {
- get => SendTo.Segments;
- set => SendTo.Segments = value;
- }
-
- [JsonPropertyName("email_config")]
- private SingleSendEmailConfig EmailConfig { get; set; }
-
[JsonPropertyName("send_to")]
- private SingleSendSendTo SendTo { get; set; }
+ public SingleSendRecipients Recipients { get; set; }
}
}
diff --git a/Source/StrongGrid/Models/SingleSendEmailConfig.cs b/Source/StrongGrid/Models/SingleSendEmailConfig.cs
index d4426a34..42fae651 100644
--- a/Source/StrongGrid/Models/SingleSendEmailConfig.cs
+++ b/Source/StrongGrid/Models/SingleSendEmailConfig.cs
@@ -5,7 +5,7 @@ namespace StrongGrid.Models
///
/// Single Send email config.
///
- internal class SingleSendEmailConfig
+ public class SingleSendEmailConfig
{
///
/// Gets or sets the subject.
diff --git a/Source/StrongGrid/Models/SingleSendSendTo.cs b/Source/StrongGrid/Models/SingleSendRecipients.cs
similarity index 86%
rename from Source/StrongGrid/Models/SingleSendSendTo.cs
rename to Source/StrongGrid/Models/SingleSendRecipients.cs
index 9a8e30fd..f6f8428b 100644
--- a/Source/StrongGrid/Models/SingleSendSendTo.cs
+++ b/Source/StrongGrid/Models/SingleSendRecipients.cs
@@ -3,9 +3,9 @@
namespace StrongGrid.Models
{
///
- /// Single Send send to.
+ /// The recipients of a Single Send.
///
- internal class SingleSendSendTo
+ public class SingleSendRecipients
{
///
/// Gets or sets the lists.
diff --git a/Source/StrongGrid/Resources/Mail.cs b/Source/StrongGrid/Resources/Mail.cs
index e8dc9ce7..c4fd2766 100644
--- a/Source/StrongGrid/Resources/Mail.cs
+++ b/Source/StrongGrid/Resources/Mail.cs
@@ -150,9 +150,9 @@ public async Task SendAsync(
foreach (var personalization in personalizationsCopy)
{
// Make sure the arrays are not null otherwise Linq's 'Except' method will throw a ArgumentNull exception (See GH-286).
- if (personalization.To == null) personalization.To = Array.Empty();
- if (personalization.Cc == null) personalization.Cc = Array.Empty();
- if (personalization.Bcc == null) personalization.Bcc = Array.Empty();
+ personalization.To ??= Array.Empty();
+ personalization.Cc ??= Array.Empty();
+ personalization.Bcc ??= Array.Empty();
// Avoid duplicate addresses. This is important because SendGrid does not throw any
// exception when a recipient is duplicated (which gives you the impression the email
diff --git a/build.cake b/build.cake
index d1be6211..0dfa1487 100644
--- a/build.cake
+++ b/build.cake
@@ -2,8 +2,8 @@
#tool dotnet:?package=GitVersion.Tool&version=5.12.0
#tool dotnet:?package=coveralls.net&version=4.0.1
#tool nuget:https://f.feedz.io/jericho/jericho/nuget/?package=GitReleaseManager&version=0.17.0-collaborators0003
-#tool nuget:?package=ReportGenerator&version=5.2.0
-#tool nuget:?package=xunit.runner.console&version=2.6.6
+#tool nuget:?package=ReportGenerator&version=5.2.1
+#tool nuget:?package=xunit.runner.console&version=2.7.0
#tool nuget:?package=CodecovUploader&version=0.7.1
// Install addins.
diff --git a/global.json b/global.json
index f43378f6..667094ad 100644
--- a/global.json
+++ b/global.json
@@ -1,6 +1,6 @@
{
"sdk": {
- "version": "8.0.101",
+ "version": "8.0.201",
"rollForward": "patch",
"allowPrerelease": false
}