Diff
Logged in as anonymous

Differences From Artifact [478a14c8ba]:

To Artifact [1c18fc67bc]:


55
56
57
58
59
60
61

62
63
64
65
66
67
68
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69







+







#[derive(Clone, Debug)]
pub struct MailServer {
	data: Vec<u8>,
	headers: Option<SomeHeaders>,
	tg: Arc<TelegramTransport>,
	fields: HashSet<String>,
	address: Regex,
	domains: HashSet<String>,
}

impl MailServer {
	/// Initializes the mail server: sets up the Telegram API client and
	/// validates all required configuration values.
	///
	/// # Arguments
91
92
93
94
95
96
97


98
99


100
101
102
103
104

105
106

107
108
109
110
111
112
113
114

115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132


133
134
135
136
137
138
139
140
92
93
94
95
96
97
98
99
100


101
102

103
104
105

106
107

108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133


134
135

136
137
138
139
140
141
142







+
+
-
-
+
+
-



-
+

-
+








+
















-
-
+
+
-







		let mut domains: HashSet<String> = HashSet::new();
		let extra_domains = settings.get_array("domains").stack()?;
		for domain in extra_domains {
			let domain = domain.to_string().to_lowercase();
			if RE_DOMAIN.is_match(&domain) {
				domains.insert(domain);
			} else {
				bail!("Invalid domain in configuration: '{domain}'\n\
					Domains must be valid (e.g., 'example.com', 'localhost').\n\
				bail!("[smtp2tg.toml] can't check domains in \"domains\": {domain}");
			}
					Check 'domains' array in smtp2tg.toml.");
		}	}
		}
		if domains.is_empty() {
			bail!("No domains, need at least one: default `localhost` would do.");
		}
		let domains = domains.into_iter().map(|s| escape(&s))
		let re_domains = domains.iter().map(|s| escape(s))
			.collect::<Vec<String>>().join("|");
		let address = RegexBuilder::new(&format!("^[a-z0-9][a-z0-9.-]*(@({domains}))?$"))
		let address = RegexBuilder::new(&format!("^[a-z0-9][a-z0-9.-]*(@({re_domains}))?$"))
			.case_insensitive(true).build().stack()?;

		Ok(MailServer {
			data: vec!(),
			headers: None,
			tg,
			fields,
			address,
			domains,
		})
	}

	/// Retrieves the Telegram chat ID for a given email address, checks that
	/// used domain is allowed.
	///
	/// # Arguments
	/// * `name` - Email address or username to look up.
	///
	/// # Returns
	/// * `Result<ChatPeerId>` - Telegram chat ID for the address, or default if
	///   not found.
	pub fn get_id (&self, name: &str) -> Result<&ChatPeerId> {
		if self.address.is_match(name) {
			Ok(self.tg.get(name).unwrap_or(&self.tg.default))
		} else {
			bail!("Doesn't look like address from one of our domains.");
		}
			bail!("Email address {name:?} is not from an allowed domain.");
	}	}
	}

	/// Attempt to deliver one message
	async fn relay_mail (&self) -> Result<()> {
		if let Some(headers) = &self.headers {
			let mail = mail_parser::MessageParser::new().parse(&self.data)
				.context("Failed to parse mail.")?;