Check-in [ec55d3e69e]
Logged in as anonymous
Overview
Comment:bumps, global permissions for workflow, docs
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: ec55d3e69ea86301053f33d9024093d5319ed80407cc1594b9f03cc5161f22f2
User & Date: arcade on 2026-10-28 17:13:38.992
Other Links: manifest | tags
Context
2026-10-28
17:22
simplify check-in: 42ac4c7a9a user: arcade tags: trunk
17:13
bumps, global permissions for workflow, docs check-in: ec55d3e69e user: arcade tags: trunk
2026-10-25
19:48
bump, new mail-parser, force LocalExecutor check-in: 1984831c3f user: arcade tags: trunk
Changes
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
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






+
+
+










-
-







name: rust-ci
on:
  push:
    branches: [ master, release ]
  pull_request:

permissions:
  contents: read

# sccache enable for rust/C builds
env:
  SCCACHE_GHA_ENABLED: "true"
  RUSTC_WRAPPER: "sccache"

jobs:
  rust-ci-run:
    name: Run rust-clippy analyzing and tests
    runs-on: ubuntu-latest
    if: github.event_name == 'push' || (github.head_ref != 'master' && github.head_ref != 'release')
    permissions:
      contents: read
    steps:
      # SETUP
      - uses: actions/checkout@v7
        with:
          persist-credentials: false
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
︙
︙
225
226
227
228
229
230
231
232

233
234

235
236
237
238
239
240
241
242

243
244

245
246
247
248
249
250
251
225
226
227
228
229
230
231

232
233

234
235
236
237
238
239
240
241

242
243

244
245
246
247
248
249
250
251







-
+

-
+







-
+

-
+







name = "autocfg"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"

[[package]]
name = "aws-lc-rs"
version = "1.18.2"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "faac5829c2b74c28f830747e7818ccfb684261b5f48a1118b1e2a13d36dfab13"
checksum = "048006790404103c488e6c5616b3e7e702a71292aadda08e8f7698a9e0d2eb53"
dependencies = [
 "aws-lc-sys",
 "zeroize",
]

[[package]]
name = "aws-lc-sys"
version = "0.46.0"
version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1622d8446a2d4b2ce0c7eefc73dd43a99779028d5ee5c2dd8073a658ba8a2bc"
checksum = "8bfbe32ac36b3c428696ce315464181bc4029d689fd58e3f2a4e58c252242f52"
dependencies = [
 "cc",
 "cmake",
 "dunce",
 "fs_extra",
 "pkg-config",
]
︙
1197
1198
1199
1200
1201
1202
1203
1204

1205
1206

1207
1208
1209
1210
1211
1212
1213
1197
1198
1199
1200
1201
1202
1203

1204
1205

1206
1207
1208
1209
1210
1211
1212
1213







-
+

-
+







name = "once_cell_polyfill"
version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"

[[package]]
name = "openssl-probe"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe"
checksum = "7e036b411754132fd6b74e94b74e9a13c5cf606fa93d1885c35860d3060820b1"

[[package]]
name = "owo-colors"
version = "4.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c45bb4a6ae1280ec0803b1ef9d3455eb50f01efbbe1447ab020f1d54fba9d8"

︙
1479
1480
1481
1482
1483
1484
1485
1486

1487
1488

1489
1490
1491
1492
1493
1494
1495
1479
1480
1481
1482
1483
1484
1485

1486
1487

1488
1489
1490
1491
1492
1493
1494
1495







-
+

-
+







checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
dependencies = [
 "semver",
]

[[package]]
name = "rustix"
version = "1.1.5"
version = "1.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "891efababe418670775f199f0d233d84843c227a0949a883ce15b37c78d6629d"
checksum = "e5e76742e5294153d4dde1207dbec5bdd81eef6fabdc0d2118babadabfd858aa"
dependencies = [
 "bitflags",
 "errno",
 "libc",
 "linux-raw-sys",
 "windows-sys 0.61.2",
]
︙
︙
65
66
67
68
69
70
71
72


73
74
75
76
77
78
79
65
66
67
68
69
70
71

72
73
74
75
76
77
78
79
80







-
+
+







	/// 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.
	/// Returns an error if required configuration values are missing or invalid,
	/// Telegram API client creation fails, or the address regex cannot be built.
	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")
			.context("[smtp2tg.toml] missing table \"recipients\".\n")?
		{
︙
127
128
129
130
131
132
133







134






135
136
137
138
139
140
141
128
129
130
131
132
133
134
135
136
137
138
139
140
141

142
143
144
145
146
147
148
149
150
151
152
153
154







+
+
+
+
+
+
+
-
+
+
+
+
+
+







	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!("Email address {name:?} is not from an allowed domain.");
	}	}

	/// Forwards the buffered email to each distinct destination chat, using the
	/// default chat for allowed addresses without a configured recipient.
	///
	/// Inlines the first plain-text body if the escaped message is below 4096
	/// bytes. Sends remaining text parts and decoded attachments as documents;
	/// HTML body parts are omitted. Leaves the buffered data and envelope intact.
	///
	/// Attempt to deliver one message
	/// # Errors
	/// Returns an error for a missing envelope, no recipients, a disallowed
	/// address, mail parsing or part extraction failures, or rejected closing
	/// `pre`/`code` tags in text passed to validation. Propagates media-group
	/// construction and Telegram request errors, including diagnostic sends.
	/// Delivery to earlier chats is not rolled back if a later send fails.
	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.")?;

			// Adding all known addresses to recipient list, for anyone else adding default
			// Also if list is empty also adding default
︙
︙
40
41
42
43
44
45
46


47
48
49
50
51
52
53
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55







+
+







///
/// The configuration file must use owner-only permissions. Once configured,
/// the SMTP server runs until it stops or encounters an error.
///
/// # Errors
/// Returns an error if the configuration file is missing, inaccessible,
/// insecure, malformed, or contains invalid required settings.
/// Also returns an error if the system hostname cannot be read or is not
/// valid UTF-8, or if mail server initialisation fails.
///
/// # Panics
/// Panics if configuring or serving the SMTP server fails.
	async fn main (ex: &LocalExecutor<'_>) -> Result<()> {
		let args = Args::parse();
		let config_file = Path::new(&args.config);
		if !config_file.try_exists().stack()? {
︙