mailrs_outbound_queue/
mta_sts.rs1pub fn mx_matches_policy(mx_host: &str, policy_mx: &[&str]) -> bool {
3 let mx_lower = mx_host.to_lowercase();
4 for pattern in policy_mx {
5 let p = pattern.to_lowercase();
6 if p.starts_with("*.") {
7 let suffix = &p[1..]; if mx_lower.ends_with(&suffix) && mx_lower.len() > suffix.len() {
10 let prefix = &mx_lower[..mx_lower.len() - suffix.len()];
12 if !prefix.contains('.') {
13 return true;
14 }
15 }
16 } else if mx_lower == p {
17 return true;
18 }
19 }
20 false
21}
22
23#[cfg(test)]
24mod tests {
25 use super::*;
26
27 #[test]
28 fn exact_match() {
29 assert!(mx_matches_policy("mail.example.com", &["mail.example.com"]));
30 }
31
32 #[test]
33 fn wildcard_match() {
34 assert!(mx_matches_policy("mail.example.com", &["*.example.com"]));
35 }
36
37 #[test]
38 fn wildcard_no_match_different_domain() {
39 assert!(!mx_matches_policy("other.com", &["*.example.com"]));
40 }
41
42 #[test]
43 fn wildcard_no_match_subdomain() {
44 assert!(!mx_matches_policy(
46 "sub.mail.example.com",
47 &["*.example.com"]
48 ));
49 }
50
51 #[test]
52 fn case_insensitive() {
53 assert!(mx_matches_policy("MAIL.Example.COM", &["*.example.com"]));
54 }
55
56 #[test]
57 fn no_match() {
58 assert!(!mx_matches_policy("mail.other.com", &["*.example.com"]));
59 }
60
61 #[test]
62 fn multiple_patterns() {
63 assert!(mx_matches_policy(
64 "backup.example.com",
65 &["mail.example.com", "*.example.com"]
66 ));
67 }
68
69 #[test]
70 fn empty_policy_never_matches() {
71 assert!(!mx_matches_policy("mail.example.com", &[]));
72 }
73
74 #[test]
75 fn wildcard_does_not_match_bare_domain() {
76 assert!(!mx_matches_policy("example.com", &["*.example.com"]));
78 }
79
80 #[test]
81 fn exact_match_case_insensitive() {
82 assert!(mx_matches_policy("MAIL.EXAMPLE.COM", &["mail.example.com"]));
83 assert!(mx_matches_policy("mail.example.com", &["MAIL.EXAMPLE.COM"]));
84 }
85
86 #[test]
87 fn wildcard_matches_single_label_only() {
88 assert!(mx_matches_policy("a.example.com", &["*.example.com"]));
90 assert!(!mx_matches_policy("a.b.example.com", &["*.example.com"]));
91 }
92
93 #[test]
94 fn no_false_positive_partial_suffix() {
95 assert!(!mx_matches_policy("mailnotexample.com", &["*.example.com"]));
97 }
98
99 #[test]
100 fn first_matching_pattern_wins() {
101 assert!(mx_matches_policy(
103 "mail.example.com",
104 &["mail.example.com", "*.other.com"]
105 ));
106 }
107
108 #[test]
109 fn pattern_without_wildcard_no_partial_match() {
110 assert!(!mx_matches_policy("mail.example.com", &["example.com"]));
112 }
113
114 #[test]
115 fn wildcard_pattern_case_insensitive_uppercase() {
116 assert!(mx_matches_policy("mail.example.com", &["*.EXAMPLE.COM"]));
117 }
118
119 #[test]
120 fn wildcard_pattern_mixed_case() {
121 assert!(mx_matches_policy("Mail.Example.Com", &["*.example.com"]));
122 assert!(mx_matches_policy("mail.example.com", &["*.Example.Com"]));
123 }
124
125 #[test]
126 fn wildcard_does_not_match_empty_prefix() {
127 assert!(!mx_matches_policy(".example.com", &["*.example.com"]));
130 }
131
132 #[test]
133 fn exact_match_trailing_case_sensitivity() {
134 assert!(mx_matches_policy("mx1.gmail.com", &["mx1.gmail.com"]));
135 assert!(mx_matches_policy("MX1.GMAIL.COM", &["mx1.gmail.com"]));
136 }
137
138 #[test]
139 fn wildcard_single_char_prefix() {
140 assert!(mx_matches_policy("a.example.com", &["*.example.com"]));
141 }
142
143 #[test]
144 fn wildcard_long_prefix() {
145 assert!(mx_matches_policy(
146 "very-long-hostname-label.example.com",
147 &["*.example.com"]
148 ));
149 }
150
151 #[test]
152 fn wildcard_hyphenated_prefix() {
153 assert!(mx_matches_policy(
154 "mail-relay-01.example.com",
155 &["*.example.com"]
156 ));
157 }
158
159 #[test]
160 fn wildcard_numeric_prefix() {
161 assert!(mx_matches_policy("123.example.com", &["*.example.com"]));
162 }
163
164 #[test]
165 fn multiple_patterns_first_exact_wins() {
166 assert!(mx_matches_policy(
167 "mx.example.com",
168 &["mx.example.com", "*.other.com"]
169 ));
170 }
171
172 #[test]
173 fn multiple_patterns_second_wildcard_wins() {
174 assert!(mx_matches_policy(
175 "relay.other.com",
176 &["mx.example.com", "*.other.com"]
177 ));
178 }
179
180 #[test]
181 fn multiple_patterns_none_match() {
182 assert!(!mx_matches_policy(
183 "mail.unknown.org",
184 &["mx.example.com", "*.other.com"]
185 ));
186 }
187
188 #[test]
189 fn wildcard_with_deeper_subdomain_parent() {
190 assert!(mx_matches_policy(
192 "relay.mail.example.com",
193 &["*.mail.example.com"]
194 ));
195 }
196
197 #[test]
198 fn wildcard_with_deeper_subdomain_no_double() {
199 assert!(!mx_matches_policy(
201 "a.b.mail.example.com",
202 &["*.mail.example.com"]
203 ));
204 }
205
206 #[test]
207 fn wildcard_pattern_exact_domain_not_matched() {
208 assert!(!mx_matches_policy(
210 "mail.example.com",
211 &["*.mail.example.com"]
212 ));
213 }
214
215 #[test]
216 fn pattern_with_only_wildcard_star_dot() {
217 assert!(mx_matches_policy("anything.com", &["*.com"]));
219 }
220
221 #[test]
222 fn pattern_star_dot_does_not_match_subdomain() {
223 assert!(!mx_matches_policy("a.b.com", &["*.com"]));
225 }
226
227 #[test]
228 fn empty_mx_host_never_matches() {
229 assert!(!mx_matches_policy("", &["*.example.com"]));
230 assert!(!mx_matches_policy("", &["example.com"]));
231 }
232
233 #[test]
234 fn empty_mx_host_and_empty_policy() {
235 assert!(!mx_matches_policy("", &[]));
236 }
237
238 #[test]
239 fn exact_match_does_not_match_substring() {
240 assert!(!mx_matches_policy("notexample.com", &["example.com"]));
242 }
243
244 #[test]
245 fn exact_match_does_not_match_superdomain() {
246 assert!(!mx_matches_policy("example.com", &["sub.example.com"]));
247 }
248
249 #[test]
250 fn many_patterns_performance() {
251 let patterns: Vec<String> = (0..100)
253 .map(|i| format!("mx{}.example{}.com", i, i))
254 .collect();
255 let pattern_refs: Vec<&str> = patterns.iter().map(|s| s.as_str()).collect();
256 assert!(!mx_matches_policy("mx.unknown.com", &pattern_refs));
257 assert!(mx_matches_policy("mx50.example50.com", &pattern_refs));
258 }
259
260 #[test]
261 fn wildcard_many_patterns_last_matches() {
262 let mut patterns: Vec<String> =
263 (0..99).map(|i| format!("mx{}.wrong{}.com", i, i)).collect();
264 patterns.push("*.target.com".to_string());
265 let pattern_refs: Vec<&str> = patterns.iter().map(|s| s.as_str()).collect();
266 assert!(mx_matches_policy("relay.target.com", &pattern_refs));
267 }
268
269 #[test]
270 fn real_world_google_mx_patterns() {
271 let policy = &["gmail-smtp-in.l.google.com", "*.gmail-smtp-in.l.google.com"];
273 assert!(mx_matches_policy("gmail-smtp-in.l.google.com", policy));
274 assert!(mx_matches_policy("alt1.gmail-smtp-in.l.google.com", policy));
275 let broad_policy = &["*.google.com"];
277 assert!(!mx_matches_policy(
278 "alt1.gmail-smtp-in.l.google.com",
279 broad_policy
280 ));
281 }
282
283 #[test]
284 fn real_world_microsoft_mx_patterns() {
285 let policy = &["*.mail.protection.outlook.com"];
286 assert!(mx_matches_policy(
287 "contoso-com.mail.protection.outlook.com",
288 policy
289 ));
290 assert!(!mx_matches_policy(
291 "a.b.mail.protection.outlook.com",
292 policy
293 ));
294 }
295}