rusmes_core/matchers/
remote_address.rs1use crate::matcher::Matcher;
4use async_trait::async_trait;
5use rusmes_proto::{Mail, MailAddress};
6use std::net::IpAddr;
7
8pub struct RemoteAddressMatcher {
10 allowed_ips: Vec<IpAddr>,
11 allowed_cidrs: Vec<(IpAddr, u8)>,
12}
13
14impl RemoteAddressMatcher {
15 pub fn new(allowed_ips: Vec<IpAddr>, allowed_cidrs: Vec<(IpAddr, u8)>) -> Self {
17 Self {
18 allowed_ips,
19 allowed_cidrs,
20 }
21 }
22
23 fn matches_cidr(&self, addr: &IpAddr) -> bool {
25 for (cidr_addr, prefix_len) in &self.allowed_cidrs {
26 if Self::ip_in_cidr(addr, cidr_addr, *prefix_len) {
27 return true;
28 }
29 }
30 false
31 }
32
33 fn ip_in_cidr(addr: &IpAddr, cidr_addr: &IpAddr, prefix_len: u8) -> bool {
35 match (addr, cidr_addr) {
36 (IpAddr::V4(a), IpAddr::V4(c)) => {
37 let addr_bits = u32::from_be_bytes(a.octets());
38 let cidr_bits = u32::from_be_bytes(c.octets());
39 let mask = !0u32 << (32 - prefix_len);
40 (addr_bits & mask) == (cidr_bits & mask)
41 }
42 (IpAddr::V6(a), IpAddr::V6(c)) => {
43 let addr_bits = u128::from_be_bytes(a.octets());
44 let cidr_bits = u128::from_be_bytes(c.octets());
45 let mask = !0u128 << (128 - prefix_len);
46 (addr_bits & mask) == (cidr_bits & mask)
47 }
48 _ => false,
49 }
50 }
51}
52
53#[async_trait]
54impl Matcher for RemoteAddressMatcher {
55 async fn match_mail(&self, mail: &Mail) -> anyhow::Result<Vec<MailAddress>> {
56 if let Some(remote_addr) = mail.remote_addr() {
57 if self.allowed_ips.contains(remote_addr) || self.matches_cidr(remote_addr) {
58 return Ok(mail.recipients().to_vec());
59 }
60 }
61 Ok(Vec::new())
62 }
63
64 fn name(&self) -> &str {
65 "RemoteAddress"
66 }
67}