Skip to content

Commit 53b42bc

Browse files
committed
Optimize dkim validation logic
1 parent d5ec8a1 commit 53b42bc

File tree

4 files changed

+57
-1
lines changed

4 files changed

+57
-1
lines changed

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

+4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ public void TryParse_ValidSelector_ReturnsTrueAndPopulatesDataFragment(string se
1919
}
2020

2121
[DataRow("verylongandinvalidselectorverylongandinvalidselectorverylongandinvalidselector")]
22+
[DataRow("-test")]
23+
[DataRow("-test-")]
24+
[DataRow("_test")]
25+
[DataRow("test_")]
2226
[DataTestMethod]
2327
public void TryParse_InvalidSelector_ReturnsTrueAndPopulatesDataFragment(string selector)
2428
{

src/Nager.EmailAuthentication.UnitTest/DmarcRecordParserTests/ComplexTest.cs

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public void TryParse_ValidDmarcString1_ReturnsTrueAndPopulatesDmarcRecord()
2222
public void TryParse_ValidDmarcString2_ReturnsTrueAndPopulatesDmarcRecord()
2323
{
2424
var isSuccessful = DmarcRecordDataFragmentParser.TryParse("v=DMARC1; p=reject; rua=mailto:[email protected], mailto:[email protected]; pct=100; adkim=s; aspf=s", out var dmarcDataFragment, out var parsingResults);
25+
Assert.IsNotNull(dmarcDataFragment);
2526

2627
var isSuccessful2 = DmarcRecordParser.TryParse(dmarcDataFragment, out var dmarcRecord);
2728
Assert.IsTrue(isSuccessful2);

src/Nager.EmailAuthentication/DkimSignatureDataFragmentParser.cs

+42-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Nager.EmailAuthentication.Handlers;
22
using Nager.EmailAuthentication.Models;
3+
using Nager.EmailAuthentication.RegexProviders;
34
using System.Diagnostics.CodeAnalysis;
45

56
namespace Nager.EmailAuthentication
@@ -79,7 +80,8 @@ public static bool TryParse(
7980
{
8081
"d", new MappingHandler<DkimSignatureDataFragment>
8182
{
82-
Map = (dataFragment, value) => dataFragment.SigningDomainIdentifier = value
83+
Map = (dataFragment, value) => dataFragment.SigningDomainIdentifier = value,
84+
Validate = ValidateDomain
8385
}
8486
},
8587
{
@@ -228,6 +230,45 @@ private static ParsingResult[] ValidateSelector(ValidateRequest validateRequest)
228230
});
229231
}
230232

233+
if (!DkimSelectorRegexProvider.GetRegex().IsMatch(validateRequest.Value))
234+
{
235+
errors.Add(new ParsingResult
236+
{
237+
Status = ParsingStatus.Error,
238+
Field = validateRequest.Field,
239+
Message = "Selector syntax invalid"
240+
});
241+
}
242+
243+
return [.. errors];
244+
}
245+
246+
private static ParsingResult[] ValidateDomain(ValidateRequest validateRequest)
247+
{
248+
var errors = new List<ParsingResult>();
249+
250+
if (string.IsNullOrEmpty(validateRequest.Value))
251+
{
252+
errors.Add(new ParsingResult
253+
{
254+
Status = ParsingStatus.Error,
255+
Field = validateRequest.Field,
256+
Message = "Is empty"
257+
});
258+
259+
return [.. errors];
260+
}
261+
262+
if (!Uri.TryCreate($"https://{validateRequest.Value}", UriKind.Absolute, out _))
263+
{
264+
errors.Add(new ParsingResult
265+
{
266+
Status = ParsingStatus.Critical,
267+
Field = validateRequest.Field,
268+
Message = "Invalid domain syntax"
269+
});
270+
}
271+
231272
return [.. errors];
232273
}
233274

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using System.Text.RegularExpressions;
2+
3+
namespace Nager.EmailAuthentication.RegexProviders
4+
{
5+
internal static partial class DkimSelectorRegexProvider
6+
{
7+
[GeneratedRegex("^[a-z0-9]{1}[a-z0-9-]*[a-z0-9]{1}$", RegexOptions.IgnoreCase)]
8+
internal static partial Regex GetRegex();
9+
}
10+
}

0 commit comments

Comments
 (0)