-
Notifications
You must be signed in to change notification settings - Fork 38
Authenticated Received Chain - ARC-sealing #31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
agrinchenko
wants to merge
115
commits into
apache:master
Choose a base branch
from
agrinchenko:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
115 commits
Select commit
Hold shift + click to select a range
22266e5
Merge pull request #8 from Weiling-Liao/master
mbaechler e8a21b0
JDKIM-42 Upgrade apache parent pom version 18 -> 21
Arsnael ab18800
JDKIM-42 Upgrade maven-assembly-plugin 3.0.0 -> 3.1.1
Arsnael bc8ace8
JDKIM-42 Upgrade junit 4.10 -> 4.12
Arsnael fa03947
JDKIM-42 Upgrade commons-codec 1.7 -> 1.13
Arsnael 62408fd
JDKIM-42 Upgrade commons-logging 1.1.1 -> 1.2
Arsnael eabf827
JDKIM-42 Upgrade dnsjava 2.1.1 -> 2.1.9
Arsnael e3f49cb
JDKIM-42 Upgrade log4j 1.2.16 -> log4j-core 2.12.1
Arsnael 2ee6bc6
JDKIM-42 Upgrade maven-site-plugin 3.3 -> 3.7.1
Arsnael b4f162c
JDKIM-42 Upgrade wagon-ssh 2.0 -> 3.3.3
Arsnael 2d6177a
JDKIM-42 Upgrade maven-bundle-plugin 2.3.7 -> 4.2.1
Arsnael c8bc3db
JDKIM-42 Upgrade maven-compiler-plugin 3.0 -> 3.8.1
Arsnael 7b263de
JDKIM-42 Upgrade apache-rat-plugin 0.8 -> 0.13
Arsnael 3d05194
JDKIM-42 Upgrade versions-maven-plugin 2.0 -> 2.7
Arsnael b558816
JDKIM-42 Upgrade apache-mime4j 0.8.1 -> 0.8.3
Arsnael 8a92e65
JDKIM-42 Reorder dependencies in pom files
Arsnael c896a16
JDKIM-42 Remove apache-jdkim-mailets
Arsnael 82c43f5
JDKIM-42 Remove geronimo libs
Arsnael 6ce11b2
JDKIM-42 Update README to state that the mailet has been moved to Jam…
Arsnael a3269a8
JDKIM-44 Use JDK 8 as a target JDK
chibenwa 1005b1c
[JAMES-3226] #comment Added antora docs stub
ieugen ac56007
JDKIM-46 Set up Jenkins build system
chibenwa a5a91b2
[Documentation] Links should enforce HTTPS in menus
chibenwa cb715a8
[Documentation] Retire HUPA
chibenwa 1b04fb8
Upgrade DNS Java 2.1.9 -> 3.4.1
chibenwa 087df46
Upgrade commons-codec 1.13 -> 1.15
chibenwa 3fa5e75
Upgrade junit 4.12 -> 4.13.2
chibenwa 95862c5
Upgrade log4j 2.12.1 -> 2.14.1
chibenwa 80a6909
Upgrade wagon-ssh 3.3.3 -> 3.4.3
chibenwa 4f4d6ef
Remove unused log4j
quantranhong1999 9204dc5
Relocate SCM
chibenwa 8282f63
[maven-release-plugin] prepare release apache-jdkim-project-0.3
chibenwa 2a9eaf4
[maven-release-plugin] prepare for next development iteration
chibenwa c3558b0
Bump org.apache.james:apache-mime4j-core from 0.8.3 to 0.8.10 (#16)
dependabot[bot] 4986301
Bump dnsjava:dnsjava from 3.4.1 to 3.6.0 (#17)
dependabot[bot] 32f4438
Upgrade to latest mime4j version
chibenwa 9526639
Update commons-logging
chibenwa 7bab625
Update commons-codec
chibenwa 4ac911d
Remove bundle packaging - release fails
chibenwa ef0f4bc
[maven-release-plugin] prepare release apache-jdkim-project-0.4
chibenwa 0a92278
[maven-release-plugin] prepare for next development iteration
chibenwa 33c3f23
Revert "[maven-release-plugin] prepare for next development iteration"
Arsnael dab5d0f
Revert "[maven-release-plugin] prepare release apache-jdkim-project-0.4"
Arsnael c372f28
[maven-release-plugin] prepare release apache-jdkim-project-0.4
Arsnael 0a8a798
[maven-release-plugin] prepare for next development iteration
Arsnael edeceed
[FIX] Shade the all commons-codec lib into jdkim (#19)
Arsnael b6d70e8
Add dependency-reduced-pom to gitignore (#22)
epinter 304984b
Store SignatureRecord in FailException
epinter 7a07d58
Pass SignatureRecord to PermFailException
epinter 92438be
Remove unused commons-logging
epinter 5d6bac9
Remove unused not-yet-commons-ssl
epinter 1efd3c3
Update mime4j to 0.8.12
epinter ba0ab5c
Update commons-codec to 1.18.0
epinter 7c85b64
Update dnsjava to 3.6.3
epinter f5b87ef
Add a list of results to verifier (#23)
epinter df871da
Code cleanup
epinter 9ddcce8
Remove unused condition
epinter 2f62fac
Simplify dns lookup code
epinter 2d37cd6
[devscout] fixes selector for google dkim signature
jeantil f5222fc
[devscout] cleans up redundant keywords
jeantil cf7b653
[devscout] removes accessors for internals
jeantil 45eff3a
[devscout] makes MultiplexingPublicKeyRecordRetriever API immutable
jeantil 6daf8b5
[devscout] removes unnecessary inheritance of DKIMCommon
jeantil 9aca9bd
[devscout] moves dkimQuotedPrintableDecode to SignatureRecord
jeantil e895067
[devscout] introduce SignatureRecordTemplate
jeantil a562f92
[devscout] documents proper JDKIM API usage
jeantil 948680a
Add DMARC compliant result method
epinter 2262f97
Only 'pass' result should be considered for valid signatures.
epinter f079e46
Remove unneeded method.
epinter a20366f
[maven-release-plugin] prepare release apache-jdkim-project-0.5
Arsnael d55ca3c
[maven-release-plugin] prepare for next development iteration
Arsnael c4cd7a4
JDKIM-49 Add clock drift tolerance to signature validation
epinter ccd7b4d
Adopt JDK 11 as a build target (#29)
chibenwa a93add8
First commit
agrinchenko b68a0d8
Update arc/src/main/java/org/apache/james/arc/ArcSealVerifyData.java
agrinchenko bb93a64
Update arc/src/main/java/org/apache/james/arc/ARCChainValidator.java
agrinchenko 90dd4a2
Update arc/src/main/java/org/apache/james/arc/ARCChainValidator.java
agrinchenko 95d9aba
Update arc/src/main/java/org/apache/james/arc/ARCChainValidator.java
agrinchenko f766428
Refactor ARC to minimize dependencies and address some initial PR fee…
agrinchenko fb3718f
Remove commons-codec
epinter dcaec3a
Rework DMARK and reduce dependencies
agrinchenko 1f420fd
Adding DMARC pom.xml that was missing in the previous commit
agrinchenko 36da05e
Remove maven compiler plugin in DMARC pom.xml causing build to fail
agrinchenko 0d7b82e
Add to the maven-compiler-plugin in DMARC pom.xml to fix the auto bu…
agrinchenko ac8d95b
Add to the maven-compiler-plugin in ARC pom.xml to fix the auto buil…
agrinchenko abe368c
Updating ARC pom to make sure it can see DMARC test dependencies on J…
agrinchenko 864a57d
Fixing the Jenkins build. Realigning to JDK 11
agrinchenko 2193cdb
Add missing license info. Reorder 'dmarc' and 'arc' modules in the pa…
agrinchenko 786bb64
Rewrote PSL matching to handle exceptions/wildcards plus:
agrinchenko e559df1
Bump org.assertj:assertj-core from 3.26.0 to 3.27.7
dependabot[bot] b02988d
Updated README to reflect the purpose of the fork
agrinchenko 84d6bd9
Update README.adoc
agrinchenko 4df4d24
Merge branch 'apache:master' into master
agrinchenko 8cd21d0
Fix site build and ARC/DMARC test support
agrinchenko 8850c77
Merge upstream master
agrinchenko cb4b6ff
Updated README to show ARC Test examples
agrinchenko 797bfd2
Add cv_fail_i1_ams_invalid test: assert cv=fail when ARC-Message-Sign…
agrinchenko 4914e05
Add cv_fail_i1_as_invalid test: assert cv=fail when ARC-Seal b= is cr…
agrinchenko 53153d4
Fix ARCChainValidator to return cv=fail instead of throwing when ARC …
agrinchenko 8d35409
Add 10 cv_fail_i2_* tests: assert cv=fail for all structural and sign…
agrinchenko cbb24f1
Fix a bug in ARC-Seal to cover all prior hop headers as per RFC 8617;…
agrinchenko a1c1701
Add AMS structural validation tests and fix uncaught exceptions for m…
agrinchenko fac3949
Add AMS tag format validation tests and fix null-safe DNS result hand…
agrinchenko d7e40d8
Add canonicalization tests for body whitespace and header normalization
agrinchenko 4bf5653
Add ARC AMS formatting and duplicate instance tests:
agrinchenko c6dbdb2
Expand ARC validation coverage and fix header parsing:
agrinchenko 3ac3c01
Add ARC-Seal field validation tests:
agrinchenko b5fde46
Add ARC-Seal b= validation test coverage:
agrinchenko 87539b9
Add the ARC-Seal b= group test cases:
agrinchenko d51933d
Added more AMS field validation coverage:
agrinchenko 72c8fe1
Add ARC body hash and key fixture coverage:
agrinchenko 25a1356
Added ValiMail coverage tests in ARCTest for "c=" edge cases:
agrinchenko ff1dcbb
Added AMS tag validation in ARCVerifier:
agrinchenko ff3b04f
Add remaining ARC h= and first-hop signing test coverage:
agrinchenko 5f04ea9
Updated README with a Test Coverage section
agrinchenko File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,88 +1,112 @@ | ||
| = JAMES jDKIM library | ||
| = JAMES jDKIM fork with ARC support | ||
|
|
||
| This repository is a fork of Apache James jDKIM that adds ARC (Authenticated Received Chain) signing and related mail authentication capabilities alongside | ||
| the original DKIM functionality. | ||
|
|
||
| Library dealing with parsing and crytography to sign and verify DKIM signatures. | ||
| It is intended for experimentation and integration work around RFC 8617 in Java-based mail processing workflows. | ||
|
|
||
| Original upstream project: | ||
| https://github.com/apache/james-jdkim | ||
|
|
||
| The mailet has been moved to James project: https://github.com/apache/james-project/tree/master/server/mailet/dkim | ||
|
|
||
| == Fork-specific additions | ||
|
|
||
| This fork extends the original Apache James jDKIM codebase with ARC-related functionality. | ||
|
|
||
| Current fork-specific focus includes: | ||
|
|
||
| - ARC signing support | ||
| - ARC chain handling | ||
| - Mail authentication extensions related to RFC 8617 | ||
|
|
||
| == Test Coverage | ||
|
|
||
| ARC functionality is covered by tests in | ||
| https://github.com/apache/james-jdkim/blob/master/arc/src/test/java/org/apache/james/arc/ARCTest.java[ARCTest]. | ||
| The coverage is based on the ARC protocol requirements from | ||
| https://datatracker.ietf.org/doc/html/rfc8617[RFC 8617] and on the public | ||
| https://github.com/ValiMail/arc_test_suite[ValiMail ARC test suite]. The tests | ||
| exercise ARC set creation, chain validation, ARC-Seal verification, | ||
| ARC-Message-Signature canonicalization, body hash handling, required tag | ||
| validation, and malformed or tampered ARC header cases. | ||
|
|
||
| == Usage | ||
|
|
||
| A full example is available in | ||
| https://github.com/apache/james-jdkim/blob/master/main/src/test/java/org/apache/james/jdkim/DKIMTest.java[DKIMTest] | ||
| https://github.com/apache/james-jdkim/blob/master/arc/src/test/java/org/apache/james/arc/ARCTest.java[ARCTest] | ||
|
|
||
| === Signing | ||
| === Building An ARC Set | ||
|
|
||
| Signing a mime message can be achieved using the following snippet | ||
| Generating ARC headers for a MIME message can be achieved using the following | ||
| snippet. | ||
|
|
||
| [source,java] | ||
| ---- | ||
| import java.io.InputStream; | ||
| import java.security.PrivateKey; | ||
| import java.util.Map; | ||
|
|
||
| import org.apache.james.arc.ArcSetBuilder; | ||
| import org.apache.james.arc.PublicKeyRetrieverArc; | ||
| import org.apache.james.mime4j.dom.Message; | ||
| import org.apache.james.mime4j.message.DefaultMessageBuilder; | ||
|
|
||
| String signatureTemplate = "v=1; a=rsa-sha256; c=simple; d=messiah.edu; h=date:from:subject; q=dns/txt; s=selector2;"; | ||
| String amsTemplate = "i=; a=rsa-sha256; c=relaxed/relaxed; d=example.org; s=arc; t=; h=Subject:From:To; bh=; b="; | ||
| String sealTemplate = "i=; cv=; a=rsa-sha256; d=example.org; s=arc; t=; b="; | ||
|
|
||
| PrivateKey privateKey = null; | ||
| DKIMSigner dkimSigner = new DKIMSigner(signatureTemplate, privateKey); | ||
| // You need to provide the input stream of the mime message, it will be parsed | ||
| // by mime4j | ||
| InputStream stream = null; | ||
| String signature = dkimSigner.sign(inputStream); | ||
| // `signature` contains the full header | ||
| // DKIM-Signature: a=rsa-sha256; q=dns/txt; b=Axa8s/g...U1SIw==; c=simple; s=selector2; d=messiah.edu; v=1; bh=6pQ...6g=; h=date:from:subject; | ||
| Message message = new DefaultMessageBuilder().parseMessage(stream); | ||
|
|
||
| ArcSetBuilder arcSetBuilder = new ArcSetBuilder( | ||
| privateKey, | ||
| amsTemplate, | ||
| sealTemplate, | ||
| "mx.example.org", | ||
| System.currentTimeMillis() / 1000); | ||
|
|
||
| PublicKeyRetrieverArc keyRecordRetriever = null; | ||
| Map<String, String> arcSet = arcSetBuilder.buildArcSet( | ||
| message, | ||
| "mail.example.org", | ||
| "sender@example.org", | ||
| "192.0.2.1", | ||
| keyRecordRetriever); | ||
|
|
||
| String authenticationResults = arcSet.get("Authentication-Results"); | ||
| String arcAuthenticationResults = arcSet.get("ARC-Authentication-Results"); | ||
| String arcMessageSignature = arcSet.get("ARC-Message-Signature"); | ||
| String arcSeal = arcSet.get("ARC-Seal"); | ||
| ---- | ||
|
|
||
| More advanced usage such as including multiple signatures can be found in | ||
| https://github.com/apache/james-jdkim/blob/master/main/src/test/java/org/apache/james/jdkim/DKIMTest.java[DKIMTest] | ||
| The generated map contains the ARC headers for the current hop, ready to be | ||
| added to the message. | ||
|
|
||
| More complete usage can be found in | ||
| https://github.com/apache/james-jdkim/blob/master/arc/src/test/java/org/apache/james/arc/ARCTest.java[ARCTest] | ||
|
|
||
| === Verifying | ||
| === Validating An ARC Chain | ||
|
|
||
| Verifying a mime message DKIM signatures can be achieved using the following | ||
| snippet. The verifier always verifies all the signatures. | ||
| Validating ARC headers on a MIME message can be achieved using the following | ||
| snippet. | ||
|
|
||
| [source,java] | ||
| ---- | ||
| import java.io.InputStream; | ||
| // You can override the resolver in the constructor, use your own | ||
| // implementation of a retriever or use multiple implementations using a | ||
| // `MultiplexingPublicKeyRecordRetriever` | ||
| PublicKeyRecordRetriever keyRecordRetriever = new DNSPublicKeyRecordRetriever(); | ||
| DKIMVerifier verifier = new DKIMVerifier(keyRecordRetriever); | ||
| InputStream stream = null; // you need to provide the input stream of the mime message | ||
| List<SignatureRecord> verifiedSignatures = verifier.verify(stream); | ||
| // `verifiedSignatures` contains only the signatures that have successfully | ||
| // passed the validation. | ||
| // If you want to query all the results including all the failures, you can | ||
| // retrieve them from the verifier | ||
| List<Result> results = verifier.getResults(); | ||
| ---- | ||
| import org.apache.james.arc.ARCChainValidator; | ||
| import org.apache.james.arc.ArcValidationOutcome; | ||
| import org.apache.james.arc.PublicKeyRetrieverArc; | ||
| import org.apache.james.mime4j.dom.Message; | ||
| import org.apache.james.mime4j.message.DefaultMessageBuilder; | ||
|
|
||
| PublicKeyRetrieverArc keyRecordRetriever = null; | ||
| InputStream stream = null; | ||
| Message message = new DefaultMessageBuilder().parseMessage(stream); | ||
|
|
||
| == Cryptography Notice | ||
| ARCChainValidator arcChainValidator = new ARCChainValidator(keyRecordRetriever); | ||
| ArcValidationOutcome validation = arcChainValidator.validateArcChain(message); | ||
|
|
||
| boolean valid = validation.isValid(); | ||
| String chainValidation = validation.getResult().toString(); | ||
| ---- | ||
| This distribution includes cryptographic software. The country in | ||
| which you currently reside may have restrictions on the import, | ||
| possession, use, and/or re-export to another country, of | ||
| encryption software. BEFORE using any encryption software, please | ||
| check your country's laws, regulations and policies concerning the | ||
| import, possession, or use, and re-export of encryption software, to | ||
| see if this is permitted. See http://www.wassenaar.org for more | ||
| information. | ||
|
|
||
| The U.S. Government Department of Commerce, Bureau of Industry and | ||
| Security (BIS), has classified this software as Export Commodity | ||
| Control Number (ECCN) 5D002.C.1, which includes information security | ||
| software using or performing cryptographic functions with asymmetric | ||
| algorithms. The form and manner of this Apache Software Foundation | ||
| distribution makes it eligible for export under the License Exception | ||
| ENC Technology Software Unrestricted (TSU) exception (see the BIS | ||
| Export Administration Regulations, Section 740.13) for both object | ||
| code and source code. | ||
|
|
||
| The following provides more details on the included cryptographic | ||
| software: | ||
|
|
||
| - jDKIM includes code designed to work with Java SE Security | ||
|
|
||
| Export classifications and source links can be found | ||
| at http://www.apache.org/licenses/exports/. | ||
| ---- | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <!-- | ||
| Licensed to the Apache Software Foundation (ASF) under one | ||
| or more contributor license agreements. See the NOTICE file | ||
| distributed with this work for additional information | ||
| regarding copyright ownership. The ASF licenses this file | ||
| to you under the Apache License, Version 2.0 (the | ||
| "License"); you may not use this file except in compliance | ||
| with the License. You may obtain a copy of the License at | ||
|
|
||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
|
|
||
| Unless required by applicable law or agreed to in writing, | ||
| software distributed under the License is distributed on an | ||
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| KIND, either express or implied. See the License for the | ||
| specific language governing permissions and limitations | ||
| under the License. | ||
| --> | ||
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
| <modelVersion>4.0.0</modelVersion> | ||
|
|
||
| <parent> | ||
| <artifactId>apache-jdkim-project</artifactId> | ||
| <groupId>org.apache.james.jdkim</groupId> | ||
| <version>0.6-SNAPSHOT</version> | ||
| <relativePath>../pom.xml</relativePath> | ||
| </parent> | ||
|
|
||
| <artifactId>apache-arc-library</artifactId> | ||
|
|
||
| <name>Apache James :: ARC</name> | ||
| <description>A Java implementation for the ARC specification.</description> | ||
| <url>http://james.apache.org/jdkim/main/</url> | ||
| <inceptionYear>2008</inceptionYear> | ||
|
|
||
| <dependencies> | ||
| <dependency> | ||
| <groupId>org.apache.james.jdkim</groupId> | ||
| <artifactId>apache-dmarc-library</artifactId> | ||
| <version>${project.version}</version> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.apache.james.jdkim</groupId> | ||
| <artifactId>apache-dmarc-library</artifactId> | ||
| <version>${project.version}</version> | ||
| <type>test-jar</type> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.apache.james.jdkim</groupId> | ||
| <artifactId>apache-jdkim-library</artifactId> | ||
| <version>${project.version}</version> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.apache.james.jdkim</groupId> | ||
| <artifactId>apache-jdkim-library</artifactId> | ||
| <version>${project.version}</version> | ||
| <type>test-jar</type> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.apache.james.jspf</groupId> | ||
| <artifactId>apache-jspf-resolver</artifactId> | ||
| <version>${jspf-resolver.version}</version> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>junit</groupId> | ||
| <artifactId>junit</artifactId> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.apache.james</groupId> | ||
| <artifactId>apache-mime4j-core</artifactId> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.apache.james</groupId> | ||
| <artifactId>apache-mime4j-dom</artifactId> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.assertj</groupId> | ||
| <artifactId>assertj-core</artifactId> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| </dependencies> | ||
| </project> |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please rework the readme:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, agreed. Reworking the README to keep the upstream-neutral project framing and preserve the existin DKIM explanations. Adding ARC as a dedicated support section instead of redefining the repository as a fork. Also adding a short DMARC usage example as sugested.