diff --git a/CHANGELOG.md b/CHANGELOG.md index e1e64988..fbb223b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). -## [0.16.13] - 2026-07-XX +## [0.16.13] - 2026-07-12 If you are upgrading from v0.16.x, replace the binary (or run `docker pull`). If you are upgrading from v0.15.x and below, please read the [upgrading documentation](https://github.com/stalwartlabs/stalwart/blob/main/UPGRADING/v0_16.md) for more information on how to upgrade from previous versions. @@ -18,7 +18,9 @@ If you are upgrading from v0.16.x, replace the binary (or run `docker pull`). If - VacationResponse: `isEnabled` reset to false whenever properties are changed. - Capabilities: Return RFC-3339-conformant UTCDate literals in capabilities: min `0001-01-01T00:00:00Z`, max `9999-12-31T23:59:59Z`. - Directory: Update local groups only when the external directory includes a group attribute. -- DNS Management: CAA management deletes too third-party CAA entries. +- DNS Management: + - CAA management deletes too third-party CAA entries. + - Multiple provider fixes (see `dns-update` crate changelog). - Reject invalid duration values (e.g. `1h30m`). - Branding: Custom logos for domains do not work. - Sieve: add `Received` headers to auto-generated messages and detect loops. diff --git a/Cargo.lock b/Cargo.lock index 3fdd4cee..5e6479e4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2124,9 +2124,9 @@ dependencies = [ [[package]] name = "dns-update" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8114773ce0ea3c3443cfb63025aa02fcddddf5f2b3d090e822e10dbf0572c2" +checksum = "0c07b2767be6aead1916e05cc9a655c7d34737eb071cda3f05f67031b29891c8" dependencies = [ "aws-lc-rs", "base64 0.22.1", @@ -4386,9 +4386,9 @@ dependencies = [ [[package]] name = "mail-auth" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a88908ddf3a07fa2e76873f84d28476d3c802173fee0a44f6c5e5472523e6986" +checksum = "5dc03ec0f6be1788623ee3d275940ca0053ced3154eb881ffe70edf2f43d3d41" dependencies = [ "aws-lc-rs", "flate2", @@ -7706,9 +7706,9 @@ dependencies = [ [[package]] name = "smtp-proto" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97c9f5dd7ec5cc6d743f33fcb96de4eb91bb1cc51c5e0ba40cb285a9012043da" +checksum = "4570e312141d42f0cb8d4e532fc8ec96c805b308fcb9012d973558cccd9dee85" dependencies = [ "rkyv", "serde", diff --git a/crates/common/src/network/dns/update.rs b/crates/common/src/network/dns/update.rs index 79cd6743..394ba85f 100644 --- a/crates/common/src/network/dns/update.rs +++ b/crates/common/src/network/dns/update.rs @@ -217,6 +217,7 @@ impl DnsUpdater { region: Some(server.region), hosted_zone_id: server.hosted_zone_id, private_zone_only: Some(server.private_zone_only), + endpoint: None, }; Ok(DnsUpdater { polling_interval: server.polling_interval.into_inner(), diff --git a/crates/http/src/auth/oauth/auth.rs b/crates/http/src/auth/oauth/auth.rs index 11d1616c..8d482d6e 100644 --- a/crates/http/src/auth/oauth/auth.rs +++ b/crates/http/src/auth/oauth/auth.rs @@ -632,8 +632,8 @@ fn is_known_resource<'x>(hostnames: impl IntoIterator, uri: &str let authority = rest.split_once('/').map_or(rest, |(auth, _)| auth); let host = authority .rsplit_once(':') - .filter(|(h, _)| h.as_bytes().iter().all(|c| c.is_ascii_digit())) - .map_or(authority, |(h, _)| h); + .filter(|(_, port)| !port.is_empty() && port.as_bytes().iter().all(|c| c.is_ascii_digit())) + .map_or(authority, |(host, _)| host); supported && hostnames diff --git a/tests/src/imap/pop.rs b/tests/src/imap/pop.rs index be1904ae..854b2762 100644 --- a/tests/src/imap/pop.rs +++ b/tests/src/imap/pop.rs @@ -73,7 +73,7 @@ pub async fn test(test: &TestServer) { pop3.send("STAT").await; pop3.assert_read(ResponseType::Ok) .await - .assert_contains("+OK 3 603"); + .assert_contains("+OK 3 609"); // UTF8 pop3.send("UTF8").await; @@ -84,13 +84,13 @@ pub async fn test(test: &TestServer) { pop3.assert_read(ResponseType::Multiline) .await .assert_contains("+OK 3 messages") - .assert_contains("1 201") - .assert_contains("2 201") - .assert_contains("3 201"); + .assert_contains("1 203") + .assert_contains("2 203") + .assert_contains("3 203"); pop3.send("LIST 2").await; pop3.assert_read(ResponseType::Ok) .await - .assert_contains("+OK 2 201"); + .assert_contains("+OK 2 203"); // UIDL pop3.send("UIDL").await; @@ -109,13 +109,13 @@ pub async fn test(test: &TestServer) { pop3.send("RETR 1").await; pop3.assert_read(ResponseType::Multiline) .await - .assert_contains("+OK 201 octets") + .assert_contains("+OK 203 octets") .assert_contains("I'm going to need those TPS 0 reports ASAP.") .assert_contains("So, if you could do that, that'd be great."); pop3.send("RETR 3").await; pop3.assert_read(ResponseType::Multiline) .await - .assert_contains("+OK 201 octets") + .assert_contains("+OK 203 octets") .assert_contains("I'm going to need those TPS 2 reports ASAP.") .assert_contains("So, if you could do that, that'd be great."); pop3.send("RETR 4").await; @@ -125,13 +125,13 @@ pub async fn test(test: &TestServer) { pop3.send("TOP 1 4").await; pop3.assert_read(ResponseType::Multiline) .await - .assert_contains("+OK 201 octets") + .assert_contains("+OK 203 octets") .assert_contains("Subject: TPS Report 0") .assert_not_contains("I'm going to need those TPS 0 reports ASAP."); pop3.send("TOP 3 4").await; pop3.assert_read(ResponseType::Multiline) .await - .assert_contains("+OK 201 octets") + .assert_contains("+OK 203 octets") .assert_contains("Subject: TPS Report 2") .assert_not_contains("I'm going to need those TPS 2 reports ASAP."); @@ -148,7 +148,7 @@ pub async fn test(test: &TestServer) { pop3.send("STAT").await; pop3.assert_read(ResponseType::Ok) .await - .assert_contains("+OK 3 603"); + .assert_contains("+OK 3 609"); // DELE + QUIT (should delete messages) pop3.send("DELE 2").await; @@ -160,7 +160,7 @@ pub async fn test(test: &TestServer) { pop3.send("STAT").await; pop3.assert_read(ResponseType::Ok) .await - .assert_contains("+OK 2 402"); + .assert_contains("+OK 2 406"); pop3.send("TOP 1 4").await; pop3.assert_read(ResponseType::Multiline) .await diff --git a/tests/src/smtp/inbound/data.rs b/tests/src/smtp/inbound/data.rs index ca008a62..ba53a425 100644 --- a/tests/src/smtp/inbound/data.rs +++ b/tests/src/smtp/inbound/data.rs @@ -218,7 +218,7 @@ async fn data() { .await; assert_eq!( test.expect_message().await.read_message(&test).await, - load_test_message("no_msgid", "messages") + format!("{}\r\n", load_test_message("no_msgid", "messages")) ); // Maximum one message per session is allowed for 10.0.0.1 diff --git a/tests/src/system/oidc.rs b/tests/src/system/oidc.rs index a8caf925..41d783da 100644 --- a/tests/src/system/oidc.rs +++ b/tests/src/system/oidc.rs @@ -359,7 +359,7 @@ pub async fn test(test: &mut TestServer) { code_challenge: Some(PKCE_CHALLENGE.to_string()), code_challenge_method: Some("S256".to_string()), state: None, - resource: vec!["https://127.0.0.1:8899/jmap/session".to_string()], + resource: vec!["https://mail.example.org/jmap/session".to_string()], }, ) .await diff --git a/tests/src/system/quota.rs b/tests/src/system/quota.rs index ef003294..13ee6f69 100644 --- a/tests/src/system/quota.rs +++ b/tests/src/system/quota.rs @@ -448,7 +448,7 @@ pub async fn test(test: &mut TestServer) { "jane@example.org", "user1@example.org", &format!("Ingest test {i}"), - 513, + 500, )) .unwrap(), )