public void TestParseMethodWithMultipleProperties() { const string input = "example.com; spf=pass ptype1.prop1=value1 ptype2.prop2=value2"; var buffer = Encoding.ASCII.GetBytes(input); AuthenticationResults authres; Assert.IsTrue(AuthenticationResults.TryParse(buffer, 0, buffer.Length, out authres)); Assert.AreEqual("example.com", authres.AuthenticationServiceIdentifier, "authserv-id"); Assert.AreEqual(1, authres.Results.Count, "methods"); Assert.AreEqual("spf", authres.Results[0].Method); Assert.AreEqual("pass", authres.Results[0].Result); Assert.AreEqual(2, authres.Results[0].Properties.Count, "properties"); Assert.AreEqual("ptype1", authres.Results[0].Properties[0].PropertyType); Assert.AreEqual("prop1", authres.Results[0].Properties[0].Property); Assert.AreEqual("value1", authres.Results[0].Properties[0].Value); Assert.AreEqual("ptype2", authres.Results[0].Properties[1].PropertyType); Assert.AreEqual("prop2", authres.Results[0].Properties[1].Property); Assert.AreEqual("value2", authres.Results[0].Properties[1].Value); Assert.AreEqual(input, authres.ToString()); const string expected = " example.com;\n\tspf=pass ptype1.prop1=value1 ptype2.prop2=value2\n"; var encoded = new StringBuilder(); var options = FormatOptions.Default.Clone(); options.NewLineFormat = NewLineFormat.Unix; authres.Encode(options, encoded, "Authentication-Results:".Length); Assert.AreEqual(expected, encoded.ToString()); }
public void TestParseHeavilyCommentedExample() { var buffer = Encoding.ASCII.GetBytes("foo.example.net (foobar) 1 (baz); dkim (Because I like it) / 1 (One yay) = (wait for it) fail policy (A dot can go here) . (like that) expired (this surprised me) = (as I wasn't expecting it) 1362471462"); AuthenticationResults authres; Assert.IsTrue(AuthenticationResults.TryParse(buffer, 0, buffer.Length, out authres)); Assert.AreEqual("foo.example.net", authres.AuthenticationServiceIdentifier, "authserv-id"); Assert.AreEqual(1, authres.Version.Value, "authres-version"); Assert.AreEqual(1, authres.Results.Count, "methods"); Assert.AreEqual("dkim", authres.Results[0].Method); Assert.AreEqual(1, authres.Results[0].Version.Value, "method-version"); Assert.AreEqual("fail", authres.Results[0].Result); Assert.AreEqual(1, authres.Results[0].Properties.Count, "dkim properties"); Assert.AreEqual("policy", authres.Results[0].Properties[0].PropertyType); Assert.AreEqual("expired", authres.Results[0].Properties[0].Property); Assert.AreEqual("1362471462", authres.Results[0].Properties[0].Value); Assert.AreEqual("foo.example.net 1; dkim/1=fail policy.expired=1362471462", authres.ToString()); const string expected = " foo.example.net 1;\n\tdkim/1=fail policy.expired=1362471462\n"; var encoded = new StringBuilder(); var options = FormatOptions.Default.Clone(); options.NewLineFormat = NewLineFormat.Unix; authres.Encode(options, encoded, "Authentication-Results:".Length); Assert.AreEqual(expected, encoded.ToString()); }
public void TestParseSimpleWithProperty3() { const string input = "example.com; spf=pass [email protected]"; var buffer = Encoding.ASCII.GetBytes(input); AuthenticationResults authres; Assert.IsTrue(AuthenticationResults.TryParse(buffer, 0, buffer.Length, out authres)); Assert.AreEqual("example.com", authres.AuthenticationServiceIdentifier, "authserv-id"); Assert.AreEqual(1, authres.Results.Count, "methods"); Assert.AreEqual("spf", authres.Results[0].Method); Assert.AreEqual("pass", authres.Results[0].Result); Assert.AreEqual(1, authres.Results[0].Properties.Count, "properties"); Assert.AreEqual("smtp", authres.Results[0].Properties[0].PropertyType); Assert.AreEqual("mailfrom", authres.Results[0].Properties[0].Property); Assert.AreEqual("*****@*****.**", authres.Results[0].Properties[0].Value); Assert.AreEqual(input, authres.ToString()); const string expected = " example.com;\n\tspf=pass [email protected]\n"; var encoded = new StringBuilder(); var options = FormatOptions.Default.Clone(); options.NewLineFormat = NewLineFormat.Unix; authres.Encode(options, encoded, "Authentication-Results:".Length); Assert.AreEqual(expected, encoded.ToString()); }
public void TestParseSimpleWithQuotedReasonSemiColon() { const string input = "example.com; spf=pass reason=\"good stuff\""; var buffer = Encoding.ASCII.GetBytes(input + "; "); AuthenticationResults authres; Assert.IsTrue(AuthenticationResults.TryParse(buffer, 0, buffer.Length, out authres)); Assert.AreEqual("example.com", authres.AuthenticationServiceIdentifier, "authserv-id"); Assert.AreEqual(1, authres.Results.Count, "methods"); Assert.AreEqual("spf", authres.Results[0].Method); Assert.AreEqual("pass", authres.Results[0].Result); Assert.AreEqual("good stuff", authres.Results[0].Reason); Assert.AreEqual(0, authres.Results[0].Properties.Count, "properties"); Assert.AreEqual(input, authres.ToString()); const string expected = " example.com; spf=pass reason=\"good stuff\"\n"; var encoded = new StringBuilder(); var options = FormatOptions.Default.Clone(); options.NewLineFormat = NewLineFormat.Unix; authres.Encode(options, encoded, "Authentication-Results:".Length); Assert.AreEqual(expected, encoded.ToString()); }
public void TestArgumentExceptions() { AuthenticationResults authres; var buffer = new byte[16]; Assert.Throws <ArgumentNullException> (() => new AuthenticationResults(null)); Assert.Throws <ArgumentNullException> (() => new AuthenticationMethodResult(null)); Assert.Throws <ArgumentNullException> (() => new AuthenticationMethodResult(null, "result")); Assert.Throws <ArgumentNullException> (() => new AuthenticationMethodResult("method", null)); Assert.Throws <ArgumentNullException> (() => new AuthenticationMethodProperty(null, "property", "value")); Assert.Throws <ArgumentNullException> (() => new AuthenticationMethodProperty("ptype", null, "value")); Assert.Throws <ArgumentNullException> (() => new AuthenticationMethodProperty("ptype", "Property", null)); Assert.Throws <ArgumentNullException> (() => AuthenticationResults.Parse(null)); Assert.Throws <ArgumentNullException> (() => AuthenticationResults.Parse(null, 0, 0)); Assert.Throws <ArgumentOutOfRangeException> (() => AuthenticationResults.Parse(buffer, -1, 0)); Assert.Throws <ArgumentOutOfRangeException> (() => AuthenticationResults.Parse(buffer, 0, -1)); Assert.Throws <ArgumentNullException> (() => AuthenticationResults.TryParse(null, out authres)); Assert.Throws <ArgumentNullException> (() => AuthenticationResults.TryParse(null, 0, 0, out authres)); Assert.Throws <ArgumentOutOfRangeException> (() => AuthenticationResults.TryParse(buffer, -1, 0, out authres)); Assert.Throws <ArgumentOutOfRangeException> (() => AuthenticationResults.TryParse(buffer, 0, -1, out authres)); }
public void TestParseSimpleWithComment() { const string input = "example.com; foo=pass (2 of 3 tests OK)"; var buffer = Encoding.ASCII.GetBytes(input); AuthenticationResults authres; Assert.IsTrue(AuthenticationResults.TryParse(buffer, 0, buffer.Length, out authres)); Assert.AreEqual("example.com", authres.AuthenticationServiceIdentifier, "authserv-id"); Assert.AreEqual(1, authres.Results.Count, "methods"); Assert.AreEqual("foo", authres.Results[0].Method); Assert.AreEqual("pass", authres.Results[0].Result); Assert.AreEqual("2 of 3 tests OK", authres.Results[0].ResultComment); Assert.AreEqual(input, authres.ToString()); const string expected = " example.com; foo=pass (2 of 3 tests OK)\n"; var encoded = new StringBuilder(); var options = FormatOptions.Default.Clone(); options.NewLineFormat = NewLineFormat.Unix; authres.Encode(options, encoded, "Authentication-Results:".Length); Assert.AreEqual(expected, encoded.ToString()); }
/// <summary> /// Generate the ARC-Authentication-Results header. /// </summary> /// <remarks> /// The ARC-Authentication-Results header contains information detailing the results of /// authenticating/verifying the message via ARC, DKIM, SPF, etc. /// /// In the following implementation, we assume that all of these authentication results /// have already been determined by other mail software that has added some Authentication-Results /// headers containing this information. /// /// Note: This method is used when ArcSigner.Sign() is called instead of ArcSigner.SignAsync(). /// </remarks> protected override AuthenticationResults GenerateArcAuthenticationResults(FormatOptions options, MimeMessage message, CancellationToken cancellationToken) { var results = new AuthenticationResults(AuthenticationServiceIdentifier); for (int i = 0; i < message.Headers.Count; i++) { var header = message.Headers[i]; if (header.Id != HeaderId.AuthenticationResults) { continue; } if (!AuthenticationResults.TryParse(header.RawValue, out AuthenticationResults authres)) { continue; } if (authres.AuthenticationServiceIdentifier != AuthenticationServiceIdentifier) { continue; } foreach (var result in authres.Results) { if (!results.Results.Any(r => r.Method == result.Method)) { results.Results.Add(result); } } } return(results); }
public void TestParseNoAuthServId() { var buffer = Encoding.ASCII.GetBytes("spf=fail (sender IP is 1.1.1.1) smtp.mailfrom=eu-west-1.amazonses.com; recevingdomain.com; dkim=pass (signature was verified) header.d=domain.com;domain1.com; dmarc=bestguesspass action=none header.from=domain.com;"); AuthenticationResults authres; Assert.IsTrue(AuthenticationResults.TryParse(buffer, 0, buffer.Length, out authres)); Assert.IsNull(authres.AuthenticationServiceIdentifier, "authserv-id"); Assert.AreEqual("spf=fail (sender IP is 1.1.1.1) smtp.mailfrom=eu-west-1.amazonses.com; recevingdomain.com; dkim=pass (signature was verified) header.d=domain.com;domain1.com; dmarc=bestguesspass action=\"none\" header.from=domain.com", authres.ToString()); const string expected = " spf=fail (sender IP is 1.1.1.1)\n\tsmtp.mailfrom=eu-west-1.amazonses.com; recevingdomain.com;\n\tdkim=pass (signature was verified) header.d=domain.com;domain1.com;\n\tdmarc=bestguesspass action=\"none\" header.from=domain.com\n"; var encoded = new StringBuilder(); var options = FormatOptions.Default.Clone(); options.NewLineFormat = NewLineFormat.Unix; authres.Encode(options, encoded, "Authentication-Results:".Length); Assert.AreEqual(expected, encoded.ToString()); }
public void TestParseAuthServIdSemicolon() { var buffer = Encoding.ASCII.GetBytes("example.org;"); AuthenticationResults authres; Assert.IsTrue(AuthenticationResults.TryParse(buffer, 0, buffer.Length, out authres)); Assert.AreEqual("example.org", authres.AuthenticationServiceIdentifier, "authserv-id"); Assert.AreEqual("example.org; none", authres.ToString()); const string expected = " example.org; none\n"; var encoded = new StringBuilder(); var options = FormatOptions.Default.Clone(); options.NewLineFormat = NewLineFormat.Unix; authres.Encode(options, encoded, "Authentication-Results:".Length); Assert.AreEqual(expected, encoded.ToString()); }
public void TestParseMultipleMethods() { const string input = "example.com; auth=pass (cram-md5) [email protected]; spf=pass smtp.mailfrom=example.net; sender-id=pass header.from=example.net"; var buffer = Encoding.ASCII.GetBytes(input); AuthenticationResults authres; Assert.IsTrue(AuthenticationResults.TryParse(buffer, 0, buffer.Length, out authres)); Assert.AreEqual("example.com", authres.AuthenticationServiceIdentifier, "authserv-id"); Assert.AreEqual(3, authres.Results.Count, "methods"); Assert.AreEqual("auth", authres.Results[0].Method); Assert.AreEqual("pass", authres.Results[0].Result); Assert.AreEqual("cram-md5", authres.Results[0].ResultComment); Assert.AreEqual(1, authres.Results[0].Properties.Count, "auth properties"); Assert.AreEqual("smtp", authres.Results[0].Properties[0].PropertyType); Assert.AreEqual("auth", authres.Results[0].Properties[0].Property); Assert.AreEqual("*****@*****.**", authres.Results[0].Properties[0].Value); Assert.AreEqual("spf", authres.Results[1].Method); Assert.AreEqual("pass", authres.Results[1].Result); Assert.AreEqual(1, authres.Results[1].Properties.Count, "spf properties"); Assert.AreEqual("smtp", authres.Results[1].Properties[0].PropertyType); Assert.AreEqual("mailfrom", authres.Results[1].Properties[0].Property); Assert.AreEqual("example.net", authres.Results[1].Properties[0].Value); Assert.AreEqual("sender-id", authres.Results[2].Method); Assert.AreEqual("pass", authres.Results[2].Result); Assert.AreEqual(1, authres.Results[2].Properties.Count, "sender-id properties"); Assert.AreEqual("header", authres.Results[2].Properties[0].PropertyType); Assert.AreEqual("from", authres.Results[2].Properties[0].Property); Assert.AreEqual("example.net", authres.Results[2].Properties[0].Value); Assert.AreEqual(input, authres.ToString()); const string expected = " example.com;\n\tauth=pass (cram-md5) [email protected];\n\tspf=pass smtp.mailfrom=example.net; sender-id=pass header.from=example.net\n"; var encoded = new StringBuilder(); var options = FormatOptions.Default.Clone(); options.NewLineFormat = NewLineFormat.Unix; authres.Encode(options, encoded, "Authentication-Results:".Length); Assert.AreEqual(expected, encoded.ToString()); }
static void AssertParseFailure(string input, int tokenIndex, int errorIndex) { var buffer = Encoding.ASCII.GetBytes(input); Assert.IsFalse(AuthenticationResults.TryParse(buffer, out AuthenticationResults authres)); try { AuthenticationResults.Parse(buffer); Assert.Fail("Expected parse error."); } catch (ParseException ex) { Assert.AreEqual(tokenIndex, ex.TokenIndex, "TokenIndex"); Assert.AreEqual(errorIndex, ex.ErrorIndex, "ErrorIndex"); } try { AuthenticationResults.Parse(buffer, 0, buffer.Length); Assert.Fail("Expected parse error."); } catch (ParseException ex) { Assert.AreEqual(tokenIndex, ex.TokenIndex, "TokenIndex"); Assert.AreEqual(errorIndex, ex.ErrorIndex, "ErrorIndex"); } }
public void TestParseMultipleMethodsWithReasons() { const string input = "example.com; dkim=pass reason=\"good signature\" [email protected]; dkim=fail reason=\"bad signature\" [email protected]"; var buffer = Encoding.ASCII.GetBytes(input); AuthenticationResults authres; Assert.IsTrue(AuthenticationResults.TryParse(buffer, 0, buffer.Length, out authres)); Assert.AreEqual("example.com", authres.AuthenticationServiceIdentifier, "authserv-id"); Assert.AreEqual(2, authres.Results.Count, "methods"); Assert.AreEqual("dkim", authres.Results[0].Method); Assert.AreEqual("pass", authres.Results[0].Result); Assert.AreEqual("good signature", authres.Results[0].Reason); Assert.AreEqual(1, authres.Results[0].Properties.Count, "dkim properties"); Assert.AreEqual("header", authres.Results[0].Properties[0].PropertyType); Assert.AreEqual("i", authres.Results[0].Properties[0].Property); Assert.AreEqual("@mail-router.example.net", authres.Results[0].Properties[0].Value); Assert.AreEqual("dkim", authres.Results[1].Method); Assert.AreEqual("fail", authres.Results[1].Result); Assert.AreEqual("bad signature", authres.Results[1].Reason); Assert.AreEqual(1, authres.Results[1].Properties.Count, "dkim properties"); Assert.AreEqual("header", authres.Results[1].Properties[0].PropertyType); Assert.AreEqual("i", authres.Results[1].Properties[0].Property); Assert.AreEqual("@newyork.example.com", authres.Results[1].Properties[0].Value); Assert.AreEqual(input, authres.ToString()); const string expected = " example.com;\n\tdkim=pass reason=\"good signature\" [email protected];\n\tdkim=fail reason=\"bad signature\" [email protected]\n"; var encoded = new StringBuilder(); var options = FormatOptions.Default.Clone(); options.NewLineFormat = NewLineFormat.Unix; authres.Encode(options, encoded, "Authentication-Results:".Length); Assert.AreEqual(expected, encoded.ToString()); }