58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
relay: bool,
tg: Arc<TelegramTransport>,
fields: HashSet<String>,
address: Regex,
}
impl MailServer {
/// Main asynchronous entry point for the application.
///
/// Parses command-line arguments, loads configuration, and starts the SMTP
/// server.
///
/// # Errors
/// Returns an error if configuration is invalid, files are inaccessible, or
/// server fails to start.
pub fn new(settings: config::Config) -> Result<MailServer> {
let api_key = settings.get_string("api_key")
.context("[smtp2tg.toml] missing \"api_key\" parameter.\n")?;
let mut recipients = HashMap::new();
for (name, value) in settings.get_table("recipients")
.expect("[smtp2tg.toml] missing table \"recipients\".\n")
{
let value = value.into_int()
|
|
>
<
|
>
|
|
|
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
relay: bool,
tg: Arc<TelegramTransport>,
fields: HashSet<String>,
address: Regex,
}
impl MailServer {
/// Initializes the mail server: sets up the Telegram API client and
/// validates all required configuration values.
///
/// # Arguments
/// * `settings` - Parsed application configuration.
///
/// # Errors
/// Returns an error if required configuration values are missing or invalid.
/// server fails to start.
pub fn new (settings: config::Config) -> Result<MailServer> {
let api_key = settings.get_string("api_key")
.context("[smtp2tg.toml] missing \"api_key\" parameter.\n")?;
let mut recipients = HashMap::new();
for (name, value) in settings.get_table("recipients")
.expect("[smtp2tg.toml] missing table \"recipients\".\n")
{
let value = value.into_int()
|
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
})
}
/// Retrieves the Telegram chat ID for a given email address, checks that
/// used domain is allowed.
///
/// # Arguments
/// * `name_str` - 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) {
match self.tg.get(name) {
Ok(addr) => Ok(addr),
Err(_) => Ok(&self.tg.default),
}
} else {
bail!("Doesn't look like address from one of our domains.");
}
}
/// Attempt to deliver one message
async fn relay_mail (&self) -> Result<()> {
|
|
|
<
<
<
|
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
})
}
/// 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.");
}
}
/// Attempt to deliver one message
async fn relay_mail (&self) -> Result<()> {
|
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
|
/// Just deny plain auth
fn auth_plain (&mut self, _authorization_id: &str, _authentication_id: &str, _password: &str) -> Response {
INVALID_CREDENTIALS
}
/// Verify whether address is deliverable
fn rcpt (&mut self, to: &str) -> Response {
if self.relay {
OK
} else {
match self.get_id(to) {
Ok(_) => OK,
Err(_) => {
if self.relay {
OK
} else {
NO_MAILBOX
}
}
}
}
}
/// Save headers we need
fn data_start (&mut self, _domain: &str, from: &str, _is8bit: bool, to: &[String]) -> Response {
self.headers = Some(SomeHeaders{
from: from.to_string(),
|
|
<
<
<
<
<
<
|
<
<
<
|
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
|
/// Just deny plain auth
fn auth_plain (&mut self, _authorization_id: &str, _authentication_id: &str, _password: &str) -> Response {
INVALID_CREDENTIALS
}
/// Verify whether address is deliverable
fn rcpt (&mut self, to: &str) -> Response {
if self.relay || self.get_id(to).is_ok() {
OK
} else {
NO_MAILBOX
}
}
/// Save headers we need
fn data_start (&mut self, _domain: &str, from: &str, _is8bit: bool, to: &[String]) -> Response {
self.headers = Some(SomeHeaders{
from: from.to_string(),
|