1use async_trait::async_trait;
4use rusmes_proto::{Mail, MailAddress};
5
6#[async_trait]
8pub trait Matcher: Send + Sync {
9 async fn match_mail(&self, mail: &Mail) -> anyhow::Result<Vec<MailAddress>>;
11
12 fn name(&self) -> &str;
14}
15
16#[allow(dead_code)]
18pub struct AllMatcher;
19
20#[async_trait]
21impl Matcher for AllMatcher {
22 async fn match_mail(&self, mail: &Mail) -> anyhow::Result<Vec<MailAddress>> {
23 Ok(mail.recipients().to_vec())
24 }
25
26 fn name(&self) -> &str {
27 "All"
28 }
29}
30
31#[allow(dead_code)]
33pub struct NoneMatcher;
34
35#[async_trait]
36impl Matcher for NoneMatcher {
37 async fn match_mail(&self, _mail: &Mail) -> anyhow::Result<Vec<MailAddress>> {
38 Ok(Vec::new())
39 }
40
41 fn name(&self) -> &str {
42 "None"
43 }
44}
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49 use bytes::Bytes;
50 use rusmes_proto::{HeaderMap, MessageBody, MimeMessage};
51
52 #[tokio::test]
53 async fn test_all_matcher() {
54 let recipients = vec![
55 "user1@example.com".parse().unwrap(),
56 "user2@example.com".parse().unwrap(),
57 ];
58 let message = MimeMessage::new(HeaderMap::new(), MessageBody::Small(Bytes::from("Test")));
59 let mail = Mail::new(None, recipients.clone(), message, None, None);
60
61 let matcher = AllMatcher;
62 let matched = matcher.match_mail(&mail).await.unwrap();
63 assert_eq!(matched.len(), 2);
64 }
65
66 #[tokio::test]
67 async fn test_none_matcher() {
68 let recipients = vec!["user@example.com".parse().unwrap()];
69 let message = MimeMessage::new(HeaderMap::new(), MessageBody::Small(Bytes::from("Test")));
70 let mail = Mail::new(None, recipients, message, None, None);
71
72 let matcher = NoneMatcher;
73 let matched = matcher.match_mail(&mail).await.unwrap();
74 assert_eq!(matched.len(), 0);
75 }
76}