1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
+
+
+
-
-
-
-
+
+
+
+
-
-
+
-
+
-
-
-
-
-
-
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
|
use smtp2tg::mail::MailServer;
use config::FileFormat::Toml;
use stacked_errors::{
Result,
StackableErr,
ensure,
ensure_eq,
};
use tgbot::types::ChatPeerId;
/// Builds a `MailServer` purely from an in-memory TOML source, no
/// network access is performed while constructing it.
fn build_server () -> Result<MailServer> {
let settings = config::Config::builder()
#[test]
fn get_id_properly_resolves_addresses () -> Result<()> {
let server = MailServer::new(config::Config::builder()
.add_source(config::File::from_str(r#"
api_key = "test-api-key"
api_gateway = "https://api.telegram.org"
default = 0
unknown = "relay"
fields = ["date", "from", "subject"]
domains = ["example.com"]
[recipients]
"someone@example.com" = 1
"root" = -1
"#, config::FileFormat::Toml))
"#, Toml))
.build()
.stack()?;
.stack()?)?;
MailServer::new(settings)
}
#[test]
fn get_id_returns_configured_recipient () -> Result<()> {
let server = build_server()?;
let cases = [
("someone@example.com", 1),
("someone", 0),
("root", -1),
("unknown@example.com", 0),
("SOMEONE@example.com", 1), // uppercase local part
("someone@EXAMPLE.COM", 1), // uppercase domain
("some.one@example.com", 0), // dot are not skipped
("some-one-2", 0), // Hyphens
];
for (email, id) in cases {
assert_eq!(*server.get_id(email)?, ChatPeerId::from(id), "email [{email}] expected to return id [{id}]");
ensure_eq!(*server.get_id(email)?, ChatPeerId::from(id), format!("email [{email}] expected to return id [{id}]"));
}
let cases = [
"someone@otherdomain.net",
"@example.com", // empty local part
"some@one@example.com", // more than one '@'
"someone@example.com.evil",
"someone@example.org",
];
for email in cases {
ensure!(server.get_id(email).is_err(), format!("this email should be rejected: {email}"));
}
Ok(())
}
#[test]
fn wrong_server_config () -> Result<()> {
let configs = [
"domains = []",
"",
"[recipents]\na = 1",
r#"
api_key = "test-api-key"
api_gateway = "https://api.telegram.org"
default = 0
fields = ["date", "from", "subject"]
domains = ["example.com"]
# no recipients
"#,
r#"
ap_key = "test-api-key" # bad one
api_gateway = "https://api.telegram.org"
default = 0
fields = ["date", "from", "subject"]
domains = ["example.com"]
[recipients]
"someone@example.com" = 1
"root" = -1"#,
r#"
api_key = "test-api-key"
api_gateway = "https://api.telegram.org"
default = 0
fields = ["date", "from", "subject"]
domains = [] # empty
[recipients]
"someone@example.com" = 1
"root" = -1"#,
];
for config in configs {
let settings = config::Config::builder()
.add_source(config::File::from_str(config, Toml))
.build()
.stack()?;
ensure!(MailServer::new(settings).is_err(), format!("this config shouldn't be valid:\n{config}"));
}
Ok(())
}
|