Skip to content

Commit

Permalink
Merge branch 'release/0.109.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
Jericho committed Jun 19, 2024
2 parents 961e63e + db3bdd8 commit 467f64b
Show file tree
Hide file tree
Showing 38 changed files with 1,099 additions and 266 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,13 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Logzio.DotNet.NLog" Version="1.1.1" />
<PackageReference Include="Logzio.DotNet.NLog" Version="1.2.0" />
<PackageReference Include="Microsoft.ApplicationInsights.NLogTarget" Version="2.22.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.1" />
<PackageReference Include="NLog.Extensions.Logging" Version="5.3.11" />

<!-- This is a workaround for the problem described here: https://github.com/logzio/logzio-dotnet/issues/72 -->
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="8.0.1" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public async Task RunAsync(IClient client, TextWriter log, CancellationToken can
await log.WriteLineAsync($"\t{record.FirstName} {record.LastName}").ConfigureAwait(false);
}

if (contacts.Any())
if (contacts.Length > 0)
{
var batchById = await client.Contacts.GetMultipleAsync(contacts.Take(10).Select(c => c.Id), cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"Retrieved {batchById.Length} contacts by ID in a single API call.").ConfigureAwait(false);
Expand All @@ -98,7 +98,7 @@ public async Task RunAsync(IClient client, TextWriter log, CancellationToken can
await log.WriteLineAsync($"\t{record.FirstName} {record.LastName}").ConfigureAwait(false);
}

var contact = await client.Contacts.GetAsync(contacts.First().Id).ConfigureAwait(false);
var contact = await client.Contacts.GetAsync(contacts.First().Id, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"Retrieved contact {contact.Id}").ConfigureAwait(false);
await log.WriteLineAsync($"\tEmail: {contact.Email}").ConfigureAwait(false);
await log.WriteLineAsync($"\tFirst Name: {contact.FirstName}").ConfigureAwait(false);
Expand All @@ -124,6 +124,10 @@ public async Task RunAsync(IClient client, TextWriter log, CancellationToken can
var searchResult = await client.Contacts.SearchAsync(new[] { firstNameCriteria, LastNameCriteria }, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"Found {searchResult.Length} contacts named John Doe").ConfigureAwait(false);

var modifiedDuringPriorYearCriteria = new SearchCriteriaGreaterThan(ContactsFilterField.ModifiedOn, DateTime.UtcNow.AddYears(-1));
searchResult = await client.Contacts.SearchAsync(modifiedDuringPriorYearCriteria, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"Found {searchResult.Length} contacts modified during the last year").ConfigureAwait(false);

var (totalCount, billableCount) = await client.Contacts.GetCountAsync(cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync("Record counts").ConfigureAwait(false);
await log.WriteLineAsync($"\tTotal: {totalCount}").ConfigureAwait(false);
Expand Down Expand Up @@ -176,15 +180,15 @@ public async Task RunAsync(IClient client, TextWriter log, CancellationToken can
}

// Make sure we don't loop indefinetly
if (elapsed.Elapsed >= TimeSpan.FromSeconds(5))
if (elapsed.Elapsed >= TimeSpan.FromSeconds(10))
{
elapsed.Stop();
await log.WriteLineAsync("\tThe job did not complete in a reasonable amount of time.").ConfigureAwait(false);
break;
}
}

if (contacts.Any())
if (contacts.Length > 0)
{
var contact = contacts.First();
await client.Contacts.DeleteAsync(contact.Id, cancellationToken).ConfigureAwait(false);
Expand Down
28 changes: 21 additions & 7 deletions Source/StrongGrid.IntegrationTests/Tests/ListsAndSegments.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using StrongGrid.Models;
using StrongGrid.Models.Search;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -72,17 +73,15 @@ public async Task RunAsync(IClient client, TextWriter log, CancellationToken can
{
new KeyValuePair<SearchLogicalOperator, IEnumerable<ISearchCriteria>>(SearchLogicalOperator.And, new[]
{
new SearchCriteriaEqual(ContactsFilterField.FirstName, "Jane"),
new SearchCriteriaEqual(ContactsFilterField.LastName, "Doe")
new SearchCriteriaLike(ContactsFilterField.EmailAddress, "%hotmail.com")
})
};
var segment = await client.Segments.CreateAsync("StrongGrid Integration Testing: First Name is Jane and last name is Doe", filterConditions, list.Id, cancellationToken).ConfigureAwait(false);
var segment = await client.Segments.CreateAsync("StrongGrid Integration Testing: Recipients @ Hotmail", filterConditions, list.Id, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"Segment '{segment.Name}' created. Id: {segment.Id}").ConfigureAwait(false);

// UPDATE THE SEGMENT (three contacts match the criteria)
var hotmailCriteria = new SearchCriteriaLike(ContactsFilterField.EmailAddress, "%hotmail.com");
segment = await client.Segments.UpdateAsync(segment.Id, "StrongGrid Integration Testing: Recipients @ Hotmail", hotmailCriteria, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"Segment {segment.Id} updated. The new name is: '{segment.Name}'").ConfigureAwait(false);
// PLEASE NOTE: you must wait at least 5 minutes before updating a segment.
// If you attempt to update a segment too quickly, the SendGrid API will throw the following exception:
// "Update request came too soon, please wait 5 minutes before trying again"

// GET THE SEGMENT
segment = await client.Segments.GetAsync(segment.Id, cancellationToken).ConfigureAwait(false);
Expand All @@ -91,6 +90,17 @@ public async Task RunAsync(IClient client, TextWriter log, CancellationToken can
// GET THE CONTACTS
contacts = await client.Contacts.GetMultipleByEmailAddressAsync(new[] { "[email protected]", "[email protected]", "[email protected]" }, cancellationToken).ConfigureAwait(false);

// CREATE ANOTHER SEGMENT
filterConditions = new[]
{
new KeyValuePair<SearchLogicalOperator, IEnumerable<ISearchCriteria>>(SearchLogicalOperator.And, new[]
{
new SearchCriteriaGreaterThan(ContactsFilterField.ModifiedOn, DateTime.UtcNow.AddYears(-1)),
})
};
var anotherSegment = await client.Segments.CreateAsync("StrongGrid Integration Testing: Modified in the prior year", filterConditions, list.Id, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"Segment '{anotherSegment.Name}' created. Id: {anotherSegment.Id}").ConfigureAwait(false);

// REMOVE THE CONTACTS FROM THE LIST (THEY WILL AUTOMATICALLY BE REMOVED FROM THE HOTMAIL SEGMENT)
if (contacts.Any())
{
Expand All @@ -109,6 +119,10 @@ public async Task RunAsync(IClient client, TextWriter log, CancellationToken can
await client.Segments.DeleteAsync(segment.Id, false, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"Segment {segment.Id} deleted").ConfigureAwait(false);

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

// DELETE THE LIST
await client.Lists.DeleteAsync(list.Id, false, cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"List {list.Id} deleted").ConfigureAwait(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public async Task SearchMessages_without_criteria()
var limit = 25;

var mockHttp = new MockHttpMessageHandler();
mockHttp.Expect(HttpMethod.Get, Utils.GetSendGridApiUri(ENDPOINT) + $"?limit={limit}&query=").Respond("application/json", NO_MESSAGES_FOUND);
mockHttp.Expect(HttpMethod.Get, Utils.GetSendGridApiUri(ENDPOINT) + $"?limit={limit}").Respond("application/json", NO_MESSAGES_FOUND);

var client = Utils.GetFluentClient(mockHttp);
var emailActivities = (IEmailActivities)new EmailActivities(client);
Expand Down
8 changes: 4 additions & 4 deletions Source/StrongGrid.UnitTests/StrongGrid.UnitTests.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net48;net6.0;net7.0</TargetFrameworks>
Expand Down Expand Up @@ -42,13 +42,13 @@
</ItemGroup>

<ItemGroup>
<None Update="InboudEmailTestData\email_with_attachments.txt">
<None Update="InboundEmailTestData\email_with_attachments.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="InboudEmailTestData\raw_email_with_attachments.txt">
<None Update="InboundEmailTestData\raw_email_with_attachments.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="InboudEmailTestData\raw_email.txt">
<None Update="InboundEmailTestData\raw_email.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
Expand Down
66 changes: 52 additions & 14 deletions Source/StrongGrid.UnitTests/Utilities/QueryDslTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@

namespace StrongGrid.UnitTests.Utilities
{
public class QueryDslTests
public class QueryDsl
{
public class ToQueryDslVersion2
public class Version2Tests
{
[Fact]
public void One_condition_with_two_criteria()
Expand All @@ -28,7 +28,7 @@ public void One_condition_with_two_criteria()
var result = StrongGrid.Utilities.Utils.ToQueryDslVersion2(filter);

// Assert
result.ShouldBe("SELECT contacts.contact_id, contacts.updated_at FROM contact_data AS contacts WHERE contacts.first_name='John' AND contacts.last_name='Doe'");
result.ShouldBe("SELECT c.contact_id, c.updated_at FROM contact_data AS c WHERE c.first_name='John' AND c.last_name='Doe'");
}

[Fact]
Expand All @@ -41,7 +41,7 @@ public void All_contacts()
var result = StrongGrid.Utilities.Utils.ToQueryDslVersion2(filter);

// Assert
result.ShouldBe("SELECT contacts.contact_id, contacts.updated_at FROM contact_data AS contacts");
result.ShouldBe("SELECT c.contact_id, c.updated_at FROM contact_data AS c");
}

[Fact]
Expand All @@ -60,7 +60,7 @@ public void All_contacts_with_firstname_Dave()
var result = StrongGrid.Utilities.Utils.ToQueryDslVersion2(filter);

// Assert
result.ShouldBe("SELECT contacts.contact_id, contacts.updated_at FROM contact_data AS contacts WHERE contacts.first_name='Dave'");
result.ShouldBe("SELECT c.contact_id, c.updated_at FROM contact_data AS c WHERE c.first_name='Dave'");
}

[Fact]
Expand All @@ -79,7 +79,7 @@ public void All_contacts_in_Colorado()
var result = StrongGrid.Utilities.Utils.ToQueryDslVersion2(filter);

// Assert
result.ShouldBe("SELECT contacts.contact_id, contacts.updated_at FROM contact_data AS contacts WHERE contacts.state_province_region='CO'");
result.ShouldBe("SELECT c.contact_id, c.updated_at FROM contact_data AS c WHERE c.state_province_region='CO'");
}

[Fact]
Expand All @@ -98,7 +98,7 @@ public void All_contacts_at_gmail()
var result = StrongGrid.Utilities.Utils.ToQueryDslVersion2(filter);

// Assert
result.ShouldBe("SELECT contacts.contact_id, contacts.updated_at FROM contact_data AS contacts WHERE contacts.email LIKE '%gmail.com%'");
result.ShouldBe("SELECT c.contact_id, c.updated_at FROM contact_data AS c WHERE c.email LIKE '%gmail.com%'");
}

[Fact]
Expand All @@ -117,7 +117,7 @@ public void All_contacts_with_custom_text_field()
var result = StrongGrid.Utilities.Utils.ToQueryDslVersion2(filter);

// Assert
result.ShouldBe("SELECT contacts.contact_id, contacts.updated_at FROM contact_data AS contacts WHERE contacts.my_text_custom_field='abc'");
result.ShouldBe("SELECT c.contact_id, c.updated_at FROM contact_data AS c WHERE c.my_text_custom_field='abc'");
}

[Fact]
Expand All @@ -136,7 +136,7 @@ public void All_contacts_with_custom_number_field()
var result = StrongGrid.Utilities.Utils.ToQueryDslVersion2(filter);

// Assert
result.ShouldBe("SELECT contacts.contact_id, contacts.updated_at FROM contact_data AS contacts WHERE contacts.my_number_custom_field=12");
result.ShouldBe("SELECT c.contact_id, c.updated_at FROM contact_data AS c WHERE c.my_number_custom_field=12");
}

[Fact]
Expand All @@ -155,7 +155,7 @@ public void All_contacts_with_custom_date_field()
var result = StrongGrid.Utilities.Utils.ToQueryDslVersion2(filter);

// Assert
result.ShouldBe("SELECT contacts.contact_id, contacts.updated_at FROM contact_data AS contacts WHERE contacts.my_date_custom_field='2021-01-01T12:46:24Z'");
result.ShouldBe("SELECT c.contact_id, c.updated_at FROM contact_data AS c WHERE c.my_date_custom_field='2021-01-01T12:46:24Z'");
}

[Fact]
Expand All @@ -174,7 +174,7 @@ public void All_contacts_where_alternate_email_contains()
var result = StrongGrid.Utilities.Utils.ToQueryDslVersion2(filter);

// Assert
result.ShouldBe("SELECT contacts.contact_id, contacts.updated_at FROM contact_data AS contacts WHERE array_contains(contacts.alternate_emails,'[email protected]')");
result.ShouldBe("SELECT c.contact_id, c.updated_at FROM contact_data AS c WHERE array_contains(c.alternate_emails,'[email protected]')");
}

[Fact]
Expand All @@ -193,7 +193,7 @@ public void All_contacts_member_of_either_of_lists()
var result = StrongGrid.Utilities.Utils.ToQueryDslVersion2(filter);

// Assert
result.ShouldBe("SELECT contacts.contact_id, contacts.updated_at FROM contact_data AS contacts WHERE array_contains(contacts.list_ids,['aaa','bbb'])");
result.ShouldBe("SELECT c.contact_id, c.updated_at FROM contact_data AS c WHERE array_contains(c.list_ids,['aaa','bbb'])");
}

[Fact]
Expand All @@ -213,11 +213,30 @@ public void All_contacts_not_Dave_or_first_name_is_null()
var result = StrongGrid.Utilities.Utils.ToQueryDslVersion2(filter);

// Assert
result.ShouldBe("SELECT contacts.contact_id, contacts.updated_at FROM contact_data AS contacts WHERE contacts.first_name!='Dave' OR contacts.first_name IS NULL");
result.ShouldBe("SELECT c.contact_id, c.updated_at FROM contact_data AS c WHERE c.first_name!='Dave' OR c.first_name IS NULL");
}

[Fact]
public void All_contacts_modified_before_given_date()
{
// Arrange
var filter = new[]
{
new KeyValuePair<SearchLogicalOperator, IEnumerable<ISearchCriteria>>(SearchLogicalOperator.And, new[]
{
new SearchCriteriaLessThan(ContactsFilterField.ModifiedOn, new DateTime(2024, 6, 19, 0, 0, 0, DateTimeKind.Utc))
})
};

// Act
var result = StrongGrid.Utilities.Utils.ToQueryDslVersion2(filter);

// Assert
result.ShouldBe("SELECT c.contact_id, c.updated_at FROM contact_data AS c WHERE c.updated_at<'2024-06-19T00:00:00Z'");
}
}

public class ToQueryDslVersion1
public class Version1Tests
{
[Fact]
public void Filter_by_subject()
Expand Down Expand Up @@ -275,6 +294,25 @@ public void Filter_by_bounced_email()
// Assert
result.ShouldBe("status=\"bounce\"");
}

[Fact]
public void Contacts_modified_prior_to_given_date()
{
// Arrange
var filter = new[]
{
new KeyValuePair<SearchLogicalOperator, IEnumerable<ISearchCriteria>>(SearchLogicalOperator.And, new[]
{
new SearchCriteriaLessThan(ContactsFilterField.ModifiedOn, new DateTime(2024, 6, 19, 0, 0, 0, DateTimeKind.Utc)),
})
};

// Act
var result = StrongGrid.Utilities.Utils.ToQueryDslVersion1(filter);

// Assert
result.ShouldBe("updated_at<TIMESTAMP \"2024-06-19T00:00:00Z\"");
}
}
}
}
6 changes: 3 additions & 3 deletions Source/StrongGrid.UnitTests/WebhookParserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ public async Task InboundEmailAsync()
[Fact]
public async Task InboundEmailWithAttachmentsAsync()
{
using (var fileStream = File.OpenRead("InboudEmailTestData/email_with_attachments.txt"))
using (var fileStream = File.OpenRead("InboundEmailTestData/email_with_attachments.txt"))
{
var parser = new WebhookParser();
var inboundEmail = await parser.ParseInboundEmailWebhookAsync(fileStream);
Expand Down Expand Up @@ -555,7 +555,7 @@ public async Task InboundEmailRawContentAsync()
{
// Arrange
var parser = new WebhookParser();
using (var fileStream = File.OpenRead("InboudEmailTestData/raw_email.txt"))
using (var fileStream = File.OpenRead("InboundEmailTestData/raw_email.txt"))
{
// Act
var inboundEmail = await parser.ParseInboundEmailWebhookAsync(fileStream);
Expand All @@ -580,7 +580,7 @@ public async Task InboundEmailRawContent_with_attachments_Async()
{
// Arrange
var parser = new WebhookParser();
using (var fileStream = File.OpenRead("InboudEmailTestData/raw_email_with_attachments.txt"))
using (var fileStream = File.OpenRead("InboundEmailTestData/raw_email_with_attachments.txt"))
{
// Act
var inboundEmail = await parser.ParseInboundEmailWebhookAsync(fileStream);
Expand Down
20 changes: 18 additions & 2 deletions Source/StrongGrid/Extensions/Public.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1052,7 +1052,7 @@ public static Task<WarmupResult> SendToMultipleRecipientsAsync(
/// </summary>
/// <param name="emailActivities">The email activities resource.</param>
/// <param name="criteria">Filtering criteria.</param>
/// <param name="limit">Number of IP activity entries to return.</param>
/// <param name="limit">Maximum number of activity entries to return.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>
/// An array of <see cref="EmailMessageActivity" />.
Expand All @@ -1068,7 +1068,7 @@ public static Task<EmailMessageActivity[]> SearchAsync(this IEmailActivities ema
/// </summary>
/// <param name="emailActivities">The email activities resource.</param>
/// <param name="filterConditions">Filtering conditions.</param>
/// <param name="limit">Number of IP activity entries to return.</param>
/// <param name="limit">Maximum number of activity entries to return.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>
/// An array of <see cref="EmailMessageActivity" />.
Expand All @@ -1080,6 +1080,22 @@ public static Task<EmailMessageActivity[]> SearchAsync(this IEmailActivities ema
return emailActivities.SearchAsync(filters, limit, cancellationToken);
}

/// <summary>
/// Get all of the details about the messages matching the criteria.
/// </summary>
/// <param name="emailActivities">The email activities resource.</param>
/// <param name="filterConditions">Filtering conditions.</param>
/// <param name="limit">Maximum number of activity entries to return.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>
/// An array of <see cref="Contact" />.
/// </returns>
public static Task<EmailMessageActivity[]> SearchAsync(this IEmailActivities emailActivities, IEnumerable<KeyValuePair<SearchLogicalOperator, IEnumerable<ISearchCriteria>>> filterConditions, int limit = 20, CancellationToken cancellationToken = default)
{
var query = Utils.ToQueryDslVersion1(filterConditions);
return emailActivities.SearchAsync(query, limit, cancellationToken);
}

/// <summary>
/// Get all of the details about the contacts matching the criteria.
/// </summary>
Expand Down
Loading

0 comments on commit 467f64b

Please sign in to comment.