Skip to content

Commit 5126f5b

Browse files
committed
Optimize validation logic
1 parent decb258 commit 5126f5b

File tree

4 files changed

+124
-9
lines changed

4 files changed

+124
-9
lines changed

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ public void TryParse_InvalidMessageCanonicalization1_ReturnsFalse()
132132

133133
Assert.IsFalse(isSuccessful);
134134
Assert.IsNull(dkimSignature);
135-
Assert.IsNull(parsingResults, "ParsingResults is not null");
135+
Assert.IsNotNull(parsingResults, "ParsingResults is null");
136136
}
137137

138138
[TestMethod]
@@ -144,7 +144,7 @@ public void TryParse_InvalidMessageCanonicalization2_ReturnsFalse()
144144

145145
Assert.IsFalse(isSuccessful);
146146
Assert.IsNull(dkimSignature);
147-
Assert.IsNull(parsingResults, "ParsingResults is not null");
147+
Assert.IsNotNull(parsingResults, "ParsingResults is null");
148148
}
149149
}
150150
}

src/Nager.EmailAuthentication/FragmentParsers/DkimPublicKeyRecordDataFragmentParserV1.cs

-2
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,6 @@ private static ParsingResult[] ValidatePublicKeyData(ValidateRequest validateReq
124124

125125
private static ParsingResult[] ValidateVersion(ValidateRequest validateRequest)
126126
{
127-
var parsingResults = new List<ParsingResult>();
128-
129127
if (string.IsNullOrEmpty(validateRequest.Value))
130128
{
131129
return [

src/Nager.EmailAuthentication/FragmentParsers/DkimSignatureDataFragmentParserV1.cs

+121-4
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ public static bool TryParse(
7474
{
7575
"c", new MappingHandler<DkimSignatureDataFragmentV1>
7676
{
77-
Map = (dataFragment, value) => dataFragment.MessageCanonicalization = value
78-
//TODO: Add validate logic
77+
Map = (dataFragment, value) => dataFragment.MessageCanonicalization = value,
78+
Validate = ValidateMessageCanonicalization
7979
}
8080
},
8181
{
@@ -122,13 +122,15 @@ public static bool TryParse(
122122
{
123123
"q", new MappingHandler<DkimSignatureDataFragmentV1>
124124
{
125-
Map = (dataFragment, value) => dataFragment.QueryMethods = value
125+
Map = (dataFragment, value) => dataFragment.QueryMethods = value,
126+
Validate = ValidateQueryMethods
126127
}
127128
},
128129
{
129130
"i", new MappingHandler<DkimSignatureDataFragmentV1>
130131
{
131-
Map = (dataFragment, value) => dataFragment.AgentOrUserIdentifier = value
132+
Map = (dataFragment, value) => dataFragment.AgentOrUserIdentifier = value,
133+
Validate = ValidateAgentOrUserIdentifier
132134
}
133135
}
134136
};
@@ -371,6 +373,121 @@ private static ParsingResult[] ValidateBodyLengthCount(ValidateRequest validateR
371373
return ValidatePositiveNumber(validateRequest, CheckBodyLengthCount);
372374
}
373375

376+
private static ParsingResult[] ValidateMessageCanonicalization(ValidateRequest validateRequest)
377+
{
378+
var parsingResults = new List<ParsingResult>();
379+
380+
if (string.IsNullOrEmpty(validateRequest.Value))
381+
{
382+
parsingResults.Add(new ParsingResult
383+
{
384+
Status = ParsingStatus.Error,
385+
Field = validateRequest.Field,
386+
Message = "Is empty"
387+
});
388+
389+
return [.. parsingResults];
390+
}
391+
392+
var allowedModes = new string[] { "relaxed", "simple" };
393+
394+
var parts = validateRequest.Value.Split('/');
395+
if (parts.Length == 1)
396+
{
397+
var part = parts[0].ToLower();
398+
399+
if (allowedModes.Contains(part))
400+
{
401+
return [];
402+
}
403+
404+
parsingResults.Add(new ParsingResult
405+
{
406+
Status = ParsingStatus.Error,
407+
Field = validateRequest.Field,
408+
Message = $"Unknown mode {part} detected"
409+
});
410+
411+
return [.. parsingResults];
412+
}
413+
414+
if (parts.Length == 2)
415+
{
416+
if (parts.Count(part => allowedModes.Contains(part.ToLower())) == 2)
417+
{
418+
return [];
419+
}
420+
421+
parsingResults.Add(new ParsingResult
422+
{
423+
Status = ParsingStatus.Error,
424+
Field = validateRequest.Field,
425+
Message = "Unknown mode detected"
426+
});
427+
428+
return [.. parsingResults];
429+
}
430+
431+
parsingResults.Add(new ParsingResult
432+
{
433+
Status = ParsingStatus.Error,
434+
Field = validateRequest.Field,
435+
Message = "Too much parts"
436+
});
437+
438+
return [.. parsingResults];
439+
}
440+
441+
private static ParsingResult[] ValidateQueryMethods(ValidateRequest validateRequest)
442+
{
443+
var parsingResults = new List<ParsingResult>();
444+
445+
if (string.IsNullOrEmpty(validateRequest.Value))
446+
{
447+
parsingResults.Add(new ParsingResult
448+
{
449+
Status = ParsingStatus.Error,
450+
Field = validateRequest.Field,
451+
Message = "Is empty"
452+
});
453+
454+
return [.. parsingResults];
455+
}
456+
457+
if (validateRequest.Value.Equals("dns/txt", StringComparison.OrdinalIgnoreCase))
458+
{
459+
return [];
460+
}
461+
462+
parsingResults.Add(new ParsingResult
463+
{
464+
Status = ParsingStatus.Error,
465+
Field = validateRequest.Field,
466+
Message = "Invalid query method"
467+
});
468+
469+
return [];
470+
}
471+
472+
private static ParsingResult[] ValidateAgentOrUserIdentifier(ValidateRequest validateRequest)
473+
{
474+
var parsingResults = new List<ParsingResult>();
475+
476+
if (string.IsNullOrEmpty(validateRequest.Value))
477+
{
478+
parsingResults.Add(new ParsingResult
479+
{
480+
Status = ParsingStatus.Error,
481+
Field = validateRequest.Field,
482+
Message = "Is empty"
483+
});
484+
485+
return [.. parsingResults];
486+
}
487+
488+
return [];
489+
}
490+
374491
private static ParsingResult[] ValidateSignedHeaderFields(ValidateRequest validateRequest)
375492
{
376493
var parsingResults = new List<ParsingResult>();

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>2.0.0</Version>
23+
<Version>2.0.1</Version>
2424
</PropertyGroup>
2525

2626
<ItemGroup>

0 commit comments

Comments
 (0)