1 | /*
|
2 | * Copyright (c) 2020-2023, Stalwart Labs Ltd.
|
3 | *
|
4 | * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
5 | * https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
6 | * <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
|
7 | * option. This file may not be copied, modified, or distributed
|
8 | * except according to those terms.
|
9 | */
|
10 |
|
11 | use mail_auth::report::{
|
12 | ActionDisposition, Alignment, DKIMAuthResult, Disposition, DkimResult, DmarcResult,
|
13 | PolicyOverride, PolicyOverrideReason, Record, Report, SPFAuthResult, SPFDomainScope, SpfResult,
|
14 | };
|
15 |
|
16 | fn main() {
|
17 | // Generate DMARC aggregate report
|
18 | let report = Report::new()
|
19 | .with_version(1.0)
|
20 | .with_org_name("Initech Industries Incorporated")
|
21 | .with_email("dmarc@initech.net")
|
22 | .with_extra_contact_info("XMPP:dmarc@initech.net")
|
23 | .with_report_id("abc-123")
|
24 | .with_date_range_begin(12345)
|
25 | .with_date_range_end(12346)
|
26 | .with_error("Did not include TPS report cover.")
|
27 | .with_domain("example.org")
|
28 | .with_version_published(1.0)
|
29 | .with_adkim(Alignment::Relaxed)
|
30 | .with_aspf(Alignment::Strict)
|
31 | .with_p(Disposition::Quarantine)
|
32 | .with_sp(Disposition::Reject)
|
33 | .with_testing(false)
|
34 | .with_record(
|
35 | Record::new()
|
36 | .with_source_ip("192.168.1.2".parse().unwrap())
|
37 | .with_count(3)
|
38 | .with_action_disposition(ActionDisposition::Pass)
|
39 | .with_dmarc_dkim_result(DmarcResult::Pass)
|
40 | .with_dmarc_spf_result(DmarcResult::Fail)
|
41 | .with_policy_override_reason(
|
42 | PolicyOverrideReason::new(PolicyOverride::Forwarded)
|
43 | .with_comment("it was forwarded"),
|
44 | )
|
45 | .with_policy_override_reason(
|
46 | PolicyOverrideReason::new(PolicyOverride::MailingList)
|
47 | .with_comment("sent from mailing list"),
|
48 | )
|
49 | .with_envelope_from("hello@example.org")
|
50 | .with_envelope_to("other@example.org")
|
51 | .with_header_from("bye@example.org")
|
52 | .with_dkim_auth_result(
|
53 | DKIMAuthResult::new()
|
54 | .with_domain("test.org")
|
55 | .with_selector("my-selector")
|
56 | .with_result(DkimResult::PermError)
|
57 | .with_human_result("failed to parse record"),
|
58 | )
|
59 | .with_spf_auth_result(
|
60 | SPFAuthResult::new()
|
61 | .with_domain("test.org")
|
62 | .with_scope(SPFDomainScope::Helo)
|
63 | .with_result(SpfResult::SoftFail)
|
64 | .with_human_result("dns timed out"),
|
65 | ),
|
66 | )
|
67 | .with_record(
|
68 | Record::new()
|
69 | .with_source_ip("a:b:c::e:f".parse().unwrap())
|
70 | .with_count(99)
|
71 | .with_action_disposition(ActionDisposition::Reject)
|
72 | .with_dmarc_dkim_result(DmarcResult::Fail)
|
73 | .with_dmarc_spf_result(DmarcResult::Pass)
|
74 | .with_policy_override_reason(
|
75 | PolicyOverrideReason::new(PolicyOverride::LocalPolicy)
|
76 | .with_comment("on the white list"),
|
77 | )
|
78 | .with_policy_override_reason(
|
79 | PolicyOverrideReason::new(PolicyOverride::SampledOut)
|
80 | .with_comment("it was sampled out"),
|
81 | )
|
82 | .with_envelope_from("hello2example.org")
|
83 | .with_envelope_to("other2@example.org")
|
84 | .with_header_from("bye2@example.org")
|
85 | .with_dkim_auth_result(
|
86 | DKIMAuthResult::new()
|
87 | .with_domain("test2.org")
|
88 | .with_selector("my-other-selector")
|
89 | .with_result(DkimResult::Neutral)
|
90 | .with_human_result("something went wrong"),
|
91 | )
|
92 | .with_spf_auth_result(
|
93 | SPFAuthResult::new()
|
94 | .with_domain("test.org")
|
95 | .with_scope(SPFDomainScope::MailFrom)
|
96 | .with_result(SpfResult::None)
|
97 | .with_human_result("no policy found"),
|
98 | ),
|
99 | )
|
100 | .to_rfc5322(
|
101 | "initech.net",
|
102 | ("Initech Industries", "noreply-dmarc@initech.net"),
|
103 | ["dmarc-reports@example.org"].iter().copied(),
|
104 | )
|
105 | .unwrap();
|
106 |
|
107 | // Print report to stdout
|
108 | println!("{}", report);
|
109 | }
|