Skip to content

Commit

Permalink
Merge branch 'release/0.78.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
Jericho committed Apr 15, 2021
2 parents 42ae078 + 0af4aea commit f2bc5c4
Show file tree
Hide file tree
Showing 18 changed files with 286 additions and 121 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,10 @@ MigrationBackup/
# Fody - auto-generated XML schema
FodyWeavers.xsd

### VisualStudio Patch ###
# Additional files built by Visual Studio
*.tlog

# WinMerge
*.bak

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<AssemblyName>StrongGrid.IntegrationTests</AssemblyName>
<RootNamespace>StrongGrid.IntegrationTests</RootNamespace>
</PropertyGroup>
Expand All @@ -15,7 +15,7 @@
<PackageReference Include="Logzio.DotNet.NLog" Version="1.0.10" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.1" />
<PackageReference Include="NLog.Extensions.Logging" Version="1.7.0" />
<PackageReference Include="NLog.Extensions.Logging" Version="1.7.2" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,20 @@ public async Task RunAsync(IClient client, TextWriter log, CancellationToken can

if (contacts.Any())
{
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);
foreach (var record in batchById)
{
await log.WriteLineAsync($"\t{record.FirstName} {record.LastName}").ConfigureAwait(false);
}

var batchByEmailAddress = await client.Contacts.GetMultipleByEmailAddressAsync(contacts.Take(10).Select(c => c.Email), cancellationToken).ConfigureAwait(false);
await log.WriteLineAsync($"Retrieved {batchByEmailAddress.Length} contacts by email address in a single API call.").ConfigureAwait(false);
foreach (var record in batchByEmailAddress)
{
await log.WriteLineAsync($"\t{record.FirstName} {record.LastName}").ConfigureAwait(false);
}

var contact = await client.Contacts.GetAsync(contacts.First().Id).ConfigureAwait(false);
await log.WriteLineAsync($"Retrieved contact {contact.Id}").ConfigureAwait(false);
await log.WriteLineAsync($"\tEmail: {contact.Email}").ConfigureAwait(false);
Expand Down
1 change: 1 addition & 0 deletions Source/StrongGrid.IntegrationTests/Tests/Mail.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public async Task RunAsync(IBaseClient client, TextWriter log, CancellationToken
{
new MailPersonalization
{
From = new MailAddress("[email protected]", "Alternate Sender"),
To = new[] { to1, to1 },
Cc = new[] { to1 },
Bcc = new[] { to1 },
Expand Down
6 changes: 3 additions & 3 deletions Source/StrongGrid.UnitTests/StrongGrid.UnitTests.csproj
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net461;net472;netcoreapp3.1</TargetFrameworks>
<TargetFrameworks>net461;net472;net5.0</TargetFrameworks>
<AssemblyName>StrongGrid.UnitTests</AssemblyName>
<RootNamespace>StrongGrid.UnitTests</RootNamespace>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" />
<PackageReference Include="Moq" Version="4.15.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
<PackageReference Include="Moq" Version="4.16.1" />
<PackageReference Include="RichardSzalay.MockHttp" Version="6.0.0" />
<PackageReference Include="Shouldly" Version="4.0.3" />
<PackageReference Include="xunit" Version="2.4.1" />
Expand Down
8 changes: 1 addition & 7 deletions Source/StrongGrid/BaseClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ public BaseClient(string apiKey, HttpClient httpClient, bool disposeClient, Stro
{
_mustDisposeHttpClient = disposeClient;
_httpClient = httpClient;
_options = options ?? GetDefaultOptions();
_options = options;
_logger = logger ?? NullLogger.Instance;

_fluentClient = new FluentClient(new Uri(SENDGRID_V3_BASE_URI), httpClient)
Expand Down Expand Up @@ -337,12 +337,6 @@ public BaseClient(string apiKey, HttpClient httpClient, bool disposeClient, Stro

#region PUBLIC METHODS

/// <summary>
/// When overridden in a derived class, returns the default options.
/// </summary>
/// <returns>The default options.</returns>
public abstract StrongGridClientOptions GetDefaultOptions();

/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
Expand Down
31 changes: 10 additions & 21 deletions Source/StrongGrid/Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ namespace StrongGrid
/// </summary>
public class Client : BaseClient, IClient
{
private static readonly StrongGridClientOptions _defaultOptions = new StrongGridClientOptions()
{
LogLevelSuccessfulCalls = LogLevel.Debug,
LogLevelFailedCalls = LogLevel.Error
};

#region PROPERTIES

/// <summary>
Expand Down Expand Up @@ -72,7 +78,7 @@ public class Client : BaseClient, IClient
/// <param name="options">Options for the SendGrid client.</param>
/// <param name="logger">Logger.</param>
public Client(string apiKey, StrongGridClientOptions options = null, ILogger logger = null)
: base(apiKey, null, false, options, logger)
: base(apiKey, null, false, options ?? _defaultOptions, logger)
{
Init();
}
Expand All @@ -85,7 +91,7 @@ public Client(string apiKey, StrongGridClientOptions options = null, ILogger log
/// <param name="options">Options for the SendGrid client.</param>
/// <param name="logger">Logger.</param>
public Client(string apiKey, IWebProxy proxy, StrongGridClientOptions options = null, ILogger logger = null)
: base(apiKey, new HttpClient(new HttpClientHandler { Proxy = proxy, UseProxy = proxy != null }), true, options, logger)
: base(apiKey, new HttpClient(new HttpClientHandler { Proxy = proxy, UseProxy = proxy != null }), true, options ?? _defaultOptions, logger)
{
Init();
}
Expand All @@ -98,7 +104,7 @@ public Client(string apiKey, IWebProxy proxy, StrongGridClientOptions options =
/// <param name="options">Options for the SendGrid client.</param>
/// <param name="logger">Logger.</param>
public Client(string apiKey, HttpMessageHandler handler, StrongGridClientOptions options = null, ILogger logger = null)
: base(apiKey, new HttpClient(handler), true, options, logger)
: base(apiKey, new HttpClient(handler), true, options ?? _defaultOptions, logger)
{
Init();
}
Expand All @@ -111,30 +117,13 @@ public Client(string apiKey, HttpMessageHandler handler, StrongGridClientOptions
/// <param name="options">Options for the SendGrid client.</param>
/// <param name="logger">Logger.</param>
public Client(string apiKey, HttpClient httpClient, StrongGridClientOptions options = null, ILogger logger = null)
: base(apiKey, httpClient, false, options, logger)
: base(apiKey, httpClient, false, options ?? _defaultOptions, logger)
{
Init();
}

#endregion

#region PUBLIC METHODS

/// <summary>
/// Return the default options.
/// </summary>
/// <returns>The default options.</returns>
public override StrongGridClientOptions GetDefaultOptions()
{
return new StrongGridClientOptions()
{
LogLevelSuccessfulCalls = LogLevel.Debug,
LogLevelFailedCalls = LogLevel.Error
};
}

#endregion

#region PRIVATE METHODS

private void Init()
Expand Down
62 changes: 45 additions & 17 deletions Source/StrongGrid/Extensions/Internal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
Expand All @@ -22,30 +23,45 @@ namespace StrongGrid
/// </summary>
internal static class Internal
{
internal enum UnixTimePrecision
{
Seconds = 0,
Milliseconds = 1
}

private static readonly DateTime EPOCH = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

/// <summary>
/// Converts a 'unix time' (which is expressed as the number of seconds since midnight on
/// January 1st 1970) to a .Net <see cref="DateTime" />.
/// Converts a 'unix time' (which is expressed as the number of seconds/milliseconds since
/// midnight on January 1st 1970) to a .Net <see cref="DateTime" />.
/// </summary>
/// <param name="unixTime">The unix time.</param>
/// <param name="precision">The desired precision.</param>
/// <returns>
/// The <see cref="DateTime" />.
/// </returns>
internal static DateTime FromUnixTime(this long unixTime)
internal static DateTime FromUnixTime(this long unixTime, UnixTimePrecision precision = UnixTimePrecision.Seconds)
{
return Utils.Epoch.AddSeconds(unixTime);
if (precision == UnixTimePrecision.Seconds) return EPOCH.AddSeconds(unixTime);
if (precision == UnixTimePrecision.Milliseconds) return EPOCH.AddMilliseconds(unixTime);
throw new Exception($"Unknown precision: {precision}");
}

/// <summary>
/// Converts a .Net <see cref="DateTime" /> into a 'Unix time' (which is expressed as the number
/// of seconds since midnight on January 1st 1970).
/// of seconds/milliseconds since midnight on January 1st 1970).
/// </summary>
/// <param name="date">The date.</param>
/// <param name="precision">The desired precision.</param>
/// <returns>
/// The numer of seconds since midnight on January 1st 1970.
/// The numer of seconds/milliseconds since midnight on January 1st 1970.
/// </returns>
internal static long ToUnixTime(this DateTime date)
internal static long ToUnixTime(this DateTime date, UnixTimePrecision precision = UnixTimePrecision.Seconds)
{
return Convert.ToInt64((date.ToUniversalTime() - Utils.Epoch).TotalSeconds);
var diff = date.ToUniversalTime() - EPOCH;
if (precision == UnixTimePrecision.Seconds) return Convert.ToInt64(diff.TotalSeconds);
if (precision == UnixTimePrecision.Milliseconds) return Convert.ToInt64(diff.TotalMilliseconds);
throw new Exception($"Unknown precision: {precision}");
}

/// <summary>
Expand Down Expand Up @@ -279,16 +295,16 @@ internal static async Task<PaginatedResponse<T>> AsPaginatedResponse<T>(this IRe
internal static IRequest WithJsonBody<T>(this IRequest request, T body, bool omitCharSet = false)
{
return request.WithBody(bodyBuilder =>
{
var httpContent = bodyBuilder.Model(body, new MediaTypeHeaderValue("application/json"));
{
var httpContent = bodyBuilder.Model(body, new MediaTypeHeaderValue("application/json"));

if (omitCharSet && !string.IsNullOrEmpty(httpContent.Headers.ContentType.CharSet))
{
httpContent.Headers.ContentType.CharSet = string.Empty;
}
if (omitCharSet && !string.IsNullOrEmpty(httpContent.Headers.ContentType.CharSet))
{
httpContent.Headers.ContentType.CharSet = string.Empty;
}

return httpContent;
});
return httpContent;
});
}

/// <summary>
Expand Down Expand Up @@ -652,6 +668,18 @@ internal static void CheckForSendGridErrors(this IResponse response)
}
}

internal static async Task<Stream> CompressAsync(this Stream source)
{
var compressedStream = new MemoryStream();
using (var gzip = new GZipStream(compressedStream, CompressionMode.Compress, true))
{
await source.CopyToAsync(gzip).ConfigureAwait(false);
}

compressedStream.Position = 0;
return compressedStream;
}

private static async Task<(bool, string)> GetErrorMessage(HttpResponseMessage message)
{
// Assume there is no error
Expand Down Expand Up @@ -696,7 +724,7 @@ internal static void CheckForSendGridErrors(this IResponse response)
}
I have also seen cases where the JSON string looks like this:
{
{
"error": "Name already exists"
}
*/
Expand Down
31 changes: 10 additions & 21 deletions Source/StrongGrid/LegacyClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ namespace StrongGrid
/// </summary>
public class LegacyClient : BaseClient, ILegacyClient
{
private static readonly StrongGridClientOptions _defaultOptions = new StrongGridClientOptions()
{
LogLevelSuccessfulCalls = LogLevel.Debug,
LogLevelFailedCalls = LogLevel.Debug
};

#region PROPERTIES

/// <summary>
Expand Down Expand Up @@ -79,7 +85,7 @@ public class LegacyClient : BaseClient, ILegacyClient
/// <param name="options">Options for the SendGrid client.</param>
/// <param name="logger">Logger.</param>
public LegacyClient(string apiKey, StrongGridClientOptions options = null, ILogger logger = null)
: base(apiKey, null, false, options, logger)
: base(apiKey, null, false, options ?? _defaultOptions, logger)
{
Init();
}
Expand All @@ -92,7 +98,7 @@ public LegacyClient(string apiKey, StrongGridClientOptions options = null, ILogg
/// <param name="options">Options for the SendGrid client.</param>
/// <param name="logger">Logger.</param>
public LegacyClient(string apiKey, IWebProxy proxy, StrongGridClientOptions options = null, ILogger logger = null)
: base(apiKey, new HttpClient(new HttpClientHandler { Proxy = proxy, UseProxy = proxy != null }), true, options, logger)
: base(apiKey, new HttpClient(new HttpClientHandler { Proxy = proxy, UseProxy = proxy != null }), true, options ?? _defaultOptions, logger)
{
Init();
}
Expand All @@ -105,7 +111,7 @@ public LegacyClient(string apiKey, IWebProxy proxy, StrongGridClientOptions opti
/// <param name="options">Options for the SendGrid client.</param>
/// <param name="logger">Logger.</param>
public LegacyClient(string apiKey, HttpMessageHandler handler, StrongGridClientOptions options = null, ILogger logger = null)
: base(apiKey, new HttpClient(handler), true, options, logger)
: base(apiKey, new HttpClient(handler), true, options ?? _defaultOptions, logger)
{
Init();
}
Expand All @@ -118,30 +124,13 @@ public LegacyClient(string apiKey, HttpMessageHandler handler, StrongGridClientO
/// <param name="options">Options for the SendGrid client.</param>
/// <param name="logger">Logger.</param>
public LegacyClient(string apiKey, HttpClient httpClient, StrongGridClientOptions options = null, ILogger logger = null)
: base(apiKey, httpClient, false, options, logger)
: base(apiKey, httpClient, false, options ?? _defaultOptions, logger)
{
Init();
}

#endregion

#region PUBLIC METHODS

/// <summary>
/// Return the default options.
/// </summary>
/// <returns>The default options.</returns>
public override StrongGridClientOptions GetDefaultOptions()
{
return new StrongGridClientOptions()
{
LogLevelSuccessfulCalls = LogLevel.Debug,
LogLevelFailedCalls = LogLevel.Debug
};
}

#endregion

#region PRIVATE METHODS

private void Init()
Expand Down
12 changes: 11 additions & 1 deletion Source/StrongGrid/Models/MailPersonalization.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Newtonsoft.Json;
using Newtonsoft.Json;
using StrongGrid.Utilities;
using System;
using System.Collections.Generic;
Expand All @@ -13,6 +13,16 @@ namespace StrongGrid.Models
/// </summary>
public class MailPersonalization
{
/// <summary>
/// Gets or sets the 'From' email address used to deliver the message.
/// This address should be a verified sender in your Twilio SendGrid account.
/// </summary>
/// <value>
/// From.
/// </value>
[JsonProperty("from", NullValueHandling = NullValueHandling.Ignore)]
public MailAddress From { get; set; }

/// <summary>
/// Gets or sets an array of recipients.
/// Each <see cref="MailAddress"/> object within this array may contain the recipient’s
Expand Down
3 changes: 3 additions & 0 deletions Source/StrongGrid/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

Expand All @@ -9,3 +10,5 @@
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

[assembly: CLSCompliant(true)]
Loading

0 comments on commit f2bc5c4

Please sign in to comment.