Skip to content

Commit

Permalink
Merge branch 'release/0.41.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
Jericho committed May 2, 2018
2 parents 383d154 + c9d0a25 commit 0df4ad0
Show file tree
Hide file tree
Showing 26 changed files with 374 additions and 70 deletions.
11 changes: 7 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
### VisualStudio ###
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore

# User-specific files
*.suo
Expand Down Expand Up @@ -273,9 +275,6 @@ paket-files/
# CodeRush
.cr/

# WinMerge
*.bak

# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
Expand All @@ -297,4 +296,8 @@ tools/**
# By default, sensitive information, such as encrypted password
# should be stored in the .pubxml.user file.

# End of https://www.gitignore.io/api/visualstudio

# WinMerge
*.bak

# End of https://www.gitignore.io/api/visualstudio
77 changes: 44 additions & 33 deletions Source/StrongGrid.IntegrationTests/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -726,38 +726,49 @@ private static async Task ListsAndSegments(IClient client, TextWriter log, Cance
}));
await Task.WhenAll(cleanUpTasks).ConfigureAwait(false);

foreach (var oldSegment in segments.Where(s => s.Name.StartsWith("StrongGrid Integration Testing:")))
{
await client.Segments.DeleteAsync(oldSegment.Id, false, null, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"Segment {oldSegment.Id} deleted").ConfigureAwait(false);
}

var firstList = await client.Lists.CreateAsync("StrongGrid Integration Testing: list #1", null, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"List '{firstList.Name}' created. Id: {firstList.Id}").ConfigureAwait(false);

var secondList = await client.Lists.CreateAsync("StrongGrid Integration Testing: list #2", null, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"List '{secondList.Name}' created. Id: {secondList.Id}").ConfigureAwait(false);
// CREATE A LIST
var list = await client.Lists.CreateAsync("StrongGrid Integration Testing: list #1", null, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"List '{list.Name}' created. Id: {list.Id}").ConfigureAwait(false);

await client.Lists.UpdateAsync(firstList.Id, "StrongGrid Integration Testing: new name", null, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"List '{firstList.Id}' updated").ConfigureAwait(false);

var hotmailCondition = new SearchCondition { Field = "email", Operator = ConditionOperator.Contains, Value = "hotmail.com", LogicalOperator = LogicalOperator.None };
var segment = await client.Segments.CreateAsync("StrongGrid Integration Testing: Recipients @ Hotmail", new[] { hotmailCondition }, firstList.Id, null, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"Segment '{segment.Name}' created. Id: {segment.Id}").ConfigureAwait(false);
// UPDATE THE LIST
await client.Lists.UpdateAsync(list.Id, "StrongGrid Integration Testing: new name", null, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"List '{list.Id}' updated").ConfigureAwait(false);

// CREATE A SEGMENT
var millerLastNameCondition = new SearchCondition { Field = "last_name", Operator = ConditionOperator.Equal, Value = "Miller", LogicalOperator = LogicalOperator.None };
var clickedRecentlyCondition = new SearchCondition { Field = "last_clicked", Operator = ConditionOperator.GreatherThan, Value = DateTime.UtcNow.AddDays(-30).ToString("MM/dd/yyyy"), LogicalOperator = LogicalOperator.And };
segment = await client.Segments.UpdateAsync(segment.Id, "StrongGrid Integration Testing: Last Name is Miller and clicked recently", null, new[] { millerLastNameCondition, clickedRecentlyCondition }, null, cancellationToken).ConfigureAwait(false);
var segment = await client.Segments.CreateAsync("StrongGrid Integration Testing: Last Name is Miller and clicked recently", new[] { millerLastNameCondition, clickedRecentlyCondition }, list.Id, null, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"Segment '{segment.Name}' created. Id: {segment.Id}").ConfigureAwait(false);

// UPDATE THE SEGMENT
var hotmailCondition = new SearchCondition { Field = "email", Operator = ConditionOperator.Contains, Value = "hotmail.com", LogicalOperator = LogicalOperator.None };
segment = await client.Segments.UpdateAsync(segment.Id, "StrongGrid Integration Testing: Recipients @ Hotmail", null, new[] { hotmailCondition }, null, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"Segment {segment.Id} updated. The new name is: '{segment.Name}'").ConfigureAwait(false);

// CREATE 3 CONTACTS
var contactId1 = await client.Contacts.CreateAsync("[email protected]", "Bob", "Dummy1", null, null, cancellationToken).ConfigureAwait(false);
var contactId2 = await client.Contacts.CreateAsync("[email protected]", "Bob", "Dummy2", null, null, cancellationToken).ConfigureAwait(false);
var contactId3 = await client.Contacts.CreateAsync("[email protected]", "Bob", "Dummy3", null, null, cancellationToken).ConfigureAwait(false);

// ADD THE CONTACTS TO THE LIST (THEY WILL AUTOMATICALLY BE INCLUDED IN THE HOTMAIL SEGMENT)
await client.Lists.AddRecipientAsync(list.Id, contactId1, null, CancellationToken.None).ConfigureAwait(false);
await client.Lists.AddRecipientsAsync(list.Id, new[] { contactId2, contactId3 }, null, CancellationToken.None).ConfigureAwait(false);

// REMOVE THE CONTACTS FROM THE LIST (THEY WILL AUTOMATICALLY BE REMOVED FROM THE HOTMAIL SEGMENT)
await client.Lists.RemoveRecipientAsync(list.Id, contactId3, null, CancellationToken.None).ConfigureAwait(false);
await client.Lists.RemoveRecipientsAsync(list.Id, new[] { contactId1, contactId2 }, null, CancellationToken.None).ConfigureAwait(false);

// DELETE THE CONTACTS
await client.Contacts.DeleteAsync(contactId2, null, cancellationToken).ConfigureAwait(false);
await client.Contacts.DeleteAsync(new[] { contactId1, contactId3 }, null, cancellationToken).ConfigureAwait(false);

// DELETE THE SEGMENT
await client.Segments.DeleteAsync(segment.Id, false, null, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"Segment {segment.Id} deleted").ConfigureAwait(false);

await client.Lists.DeleteAsync(firstList.Id, null, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"List {firstList.Id} deleted").ConfigureAwait(false);

await client.Lists.DeleteAsync(secondList.Id, null, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"List {secondList.Id} deleted").ConfigureAwait(false);
// DELETE THE LIST
await client.Lists.DeleteAsync(list.Id, null, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"List {list.Id} deleted").ConfigureAwait(false);
}

private static async Task CampaignsAndSenderIdentities(IClient client, TextWriter log, CancellationToken cancellationToken)
Expand Down Expand Up @@ -1213,21 +1224,21 @@ private static async Task EmailActivities(IClient client, TextWriter log, Cancel
{
await log.WriteLineAsync("\n***** EMAIL ACTIVITIES *****\n").ConfigureAwait(false);

// REQUEST THE ACTIVITIES
var allActivities = await client.EmailActivities.SearchAsync(null, 20, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"Activities requested. Found {allActivities.Count()} activities.").ConfigureAwait(false);
// REQUEST THE MOST RECENT ACTIVITIES
var recentActivities = await client.EmailActivities.SearchAsync(null, 20, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"Activities requested. Found {recentActivities.Count()} activities.").ConfigureAwait(false);

if (!allActivities.Any()) return;
if (!recentActivities.Any()) return;

// REQUEST THE ACTIVITIES FOR A SPECIFIC MESSAGE
var messageId = allActivities.First().MessageId;
// REQUEST THE EVENTS FOR A SPECIFIC MESSAGE
var messageId = recentActivities.First().MessageId;
var summary = await client.EmailActivities.GetMessageSummaryAsync(messageId, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"There are {summary.Events.Count()} events associated with message {summary.MessageId}.").ConfigureAwait(false);

// REQUEST THE ACTIVITIES OF A GIVEN TYPE
var activityType = allActivities.First().ActivityType;
var activities = await client.EmailActivities.SearchAsync(new SearchCriteriaEqual(FilterField.ActivityType, activityType), 20, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"There are {activities.Count()} '{activityType}' events.").ConfigureAwait(false);
// REQUEST THE ACTIVITIES OF A GIVEN STATUS
var activityStatus = recentActivities.First().Status;
var activities = await client.EmailActivities.SearchAsync(new SearchCriteriaEqual(FilterField.ActivityType, activityStatus), 20, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"There are {activities.Count()} '{activityStatus}' email activities.").ConfigureAwait(false);
}

// to get your public IP address we loop through an array
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public void Parse_json()
result.MessageId.ShouldBe("thtIPCIcR_iFZDws2JCrwA.filter0004p3las1-2776-5ACA5525-31.1");
result.Subject.ShouldBe("Dear customer");
result.To.ShouldBe("[email protected]");
result.ActivityType.ShouldBe(EventType.Delivered);
result.Status.ShouldBe(EmailActivityStatus.Delivered);
result.OpensCount.ShouldBe(2);
result.ClicksCount.ShouldBe(1);
result.LastEventOn.ShouldBe(new DateTime(2018, 04, 08, 17, 47, 18, DateTimeKind.Utc));
Expand Down
21 changes: 21 additions & 0 deletions Source/StrongGrid.UnitTests/Resources/ListsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -275,5 +275,26 @@ public async Task AddRecipientsAsync()
mockHttp.VerifyNoOutstandingExpectation();
mockHttp.VerifyNoOutstandingRequest();
}

[Fact]
public async Task RemoveRecipientsAsync()
{
// Arrange
var listId = 1;
var contactIds = new[] { "abc123", "def456" };

var mockHttp = new MockHttpMessageHandler();
mockHttp.Expect(HttpMethod.Delete, Utils.GetSendGridApiUri(ENDPOINT, listId, "recipients")).Respond(HttpStatusCode.NoContent);

var client = Utils.GetFluentClient(mockHttp);
var lists = new Lists(client);

// Act
await lists.RemoveRecipientsAsync(listId, contactIds, null, CancellationToken.None).ConfigureAwait(false);

// Assert
mockHttp.VerifyNoOutstandingExpectation();
mockHttp.VerifyNoOutstandingRequest();
}
}
}
31 changes: 31 additions & 0 deletions Source/StrongGrid/Models/BounceType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Runtime.Serialization;

namespace StrongGrid.Models
{
/// <summary>
/// Enumeration to indicate the type of bounce
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public enum BounceType
{
/// <summary>
/// Bounce
/// </summary>
[EnumMember(Value = "bounce")]
Bounce,

/// <summary>
/// Blocked
/// </summary>
[EnumMember(Value = "blocked")]
Blocked,

/// <summary>
/// Expired
/// </summary>
[EnumMember(Value = "expired")]
Expired
}
}
20 changes: 20 additions & 0 deletions Source/StrongGrid/Models/EmailActivities/BlockedEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Newtonsoft.Json;

namespace StrongGrid.Models.EmailActivities
{
/// <summary>
/// Message has been blocked.
/// </summary>
/// <seealso cref="StrongGrid.Models.EmailActivities.Event" />
public class BlockedEvent : Event
{
/// <summary>
/// Gets or sets the reason.
/// </summary>
/// <value>
/// The reason.
/// </value>
[JsonProperty("reason", NullValueHandling = NullValueHandling.Ignore)]
public string Reason { get; set; }
}
}
20 changes: 20 additions & 0 deletions Source/StrongGrid/Models/EmailActivities/BounceEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Newtonsoft.Json;

namespace StrongGrid.Models.EmailActivities
{
/// <summary>
/// Message has not been delivered.
/// </summary>
/// <seealso cref="StrongGrid.Models.EmailActivities.Event" />
public class BounceEvent : Event
{
/// <summary>
/// Gets or sets the type of bounce.
/// </summary>
/// <value>
/// The reason.
/// </value>
[JsonProperty("bounce_type", NullValueHandling = NullValueHandling.Ignore)]
public BounceType Type { get; set; }
}
}
29 changes: 29 additions & 0 deletions Source/StrongGrid/Models/EmailActivities/ClickEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Newtonsoft.Json;

namespace StrongGrid.Models.EmailActivities
{
/// <summary>
/// A link in the message has been clicked.
/// </summary>
/// <seealso cref="StrongGrid.Models.EmailActivities.Event" />
public class ClickEvent : Event
{
/// <summary>
/// Gets or sets the url the user clicked.
/// </summary>
/// <value>
/// The reason.
/// </value>
[JsonProperty("url", NullValueHandling = NullValueHandling.Ignore)]
public string Url { get; set; }

/// <summary>
/// Gets or sets the user agent.
/// </summary>
/// <value>
/// The user agent.
/// </value>
[JsonProperty("http_user_agent", NullValueHandling = NullValueHandling.Ignore)]
public string UserAgent { get; set; }
}
}
29 changes: 29 additions & 0 deletions Source/StrongGrid/Models/EmailActivities/DeferredEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Newtonsoft.Json;

namespace StrongGrid.Models.EmailActivities
{
/// <summary>
/// Message has been deferred.
/// </summary>
/// <seealso cref="StrongGrid.Models.EmailActivities.Event" />
public class DeferredEvent : Event
{
/// <summary>
/// Gets or sets the reason.
/// </summary>
/// <value>
/// The reason.
/// </value>
[JsonProperty("reason", NullValueHandling = NullValueHandling.Ignore)]
public string Reason { get; set; }

/// <summary>
/// Gets or sets the attempt number out of 10. One \"deferred\" entry will exists under events array for each time a message was deferred with error message from the server.
/// </summary>
/// <value>
/// The reason.
/// </value>
[JsonProperty("attempt_num", NullValueHandling = NullValueHandling.Ignore)]
public long AtemptNumber { get; set; }
}
}
10 changes: 10 additions & 0 deletions Source/StrongGrid/Models/EmailActivities/GroupResubscribeEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace StrongGrid.Models.EmailActivities
{
/// <summary>
/// Recipient has resubscribed to a group.
/// </summary>
/// <seealso cref="StrongGrid.Models.EmailActivities.Event" />
public class GroupResubscribeEvent : Event
{
}
}
10 changes: 10 additions & 0 deletions Source/StrongGrid/Models/EmailActivities/GroupUnsubscribeEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace StrongGrid.Models.EmailActivities
{
/// <summary>
/// Recipient has unsubscribed from a group.
/// </summary>
/// <seealso cref="StrongGrid.Models.EmailActivities.Event" />
public class GroupUnsubscribeEvent : Event
{
}
}
10 changes: 10 additions & 0 deletions Source/StrongGrid/Models/EmailActivities/SpamReportEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace StrongGrid.Models.EmailActivities
{
/// <summary>
/// Message has been reported as spam.
/// </summary>
/// <seealso cref="StrongGrid.Models.EmailActivities.Event" />
public class SpamReportEvent : Event
{
}
}
10 changes: 10 additions & 0 deletions Source/StrongGrid/Models/EmailActivities/UnsubscribeEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace StrongGrid.Models.EmailActivities
{
/// <summary>
/// Recipient has unsubscribed.
/// </summary>
/// <seealso cref="StrongGrid.Models.EmailActivities.Event" />
public class UnsubscribeEvent : Event
{
}
}
31 changes: 31 additions & 0 deletions Source/StrongGrid/Models/EmailActivityStatus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Runtime.Serialization;

namespace StrongGrid.Models
{
/// <summary>
/// Enumeration to indicate the status of the email activity
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public enum EmailActivityStatus
{
/// <summary>
/// Message has been received and is ready to be delivered
/// </summary>
[EnumMember(Value = "processed")]
Processed,

/// <summary>
/// Message has not been delivered
/// </summary>
[EnumMember(Value = "not_delivered")]
NotDelivered,

/// <summary>
/// Message has been successfully delivered to the receiving server.
/// </summary>
[EnumMember(Value = "delivered")]
Delivered
}
}
4 changes: 2 additions & 2 deletions Source/StrongGrid/Models/EmailMessageActivity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@ public class EmailMessageActivity
public string To { get; set; }

/// <summary>
/// Gets or sets the type of activity.
/// Gets or sets the status of the email activity.
/// </summary>
/// <value>
/// The status.
/// </value>
[JsonProperty("status", NullValueHandling = NullValueHandling.Ignore)]
public EventType ActivityType { get; set; }
public EmailActivityStatus Status { get; set; }

/// <summary>
/// Gets or sets the number of time the message was opened by the recipient.
Expand Down
Loading

0 comments on commit 0df4ad0

Please sign in to comment.