also looking at this
feat(config): add hosted_domains for multi-domain hosting
#1
7 files
+153
-42
| @@ -268,3 +268,73 @@ test "authentication configuration flags" { | ||
| 268 | 268 | |
| 269 | 269 | try testing.expectEqual(false, cfg_auth_off.enable_auth); |
| 270 | 270 | } |
| 271 | ||
| 272 | fn baseCfg(hostname: []const u8, hosted: []const []const u8) config.Config { | |
| 273 | return .{ | |
| 274 | .host = "0.0.0.0", | |
| 275 | .port = 2525, | |
| 276 | .max_connections = 100, | |
| 277 | .enable_tls = false, | |
| 278 | .tls_cert_path = null, | |
| 279 | .tls_key_path = null, | |
| 280 | .enable_auth = true, | |
| 281 | .max_message_size = 10 * 1024 * 1024, | |
| 282 | .timeout_seconds = 300, | |
| 283 | .data_timeout_seconds = 600, | |
| 284 | .command_timeout_seconds = 300, | |
| 285 | .greeting_timeout_seconds = 30, | |
| 286 | .rate_limit_per_ip = 100, | |
| 287 | .rate_limit_per_user = 200, | |
| 288 | .rate_limit_cleanup_interval = 3600, | |
| 289 | .max_recipients = 100, | |
| 290 | .hostname = hostname, | |
| 291 | .hosted_domains = hosted, | |
| 292 | .webhook_url = null, | |
| 293 | .webhook_enabled = false, | |
| 294 | .enable_dnsbl = false, | |
| 295 | .enable_greylist = false, | |
| 296 | .enable_tracing = false, | |
| 297 | .tracing_service_name = "mail", | |
| 298 | .enable_json_logging = false, | |
| 299 | }; | |
| 300 | } | |
| 301 | ||
| 302 | test "isLocalDomain matches hostname exactly" { | |
| 303 | const cfg = baseCfg("mail.stacksjs.com", &.{}); | |
| 304 | try testing.expect(cfg.isLocalDomain("mail.stacksjs.com")); | |
| 305 | } | |
| 306 | ||
| 307 | test "isLocalDomain matches parent of hostname" { | |
| 308 | const cfg = baseCfg("mail.stacksjs.com", &.{}); | |
| 309 | try testing.expect(cfg.isLocalDomain("stacksjs.com")); | |
| 310 | } | |
| 311 | ||
| 312 | test "isLocalDomain matches an entry in hosted_domains" { | |
| 313 | const extras = [_][]const u8{ "paweldregan.com", "example.org" }; | |
| 314 | const cfg = baseCfg("mail.stacksjs.com", &extras); | |
| 315 | try testing.expect(cfg.isLocalDomain("paweldregan.com")); | |
| 316 | try testing.expect(cfg.isLocalDomain("example.org")); | |
| 317 | } | |
| 318 | ||
| 319 | test "isLocalDomain is case-insensitive" { | |
| 320 | const extras = [_][]const u8{"paweldregan.com"}; | |
| 321 | const cfg = baseCfg("mail.stacksjs.com", &extras); | |
| 322 | try testing.expect(cfg.isLocalDomain("MAIL.Stacksjs.COM")); | |
| 323 | try testing.expect(cfg.isLocalDomain("StacksJS.COM")); | |
| 324 | try testing.expect(cfg.isLocalDomain("PaWeLdReGaN.com")); | |
| 325 | } | |
| 326 | ||
| 327 | test "isLocalDomain rejects unrelated domains" { | |
| 328 | const extras = [_][]const u8{"paweldregan.com"}; | |
| 329 | const cfg = baseCfg("mail.stacksjs.com", &extras); | |
| 330 | try testing.expect(!cfg.isLocalDomain("evil.example")); | |
| 331 | try testing.expect(!cfg.isLocalDomain("notstacksjs.com")); | |
| 332 | try testing.expect(!cfg.isLocalDomain("")); | |
| 333 | } | |
| 334 | ||
| 335 | test "isLocalDomain has no parent for single-label hostname" { | |
| 336 | // "localhost" has no '.' so there's no parent to match | |
| 337 | const cfg = baseCfg("localhost", &.{}); | |
| 338 | try testing.expect(cfg.isLocalDomain("localhost")); | |
| 339 | try testing.expect(!cfg.isLocalDomain("host")); | |
| 340 | } | |