From 4b5576cab491222d436ae125778c2180b3e404d1 Mon Sep 17 00:00:00 2001 From: mdecimus Date: Sun, 14 Jan 2024 10:53:41 +0100 Subject: [PATCH] v0.5.3 --- CHANGELOG.md | 18 ++++++++++++++++++ Cargo.lock | 18 +++++++++--------- README.md | 1 + UPGRADING.md | 16 ++++++++++++++++ crates/cli/Cargo.toml | 2 +- crates/imap/Cargo.toml | 2 +- crates/install/Cargo.toml | 2 +- crates/jmap/Cargo.toml | 2 +- crates/main/Cargo.toml | 2 +- crates/main/src/main.rs | 2 -- crates/managesieve/Cargo.toml | 2 +- crates/nlp/Cargo.toml | 2 +- crates/smtp/Cargo.toml | 2 +- crates/utils/Cargo.toml | 2 +- resources/config.zip | Bin 171446 -> 171400 bytes 15 files changed, 53 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89713dbf..61362e9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,24 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [0.5.3] - 2024-01-14 + +Please read the [UPGRADING.md](UPGRADING.md) file for more information on how to upgrade from previous versions. + +## Added +- Built-in [fail2ban](https://stalw.art/docs/server/fail2ban) and IP address/mask blocking (#164). +- CLI: Read URL and credentials from environment variables (#88). +- mySQL driver: Add `max-allowed-packet` setting (#201). + +### Changed +- Unified storage settings for all services (read the [UPGRADING.md](UPGRADING.md) for details) + +### Fixed +- IMAP retrieval of auto-encrypted emails (#203). +- mySQL driver: Parse `timeout.wait` property as duration (#202). +- `X-Forwarded-For` header on JMAP Rate-Limit does not work (#208). +- Use timeouts in install script (#138). + ## [0.5.2] - 2024-01-07 Please read the [UPGRADING.md](UPGRADING.md) file for more information on how to upgrade from previous versions. diff --git a/Cargo.lock b/Cargo.lock index 9871da99..c8ee2794 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2551,7 +2551,7 @@ checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284" [[package]] name = "imap" -version = "0.5.2" +version = "0.5.3" dependencies = [ "ahash 0.8.7", "dashmap", @@ -2728,7 +2728,7 @@ dependencies = [ [[package]] name = "jmap" -version = "0.5.2" +version = "0.5.3" dependencies = [ "aes", "aes-gcm", @@ -3138,7 +3138,7 @@ dependencies = [ [[package]] name = "mail-server" -version = "0.5.2" +version = "0.5.3" dependencies = [ "directory", "imap", @@ -3155,7 +3155,7 @@ dependencies = [ [[package]] name = "managesieve" -version = "0.5.2" +version = "0.5.3" dependencies = [ "ahash 0.8.7", "bincode", @@ -3422,7 +3422,7 @@ dependencies = [ [[package]] name = "nlp" -version = "0.5.2" +version = "0.5.3" dependencies = [ "ahash 0.8.7", "bincode", @@ -5385,7 +5385,7 @@ checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "smtp" -version = "0.5.2" +version = "0.5.3" dependencies = [ "ahash 0.8.7", "bincode", @@ -5507,7 +5507,7 @@ dependencies = [ [[package]] name = "stalwart-cli" -version = "0.5.2" +version = "0.5.3" dependencies = [ "clap", "console", @@ -5531,7 +5531,7 @@ dependencies = [ [[package]] name = "stalwart-install" -version = "0.5.2" +version = "0.5.3" dependencies = [ "base64 0.21.5", "clap", @@ -6414,7 +6414,7 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "utils" -version = "0.5.2" +version = "0.5.3" dependencies = [ "ahash 0.8.7", "arc-swap", diff --git a/README.md b/README.md index 838b3d2a..207957f5 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,7 @@ Key features: - Encryption at rest with **S/MIME** or **OpenPGP**. - Automatic TLS certificate provisioning with [ACME](https://datatracker.ietf.org/doc/html/rfc8555). - OAuth 2.0 [authorization code](https://www.rfc-editor.org/rfc/rfc8628) and [device authorization](https://www.rfc-editor.org/rfc/rfc8628) flows. + - Automated blocking of hosts that cause multiple authentication errors (aka **fail2ban**). - Access Control Lists (ACLs). - Rate limiting. - Security audited (read the [report](https://stalw.art/blog/security-audit)). diff --git a/UPGRADING.md b/UPGRADING.md index 1deecdc3..270d50c6 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -1,3 +1,19 @@ +Upgrading from `v0.5.2` to `v0.5.3` +----------------------------------- + +- The following configuration attributes have been renamed, see [store.toml](https://github.com/stalwartlabs/mail-server/blob/main/resources/config/common/store.toml) for an example: + - `jmap.store.data` -> `storage.data` + - `jmap.store.fts` -> `storage.fts` + - `jmap.store.blob` -> `storage.blob` + - `jmap.encryption.*` -> `storage.encryption.*` + - `jmap.spam.header` -> `storage.spam.header` + - `jmap.fts.default-language` -> `storage.fts.default-language` + - `jmap.cluster.node-id` -> `storage.cluster.node-id` + - `management.directory` and `sieve.trusted.default.directory` -> `storage.directory` + - `sieve.trusted.default.store` -> `storage.lookup` +- Proxy networks are now configured under `server.proxy.trusted-networks` rather than `server.proxy-trusted-networks`. IP addresses/masks have to be defined within a set (`{}`) rather than a list (`[]`), see [server.toml](https://github.com/stalwartlabs/mail-server/blob/main/resources/config/common/server.toml) for an example. + + Upgrading from `v0.5.1` to `v0.5.2` ----------------------------------- diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 581ad8ad..eb56d6c3 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Stalwart Labs Ltd. "] license = "AGPL-3.0-only" repository = "https://github.com/stalwartlabs/cli" homepage = "https://github.com/stalwartlabs/cli" -version = "0.5.2" +version = "0.5.3" edition = "2021" readme = "README.md" resolver = "2" diff --git a/crates/imap/Cargo.toml b/crates/imap/Cargo.toml index 93c81abe..09126e08 100644 --- a/crates/imap/Cargo.toml +++ b/crates/imap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "imap" -version = "0.5.2" +version = "0.5.3" edition = "2021" resolver = "2" diff --git a/crates/install/Cargo.toml b/crates/install/Cargo.toml index 3de253bb..6462149f 100644 --- a/crates/install/Cargo.toml +++ b/crates/install/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Stalwart Labs Ltd. "] license = "AGPL-3.0-only" repository = "https://github.com/stalwartlabs/mail-server" homepage = "https://github.com/stalwartlabs/mail-server" -version = "0.5.2" +version = "0.5.3" edition = "2021" readme = "README.md" resolver = "2" diff --git a/crates/jmap/Cargo.toml b/crates/jmap/Cargo.toml index f545dd5a..27f6766a 100644 --- a/crates/jmap/Cargo.toml +++ b/crates/jmap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "jmap" -version = "0.5.2" +version = "0.5.3" edition = "2021" resolver = "2" diff --git a/crates/main/Cargo.toml b/crates/main/Cargo.toml index ed369e3d..9d67d5ed 100644 --- a/crates/main/Cargo.toml +++ b/crates/main/Cargo.toml @@ -7,7 +7,7 @@ homepage = "https://stalw.art" keywords = ["imap", "jmap", "smtp", "email", "mail", "server"] categories = ["email"] license = "AGPL-3.0-only" -version = "0.5.2" +version = "0.5.3" edition = "2021" resolver = "2" diff --git a/crates/main/src/main.rs b/crates/main/src/main.rs index 7e0ccebd..b69834b6 100644 --- a/crates/main/src/main.rs +++ b/crates/main/src/main.rs @@ -73,8 +73,6 @@ async fn main() -> std::io::Result<()> { .reload(&config) .failed("Invalid configuration"); - let todo = "Update config.zip"; - // Parse directories let directory = config .parse_directory(&stores, &servers, data_store) diff --git a/crates/managesieve/Cargo.toml b/crates/managesieve/Cargo.toml index cbdaf1ca..eae37824 100644 --- a/crates/managesieve/Cargo.toml +++ b/crates/managesieve/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "managesieve" -version = "0.5.2" +version = "0.5.3" edition = "2021" resolver = "2" diff --git a/crates/nlp/Cargo.toml b/crates/nlp/Cargo.toml index c1250a8e..530a919f 100644 --- a/crates/nlp/Cargo.toml +++ b/crates/nlp/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nlp" -version = "0.5.2" +version = "0.5.3" edition = "2021" resolver = "2" diff --git a/crates/smtp/Cargo.toml b/crates/smtp/Cargo.toml index 668c7817..2e689b8c 100644 --- a/crates/smtp/Cargo.toml +++ b/crates/smtp/Cargo.toml @@ -7,7 +7,7 @@ homepage = "https://stalw.art/smtp" keywords = ["smtp", "email", "mail", "server"] categories = ["email"] license = "AGPL-3.0-only" -version = "0.5.2" +version = "0.5.3" edition = "2021" resolver = "2" diff --git a/crates/utils/Cargo.toml b/crates/utils/Cargo.toml index b83fee19..e8e6f0e9 100644 --- a/crates/utils/Cargo.toml +++ b/crates/utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "utils" -version = "0.5.2" +version = "0.5.3" edition = "2021" resolver = "2" diff --git a/resources/config.zip b/resources/config.zip index a53e77eac2a98c01e6046e9f878188793f3e06cf..a79ac6fbef7cd08b8e9cca2161ca24660db3dbb0 100644 GIT binary patch delta 4604 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 delta 4381 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