rusmes_core/matchers/
recipient_is_local.rs1use crate::matcher::Matcher;
4use async_trait::async_trait;
5use rusmes_proto::{Mail, MailAddress};
6
7pub struct RecipientIsLocalMatcher {
9 local_domains: Vec<String>,
10}
11
12impl RecipientIsLocalMatcher {
13 pub fn new(local_domains: Vec<String>) -> Self {
15 Self { local_domains }
16 }
17}
18
19#[async_trait]
20impl Matcher for RecipientIsLocalMatcher {
21 async fn match_mail(&self, mail: &Mail) -> anyhow::Result<Vec<MailAddress>> {
22 let matched: Vec<MailAddress> = mail
23 .recipients()
24 .iter()
25 .filter(|addr| {
26 self.local_domains
27 .iter()
28 .any(|domain| addr.domain().as_str() == domain)
29 })
30 .cloned()
31 .collect();
32
33 Ok(matched)
34 }
35
36 fn name(&self) -> &str {
37 "RecipientIsLocal"
38 }
39}
40
41#[cfg(test)]
42mod tests {
43 use super::*;
44 use bytes::Bytes;
45 use rusmes_proto::{HeaderMap, MessageBody, MimeMessage};
46
47 #[tokio::test]
48 async fn test_recipient_is_local() {
49 let matcher = RecipientIsLocalMatcher::new(vec!["example.com".to_string()]);
50
51 let recipients = vec![
52 "local@example.com".parse().unwrap(),
53 "remote@other.com".parse().unwrap(),
54 ];
55
56 let message = MimeMessage::new(HeaderMap::new(), MessageBody::Small(Bytes::from("Test")));
57 let mail = Mail::new(None, recipients, message, None, None);
58
59 let matched = matcher.match_mail(&mail).await.unwrap();
60 assert_eq!(matched.len(), 1);
61 assert_eq!(matched[0].domain().as_str(), "example.com");
62 }
63}