Skip to content

Commit

Permalink
Merge branch 'release/0.72.0' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
Jericho committed Sep 13, 2020
2 parents 924bb9e + b7dc641 commit 4d82216
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 30 deletions.
2 changes: 1 addition & 1 deletion Source/StrongGrid.IntegrationTests/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace StrongGrid.IntegrationTests
{
public class Program
{
public static async Task<int> Main(string[] args)
public static async Task<int> Main()
{
var services = new ServiceCollection();
ConfigureServices(services);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@

<ItemGroup>
<PackageReference Include="Logzio.DotNet.NLog" Version="1.0.10" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.5" />
<PackageReference Include="NLog.Extensions.Logging" Version="1.6.4" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.8" />
<PackageReference Include="NLog.Extensions.Logging" Version="1.6.5" />
</ItemGroup>

<ItemGroup>
Expand Down
10 changes: 3 additions & 7 deletions Source/StrongGrid.UnitTests/StrongGrid.UnitTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
<PackageReference Include="Moq" Version="4.14.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
<PackageReference Include="Moq" Version="4.14.5" />
<PackageReference Include="RichardSzalay.MockHttp" Version="6.0.0" />
<PackageReference Include="Shouldly" Version="3.0.2" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.2">
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand All @@ -22,10 +22,6 @@
<ProjectReference Include="..\StrongGrid\StrongGrid.csproj" />
</ItemGroup>

<ItemGroup>
<Folder Include="InboudEmailTestData\" />
</ItemGroup>

<ItemGroup>
<None Update="InboudEmailTestData\raw_data.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
Expand Down
73 changes: 73 additions & 0 deletions Source/StrongGrid.UnitTests/WebhookParserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,55 @@ Bob Smith<[email protected]>
--xYzZY
Content-Disposition: form-data; name=""attachments""
0
--xYzZY--";

private const string INBOUND_EMAIL_UNUSUAL_ENCODING_WEBHOOK = @"--xYzZY
Content-Disposition: form-data; name=""dkim""
{@hotmail.com : pass}
--xYzZY
Content-Disposition: form-data; name=""envelope""
{""to"":[""[email protected]""],""from"":""[email protected]""}
--xYzZY
Content-Disposition: form-data; name=""subject""
Test #1
--xYzZY
Content-Disposition: form-data; name=""charsets""
{""to"":""UTF-8"",""html"":""us-ascii"",""subject"":""UTF-8"",""from"":""UTF-8"",""text"":""iso-8859-10""}
--xYzZY
Content-Disposition: form-data; name=""SPF""
softfail
--xYzZY
Content-Disposition: form-data; name=""to""
""Test Recipient"" <[email protected]>
--xYzZY
Content-Disposition: form-data; name=""html""
<html><body><strong>Hello SendGrid!</body></html>
--xYzZY
Content-Disposition: form-data; name=""from""
Bob Smith<[email protected]>
--xYzZY
Content-Disposition: form-data; name=""text""
Hello SendGrid!
--xYzZY
Content-Disposition: form-data; name=""sender_ip""
10.43.24.23
--xYzZY
Content-Disposition: form-data; name=""attachments""
0
--xYzZY--";

Expand Down Expand Up @@ -503,6 +552,30 @@ public async Task RawPayloadWithAttachmentsAsync()
}
}

[Fact]
public void InboundEmail_with_unusual_encoding()
{
// Arrange
var parser = new WebhookParser();
using (var stream = GetStream(INBOUND_EMAIL_UNUSUAL_ENCODING_WEBHOOK))
{
// Act
var inboundEmail = parser.ParseInboundEmailWebhook(stream);

// Assert
inboundEmail.Charsets.ShouldNotBeNull();
inboundEmail.Charsets.Except(new[]
{
new KeyValuePair<string, Encoding>("to", Encoding.UTF8),
new KeyValuePair<string, Encoding>("subject", Encoding.UTF8),
new KeyValuePair<string, Encoding>("from", Encoding.UTF8),
new KeyValuePair<string, Encoding>("html", Encoding.ASCII),
new KeyValuePair<string, Encoding>("text", Encoding.UTF8) // The original encoding is iso-8859-10 but we fallback on UTF-8
}).Count().ShouldBe(0);
inboundEmail.Text.ShouldBe("Hello SendGrid!\r\n");
}
}

[Fact]
public void Parse_processed_JSON()
{
Expand Down
4 changes: 2 additions & 2 deletions Source/StrongGrid/StrongGrid.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@

<ItemGroup>
<PackageReference Include="HttpMultipartParser" Version="4.3.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.5" />
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="1.3.4" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.8" />
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="1.3.5" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
<PackageReference Include="MimeTypesMap" Version="1.0.8" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.1" />
Expand Down
46 changes: 39 additions & 7 deletions Source/StrongGrid/WebhookParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,32 @@ public async Task<InboundEmail> ParseInboundEmailWebhookAsync(Stream stream)
.Select(prop =>
{
var key = prop.Name;
var value = Encoding.GetEncoding(prop.Value.ToString());
return new KeyValuePair<string, Encoding>(key, value);
var encodingName = prop.Value.ToString();

try
{
var encoding = Encoding.GetEncoding(encodingName);
return new KeyValuePair<string, Encoding>(key, encoding);
}
catch (ArgumentException)
{
// ArgumentException is thrown when an "unusual" code page was used to encode a section of the email
// For example: {"to":"UTF-8","subject":"UTF-8","from":"UTF-8","text":"iso-8859-10"}
// We can see that 'iso-8859-10' was used to encode the "Text" but this encoding is not supported in
// .net (neither dotnet full nor dotnet core). Therefore we fallback on UTF-8. This is obviously not
// perfect because UTF-8 may or may not be able to handle all the encoded characters, but it's better
// than simply erroring out.
// See https://github.com/Jericho/StrongGrid/issues/341 for discussion.
return new KeyValuePair<string, Encoding>(key, Encoding.UTF8);
}
}).ToArray();

// Create a dictionary of parsers, one parser for each desired encoding.
// This is necessary because MultipartFormDataParser can only handle one
// encoding and SendGrid can use different encodings for parameters such
// as "from", "to", "text" and "html".
var encodedParsers = charsets
.Where(c => c.Value != Encoding.UTF8)
.Where(c => !c.Value.Equals(Encoding.UTF8))
.Select(c => c.Value)
.Distinct()
.Select(async encoding =>
Expand Down Expand Up @@ -152,16 +168,32 @@ public InboundEmail ParseInboundEmailWebhook(Stream stream)
.Select(prop =>
{
var key = prop.Name;
var value = Encoding.GetEncoding(prop.Value.ToString());
return new KeyValuePair<string, Encoding>(key, value);
var encodingName = prop.Value.ToString();

try
{
var encoding = Encoding.GetEncoding(encodingName);
return new KeyValuePair<string, Encoding>(key, encoding);
}
catch (ArgumentException)
{
// ArgumentException is thrown when an "unusual" code page was used to encode a section of the email
// For example: {"to":"UTF-8","subject":"UTF-8","from":"UTF-8","text":"iso-8859-10"}
// We can see that 'iso-8859-10' was used to encode the "Text" but this encoding is not supported in
// .net (neither dotnet full nor dotnet core). Therefore we fallback on UTF-8. This is obviously not
// perfect because UTF-8 may or may not be able to handle all the encoded characters, but it's better
// than simply erroring out.
// See https://github.com/Jericho/StrongGrid/issues/341 for discussion.
return new KeyValuePair<string, Encoding>(key, Encoding.UTF8);
}
}).ToArray();

// Create a dictionary of parsers, one parser for each desired encoding.
// This is necessary because MultipartFormDataParser can only handle one
// encoding and SendGrid can use different encodings for parameters such
// as "from", "to", "text" and "html".
var encodedParsers = charsets
.Where(c => c.Value != Encoding.UTF8)
.Where(c => !c.Value.Equals(Encoding.UTF8))
.Select(c => c.Value)
.Distinct()
.Select(encoding =>
Expand Down Expand Up @@ -210,7 +242,7 @@ private static string GetEncodedValue(string parameterName, IEnumerable<KeyValue
private static InboundEmail ParseInboundEmail(IDictionary<Encoding, MultipartFormDataParser> encodedParsers, KeyValuePair<string, Encoding>[] charsets)
{
// Get the default UTF8 parser
var parser = encodedParsers.Single(p => p.Key == Encoding.UTF8).Value;
var parser = encodedParsers.Single(p => p.Key.Equals(Encoding.UTF8)).Value;

// Convert the 'headers' from a string into array of KeyValuePair
var headers = parser
Expand Down
14 changes: 3 additions & 11 deletions build.cake
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
#tool dotnet:?package=BenchmarkDotNet.Tool&version=0.12.0

// Install tools.
#tool nuget:?package=GitVersion.CommandLine&version=5.3.6
#tool nuget:?package=GitVersion.CommandLine&version=5.3.7
#tool nuget:?package=GitReleaseManager&version=0.11.0
#tool nuget:?package=OpenCover&version=4.7.922
#tool nuget:?package=ReportGenerator&version=4.6.1
#tool nuget:?package=ReportGenerator&version=4.6.6
#tool nuget:?package=coveralls.io&version=1.4.2
#tool nuget:?package=xunit.runner.console&version=2.4.1

// Install addins.
#addin nuget:?package=Cake.Coveralls&version=0.10.1
#addin nuget:?package=Cake.Coveralls&version=0.10.2


///////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -359,14 +359,6 @@ Task("Publish-GitHub-Release")
.WithCriteria(() => isTagged)
.Does(() =>
{
var settings = new GitReleaseManagerCreateSettings
{
Name = milestone,
Milestone = milestone,
Prerelease = false,
TargetCommitish = "master"
};

if (!string.IsNullOrEmpty(gitHubToken))
{
GitReleaseManagerClose(gitHubToken, gitHubRepoOwner, gitHubRepo, milestone);
Expand Down

0 comments on commit 4d82216

Please sign in to comment.