diff --git a/CHANGELOG.md b/CHANGELOG.md index 164bee07..0a4ecc96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,29 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [0.12.5] - 2025-06-25 + +If you are upgrading from v0.11.x, this version includes **breaking changes** to the database layout and requires a migration. Please read the [UPGRADING.md](https://github.com/stalwartlabs/stalwart/blob/main/UPGRADING.md) file for more information on how to upgrade from previous versions. + +## Added +- Calendar Scheduling Extensions to CalDAV - RFC6368 (#1514) +- Calendar E-Mail Notifications (#1514) +- Limited i18n support for calendaring events. +- Assisted CalDAV/CardDAV shared resource discovery (#1691). + +## Changed +- JMAP: Allow unauthenticated access to JMAP session object. + +## Fixed +- WebDAV: Return NOTFOUND error instead of MULTISTATUS on empty PROPFIND responses (#1657). +- WebDAV: Update account name when refreshing DAV caches (#1694). +- JMAP: Do not include email address in identity names (#1688). +- IMAP: Normalize `INBOX` name when creating/renaming folders (#1636). +- LDAP: Request `secret-changed` attribute in LDAP queries (#1409). +- Branding: Unable to change logos (#1652). +- Antispam: Skip `card-is-ham` override when sender does not pass DMARC (#1648). +- FoundationDB: Renew old/expired FDB read transactions after the `1007` error code is received rather than estimating expiration time. + ## [0.12.4] - 2025-06-03 If you are upgrading from v0.11.x, this version includes **breaking changes** to the database layout and requires a migration. Please read the [UPGRADING.md](https://github.com/stalwartlabs/stalwart/blob/main/UPGRADING.md) file for more information on how to upgrade from previous versions. diff --git a/README.md b/README.md index 55ff0f3b..f107ce74 100644 --- a/README.md +++ b/README.md @@ -53,9 +53,10 @@ Key features: * Distributed virtual queues with delayed delivery, priority delivery, quotas, routing rules and throttling support. * Envelope rewriting and message modification. - **Collaboration** server: - - Calendar and scheduling with [CalDAV](https://datatracker.ietf.org/doc/html/rfc4791). - - Contact management with [CardDAV](https://datatracker.ietf.org/doc/html/rfc6352). - - File storage and sharing with [WebDAV](https://datatracker.ietf.org/doc/html/rfc4918). + - Calendaring with [CalDAV](https://datatracker.ietf.org/doc/html/rfc4791), [CalDAV Scheduling](https://datatracker.ietf.org/doc/html/rfc6638) and e-mail alarms support. + - Contact management with [CardDAV](https://datatracker.ietf.org/doc/html/rfc6352) support. + - File storage with [WebDAV](https://datatracker.ietf.org/doc/html/rfc4918) support. + - Sharing with [WebDAV ACL](https://datatracker.ietf.org/doc/html/rfc3744) support for fine-grained access control. - **Spam** and **Phishing** built-in filter: - Comprehensive set of filtering **rules** on par with popular solutions. - LLM-driven spam filtering and message analysis. diff --git a/crates/dav/src/common/propfind.rs b/crates/dav/src/common/propfind.rs index e6ace176..ed8ecc71 100644 --- a/crates/dav/src/common/propfind.rs +++ b/crates/dav/src/common/propfind.rs @@ -348,7 +348,6 @@ impl PropFindRequestHandler for Server { collection_container = parent_collection; collection_children = collection_container.child_collection().unwrap(); sync_collection = SyncCollection::from(collection_container); - response.set_namespace(collection_container.namespace()); multiget( self, @@ -371,7 +370,7 @@ impl PropFindRequestHandler for Server { collection_container = parent_collection; collection_children = collection_container.child_collection().unwrap(); sync_collection = SyncCollection::from(collection_container); - response.set_namespace(collection_container.namespace()); + items } DavQueryResource::Discovery { @@ -381,7 +380,6 @@ impl PropFindRequestHandler for Server { collection_container = parent_collection; collection_children = collection_container.child_collection().unwrap(); sync_collection = SyncCollection::from(collection_container); - response.set_namespace(collection_container.namespace()); // Add container info if !query.depth_no_root { @@ -407,6 +405,7 @@ impl PropFindRequestHandler for Server { } DavQueryResource::None => unreachable!(), }; + response.set_namespace(collection_container.namespace()); let mut skip_not_found = query.expand; let properties = match &query.propfind { diff --git a/crates/groupware/src/calendar/storage.rs b/crates/groupware/src/calendar/storage.rs index 6a02efcf..3a63457d 100644 --- a/crates/groupware/src/calendar/storage.rs +++ b/crates/groupware/src/calendar/storage.rs @@ -376,12 +376,16 @@ impl DestroyArchive> { batch.delete_document(document_id); // Remove next alarm if it exists - if let Some(next_alarm) = event.inner.data.next_alarm(now() as i64, Tz::Floating) { + let now = now() as i64; + if let Some(next_alarm) = event.inner.data.next_alarm(now, Tz::Floating) { next_alarm.delete_task(batch); } // Scheduling - if send_itip && event.inner.schedule_tag.is_some() { + if send_itip + && event.inner.schedule_tag.is_some() + && event.inner.data.event_range_end() > now + { let event = event .deserialize::() .caused_by(trc::location!())?;