Skip to content

Commit

Permalink
optimize validate logic
Browse files Browse the repository at this point in the history
  • Loading branch information
tinohager committed Jan 13, 2025
1 parent e85cc4f commit 499dd25
Show file tree
Hide file tree
Showing 7 changed files with 233 additions and 115 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
namespace Nager.EmailAuthentication.UnitTest
{
[TestClass]
public sealed class DmarcRecordParserBasicTest
{
[TestMethod]
public void TryParse_InvalidDmarcString1_ReturnsTrueAndPopulatesDmarcRecord()
{
var isSuccessful = DmarcRecordParser.TryParse("v=DMARC", out var dmarcDataFragment, out var parseErrors);
Assert.IsTrue(isSuccessful);
Assert.IsNotNull(dmarcDataFragment);
Assert.IsNotNull(parseErrors, "ParseErrors is null");
}

[TestMethod]
public void TryParse_InvalidDmarcString2_ReturnsTrueAndPopulatesDmarcRecord()
{
var isSuccessful = DmarcRecordParser.TryParse("v=DMARC1", out var dmarcDataFragment, out var parseErrors);
Assert.IsTrue(isSuccessful);
Assert.IsNotNull(dmarcDataFragment);
Assert.IsNull(parseErrors, "ParseErrors is not null");
}

[TestMethod]
public void TryParse_CorruptDmarcString1_ReturnsTrueAndParseErrors()
{
var isSuccessful = DmarcRecordParser.TryParse("verification=123456789", out var dmarcDataFragment, out var parseErrors);
Assert.IsTrue(isSuccessful);
Assert.IsNotNull(dmarcDataFragment);
Assert.IsNotNull(parseErrors, "ParseErrors is null");
Assert.IsTrue(parseErrors.Length == 2);
}

[TestMethod]
public void TryParse_CorruptDmarcString2_ReturnsFalse()
{
var isSuccessful = DmarcRecordParser.TryParse(" ", out var dmarcDataFragment, out var parseErrors);
Assert.IsFalse(isSuccessful);
Assert.IsNull(dmarcDataFragment);
Assert.IsNull(parseErrors, "ParseErrors is not null");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace Nager.EmailAuthentication.UnitTest
{
[TestClass]
public sealed class DmarcRecordParserComplexTest
{
[TestMethod]
public void TryParse_ValidDmarcString1_ReturnsTrueAndPopulatesDmarcRecord()
{
var isSuccessful = DmarcRecordParser.TryParse("v=DMARC1; p=reject; rua=mailto:[email protected], mailto:[email protected]; pct=100; adkim=s; aspf=s", out var dmarcDataFragment, out var parseErrors);
Assert.IsTrue(isSuccessful);
Assert.IsNotNull(dmarcDataFragment);
Assert.AreEqual("reject", dmarcDataFragment.DomainPolicy);
Assert.AreEqual("mailto:[email protected], mailto:[email protected]", dmarcDataFragment.AggregateReportUri);
Assert.AreEqual("100", dmarcDataFragment.PolicyPercentage);
Assert.AreEqual("s", dmarcDataFragment.DkimAlignmentMode);
Assert.AreEqual("s", dmarcDataFragment.SpfAlignmentMode);
Assert.IsNull(parseErrors, "ParseErrors is not null");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
namespace Nager.EmailAuthentication.UnitTest
{
[TestClass]
public sealed class DmarcRecordParserPolicyPercentageTest
{
[TestMethod]
public void TryParse_ValidDmarcString1_ReturnsTrueAndPopulatesDmarcRecord()
{
var isSuccessful = DmarcRecordParser.TryParse("v=DMARC1; p=reject; pct=60;", out var dmarcDataFragment, out var parseErrors);
Assert.IsTrue(isSuccessful);
Assert.IsNotNull(dmarcDataFragment);
Assert.AreEqual("reject", dmarcDataFragment.DomainPolicy);
Assert.AreEqual("60", dmarcDataFragment.PolicyPercentage);
Assert.IsNull(parseErrors, "ParseErrors is not null");
}

[TestMethod]
public void TryParse_InvalidDmarcString1_ReturnsTrueWithErrors()
{
var isSuccessful = DmarcRecordParser.TryParse("v=DMARC1; p=reject; pct=;", out var dmarcDataFragment, out var parseErrors);
Assert.IsTrue(isSuccessful);
Assert.IsNotNull(dmarcDataFragment);
Assert.AreEqual("reject", dmarcDataFragment.DomainPolicy);
Assert.AreEqual("", dmarcDataFragment.PolicyPercentage);
Assert.IsNotNull(parseErrors, "ParseErrors is null");
}

[TestMethod]
public void TryParse_InvalidDmarcString2_ReturnsTrueWithErrors()
{
var isSuccessful = DmarcRecordParser.TryParse("v=DMARC1; p=reject; pct=200;", out var dmarcDataFragment, out var parseErrors);
Assert.IsTrue(isSuccessful);
Assert.IsNotNull(dmarcDataFragment);
Assert.AreEqual("reject", dmarcDataFragment.DomainPolicy);
Assert.AreEqual("200", dmarcDataFragment.PolicyPercentage);
Assert.IsNotNull(parseErrors, "ParseErrors is null");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
namespace Nager.EmailAuthentication.UnitTest
{
[TestClass]
public sealed class DmarcRecordParserPolicyTest
{
[TestMethod]
public void TryParse_InvalidDmarcString1_ReturnsTrueAndPopulatesDmarcRecord()
{
var isSuccessful = DmarcRecordParser.TryParse("v=DMARC1; p=Test", out var dmarcDataFragment, out var parseErrors);
Assert.IsTrue(isSuccessful);
Assert.IsNotNull(dmarcDataFragment);
Assert.AreEqual("Test", dmarcDataFragment.DomainPolicy);
Assert.IsNotNull(parseErrors);
Assert.IsTrue(parseErrors.Length == 1);
}

[TestMethod]
public void TryParse_InvalidDmarcString2_ReturnsTrueAndPopulatesDmarcRecord()
{
var isSuccessful = DmarcRecordParser.TryParse("v=DMARC1; p=Test;", out var dmarcDataFragment, out var parseErrors);
Assert.IsTrue(isSuccessful);
Assert.IsNotNull(dmarcDataFragment);
Assert.AreEqual("Test", dmarcDataFragment.DomainPolicy);
Assert.IsNotNull(parseErrors);
Assert.IsTrue(parseErrors.Length == 1);
}

[TestMethod]
public void TryParse_ValidDmarcString1_ReturnsTrueAndPopulatesDmarcRecord()
{
var isSuccessful = DmarcRecordParser.TryParse("v=DMARC1; p=reject;", out var dmarcDataFragment, out var parseErrors);
Assert.IsTrue(isSuccessful);
Assert.IsNotNull(dmarcDataFragment);
Assert.AreEqual("reject", dmarcDataFragment.DomainPolicy);
Assert.IsNull(parseErrors, "ParseErrors is not null");
}

[TestMethod]
public void TryParse_ValidDmarcString2_ReturnsTrueAndPopulatesDmarcRecord()
{
var isSuccessful = DmarcRecordParser.TryParse("v=DMARC1; p=reject; sp=none;", out var dmarcDataFragment, out var parseErrors);
Assert.IsTrue(isSuccessful);
Assert.IsNotNull(dmarcDataFragment);
Assert.AreEqual("reject", dmarcDataFragment.DomainPolicy);
Assert.AreEqual("none", dmarcDataFragment.SubdomainPolicy);
Assert.IsNull(parseErrors, "ParseErrors is not null");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
namespace Nager.EmailAuthentication.UnitTest
{
[TestClass]
public sealed class DmarcRecordParserReportFormatTest
{
[TestMethod]
public void TryParse_ValidDmarcString1_ReturnsTrueAndPopulatesDmarcRecord()
{
var isSuccessful = DmarcRecordParser.TryParse("v=DMARC1; p=reject; rf=afrf", out var dmarcDataFragment, out var parseErrors);
Assert.IsTrue(isSuccessful);
Assert.IsNotNull(dmarcDataFragment);
Assert.AreEqual("reject", dmarcDataFragment.DomainPolicy);
Assert.AreEqual("afrf", dmarcDataFragment.ReportFormat);
Assert.IsNull(parseErrors, "ParseErrors is not null"); ;
}

[TestMethod]
public void TryParse_InvalidDmarcString1_ReturnsTrueAndPopulatesDmarcRecordWithParseErrors()
{
var isSuccessful = DmarcRecordParser.TryParse("v=DMARC1; p=reject; rf=afrf1", out var dmarcDataFragment, out var parseErrors);
Assert.IsTrue(isSuccessful);
Assert.IsNotNull(dmarcDataFragment);
Assert.AreEqual("reject", dmarcDataFragment.DomainPolicy);
Assert.AreEqual("afrf1", dmarcDataFragment.ReportFormat);
Assert.IsNotNull(parseErrors, "ParseErrors is null");
Assert.IsTrue(parseErrors.Length == 1);
}

[TestMethod]
public void TryParse_InvalidDmarcString2_ReturnsTrueAndPopulatesDmarcRecordWithParseErrors()
{
var isSuccessful = DmarcRecordParser.TryParse("v=DMARC1; p=reject; rf=", out var dmarcDataFragment, out var parseErrors);
Assert.IsTrue(isSuccessful);
Assert.IsNotNull(dmarcDataFragment);
Assert.AreEqual("reject", dmarcDataFragment.DomainPolicy);
Assert.AreEqual("", dmarcDataFragment.ReportFormat);
Assert.IsNotNull(parseErrors, "ParseErrors is null");
Assert.IsTrue(parseErrors.Length == 1);
}
}
}
111 changes: 0 additions & 111 deletions src/Nager.EmailAuthentication.UnitTest/DmarcRecordParserTest.cs

This file was deleted.

45 changes: 41 additions & 4 deletions src/Nager.EmailAuthentication/DmarcRecordParser.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Nager.EmailAuthentication.Models;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace Nager.EmailAuthentication
{
Expand Down Expand Up @@ -119,7 +120,8 @@ public static bool TryParse(
{
"rf", new MappingHandler
{
Map = value => dataFragment.ReportFormat = value
Map = value => dataFragment.ReportFormat = value,
Validate = ValidateReportFormat
}
},
{
Expand Down Expand Up @@ -213,12 +215,18 @@ private static ParseError[] ValidateDomainPolicy(ValidateRequest validateRequest

private static ParseError[] ValidatePolicyPercentage(ValidateRequest validateRequest)
{
var errors = new List<ParseError>();

if (string.IsNullOrEmpty(validateRequest.Value))
{
return [];
}
errors.Add(new ParseError
{
Severity = ErrorSeverity.Error,
ErrorMessage = $"{validateRequest.Field} is empty"
});

var errors = new List<ParseError>();
return [.. errors];
}

if (!int.TryParse(validateRequest.Value, out var percentage))
{
Expand All @@ -244,5 +252,34 @@ private static ParseError[] ValidatePolicyPercentage(ValidateRequest validateReq

return [];
}

private static ParseError[] ValidateReportFormat(ValidateRequest validateRequest)
{
var errors = new List<ParseError>();

if (string.IsNullOrEmpty(validateRequest.Value))
{
errors.Add(new ParseError
{
Severity = ErrorSeverity.Error,
ErrorMessage = $"{validateRequest.Field} is empty"
});

return [.. errors];
}

if (!validateRequest.Value.Equals("afrf", StringComparison.OrdinalIgnoreCase))
{
errors.Add(new ParseError
{
Severity = ErrorSeverity.Error,
ErrorMessage = $"{validateRequest.Field} only allow Authentication Failure Reporting Format (afrf)"
});

return [.. errors];
}

return [];
}
}
}

0 comments on commit 499dd25

Please sign in to comment.