Skip to content

Commit ab9ee5a

Browse files
committed
optimize parse logic and unit tests
1 parent 5473e70 commit ab9ee5a

File tree

6 files changed

+44
-11
lines changed

6 files changed

+44
-11
lines changed

src/Nager.EmailAuthentication.UnitTest/DkimSignatureParserTests/FoldingTest.cs

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ namespace Nager.EmailAuthentication.UnitTest.DkimSignatureParserTests
55
[TestClass]
66
public sealed class FoldingTest
77
{
8+
/// <summary>
9+
/// DKIM signature folding refers to breaking long header field lines into multiple lines for better readability
10+
/// and compliance with email standards. It uses whitespace and line breaks while ensuring the signature remains valid.
11+
/// </summary>
812
[TestMethod]
913
public void TryParse_ValidSelector_ReturnsTrueAndPopulatesDataFragment()
1014
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
namespace Nager.EmailAuthentication.UnitTest.DkimSignatureParserTests
2+
{
3+
[TestClass]
4+
public sealed class HeaderTest
5+
{
6+
[TestMethod]
7+
public void TryParse_NoHeadersDefined_ReturnsTrueAndPopulatesDataFragment()
8+
{
9+
var dkimSignatureRaw = "v=1; a=rsa-sha256; d=domain.com; s=test; h=; bh=testbodyhash=; b=signaturedata";
10+
11+
var isSuccessful = DkimSignatureDataFragmentParser.TryParse(dkimSignatureRaw, out var dkimSignatureDataFragment, out var parsingResults);
12+
13+
Assert.IsTrue(isSuccessful);
14+
Assert.IsNotNull(dkimSignatureDataFragment);
15+
Assert.IsNotNull(parsingResults, "ParsingResults is null");
16+
}
17+
18+
[TestMethod]
19+
public void TryParse_OnlyOneHeaderIsDefined_ReturnsTrueAndPopulatesDataFragment()
20+
{
21+
var dkimSignatureRaw = "v=1; a=rsa-sha256; d=domain.com; s=test; h=test; bh=testbodyhash=; b=signaturedata";
22+
23+
var isSuccessful = DkimSignatureDataFragmentParser.TryParse(dkimSignatureRaw, out var dkimSignatureDataFragment, out var parsingResults);
24+
25+
Assert.IsTrue(isSuccessful);
26+
Assert.IsNotNull(dkimSignatureDataFragment);
27+
Assert.IsNotNull(parsingResults, "ParsingResults is null");
28+
}
29+
}
30+
}

src/Nager.EmailAuthentication/DkimSignatureDataFragmentParser.cs

+5-8
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ private static ParsingResult[] ValidateSignedHeaderFields(ValidateRequest valida
381381
{
382382
Status = ParsingStatus.Error,
383383
Field = validateRequest.Field,
384-
Message = "Is empty"
384+
Message = "The signed header fields is empty, from is required"
385385
});
386386

387387
return [.. parsingResults];
@@ -391,12 +391,10 @@ private static ParsingResult[] ValidateSignedHeaderFields(ValidateRequest valida
391391
{
392392
parsingResults.Add(new ParsingResult
393393
{
394-
Status = ParsingStatus.Error,
394+
Status = ParsingStatus.Info,
395395
Field = validateRequest.Field,
396-
Message = "No colon found"
396+
Message = "No colon separator found"
397397
});
398-
399-
return [.. parsingResults];
400398
}
401399

402400
var parts = validateRequest.Value.Split(':');
@@ -417,16 +415,15 @@ private static ParsingResult[] ValidateSignedHeaderFields(ValidateRequest valida
417415
}
418416
}
419417

420-
//TODO: Check important Headers
421418
var recommendedHeaders = new string[] { "from", "to", "subject", "reply-to", "date", "cc", "content-type" };
422419
var missingRecommendedHeaders = recommendedHeaders.Except(groupedHeaders.Select(o => o.Key));
423420
foreach (var missingRecommendedHeader in missingRecommendedHeaders)
424421
{
425422
parsingResults.Add(new ParsingResult
426423
{
427-
Status = ParsingStatus.Info,
424+
Status = ParsingStatus.Warning,
428425
Field = validateRequest.Field,
429-
Message = $"Missing recommended header detected {missingRecommendedHeader}"
426+
Message = $"Missing recommended header detected '{missingRecommendedHeader}'"
430427
});
431428
}
432429

src/Nager.EmailAuthentication/DkimSignatureParser.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ public static bool TryParse(
151151
}
152152
}
153153

154+
var signedHeaders = dkimSignatureDataFragment.SignedHeaderFields.Split(':', StringSplitOptions.TrimEntries);
155+
154156
dkimSignature = new DkimSignature
155157
{
156158
Version = dkimSignatureDataFragment.Version,
@@ -163,7 +165,7 @@ public static bool TryParse(
163165
SignatureAlgorithm = signatureAlgorithm.Value,
164166
SignatureExpiration = signatureExpiration,
165167
AgentOrUserIdentifier = dkimSignatureDataFragment.AgentOrUserIdentifier,
166-
SignedHeaderFields = dkimSignatureDataFragment.SignedHeaderFields.Split(':'),
168+
SignedHeaderFields = signedHeaders,
167169
MessageCanonicalizationHeader = messageCanonicalizationHeader,
168170
MessageCanonicalizationBody = messageCanonicalizationBody,
169171
Timestamp = timestamp

src/Nager.EmailAuthentication/DmarcRecordDataFragmentParser.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ private static ParsingResult[] ValidateFailureReportingOptions(ValidateRequest v
310310
{
311311
Status = ParsingStatus.Error,
312312
Field = validateRequest.Field,
313-
Message = "No colon found"
313+
Message = "No colon separator found"
314314
});
315315

316316
return [.. parsingResults];

src/Nager.EmailAuthentication/Nager.EmailAuthentication.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
2222

23-
<Version>1.6.0</Version>
23+
<Version>1.6.1</Version>
2424
</PropertyGroup>
2525

2626
<ItemGroup>

0 commit comments

Comments
 (0)