diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 99777e05..6574e767 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -132,7 +132,7 @@ jobs: mkdir -p "${root}/target/${target}/release" && cd "$_" if [ "${USE_FOUNDATIONDB:-0}" = 1 ]; then - build -p mail-server --no-default-features --features "foundationdb elastic s3 redis" + build -p mail-server --no-default-features --features "foundationdb elastic s3 redis enterprise" artifact stalwart-mail stalwart-mail-foundationdb fi diff --git a/LICENSES/LicenseRef-SEL.txt b/LICENSES/LicenseRef-SEL.txt index 0230d7fe..79b44ae7 100644 --- a/LICENSES/LicenseRef-SEL.txt +++ b/LICENSES/LicenseRef-SEL.txt @@ -1,7 +1,7 @@ Stalwart Enterprise License 1.0 (SELv1) Agreement ================================================= -Last Update: June 26, 2024 +Last Update: July 8, 2024 PLEASE CAREFULLY READ THIS STALWART ENTERPRISE LICENSE AGREEMENT ("AGREEMENT"). THIS AGREEMENT CONSTITUTES A LEGALLY BINDING AGREEMENT BETWEEN YOU AND STALWART LABS LTD AND GOVERNS YOUR USE OF THE SOFTWARE (DEFINED BELOW). IF YOU DO NOT AGREE WITH THIS AGREEMENT, YOU MAY NOT USE THE SOFTWARE. IF YOU ARE USING THE SOFTWARE ON BEHALF OF A LEGAL ENTITY, YOU REPRESENT AND WARRANT THAT YOU HAVE AUTHORITY TO AGREE TO THIS AGREEMENT ON BEHALF OF SUCH ENTITY. IF YOU DO NOT HAVE SUCH AUTHORITY, DO NOT USE THE SOFTWARE IN ANY MANNER. @@ -10,9 +10,11 @@ This Agreement is entered into by and between Stalwart Labs Ltd and you, or the 1. DEFINITIONS 1.1. "Software" refers to the Stalwart Mail Server Enterprise Edition software, including all its versions, updates, modifications, accompanying documentation, and related materials. -1.2. "Licensor" refers to Stalwart Labs Ltd, the entity providing the Software. -1.3. "Licensee" refers to the individual or entity installing, accessing, or using the Software. -1.4. "License Key" refers to the unique code provided by Licensor upon purchasing a subscription which activates the full features of the Software. +1.2. "Subscription" refers to the paid access to the Software provided by Licensor to Licensee. +1.3. "Licensor" refers to Stalwart Labs Ltd, the entity providing the Software. +1.4. "Licensee" refers to the individual or entity installing, accessing, or using the Software with a valid Subscription. +1.5. "License Key" refers to the unique code provided by Licensor upon purchasing a Subscription which activates the full features of the Software. +1.6. "Source Code" refers to the human-readable version of the Software's code, as opposed to the compiled machine-readable version. 2. GRANT OF LICENSE @@ -20,21 +22,23 @@ This Agreement is entered into by and between Stalwart Labs Ltd and you, or the 2.2. The use of the Software is conditioned upon Licensee maintaining an active and valid paid subscription with Licensor. The paid subscription covers all versions of the Software and all updates and modifications. 2.3. This license grants Licensee the right to use the Software for both personal and commercial purposes. However, Licensee is expressly prohibited from reselling, leasing, sublicensing, or otherwise redistributing the Software itself. 2.4. This license is further governed by the terms and conditions set forth in any licensing agreements separately executed between Licensor and Licensee. In the event of any conflict between the terms of this Agreement and the terms of a signed licensing agreement, the terms of the signed licensing agreement shall control. +2.5. You are not granted any other rights beyond what is expressly stated herein. 3. LICENSE KEYS 3.1. The Software shall not be used without a valid License Key issued by Licensor. -3.1. Distribution or sharing of License Keys to third parties, not associated with Licensee, is strictly prohibited. -3.2. License Keys are bound to the subscription period. Should your subscription expire, all License Keys will become invalid after 15 days from the subscription expiration date. -3.3. Any instance of the Software using such an expired key will revert to the Community Edition functionality after the aforementioned 15-day period. +3.2. Licensee is required to use valid License Keys issued by Licensor to run the Software, including any modified versions. Any attempts to bypass the License Key requirement is a violation of this Agreement. +3.3. Distribution or sharing of License Keys to third parties, not associated with Licensee, is strictly prohibited. +3.4. License Keys are bound to the subscription period. Should your subscription expire, all License Keys will become invalid after 15 days from the subscription expiration date. +3.5. Any instance of the Software using such an expired key will revert to the Community Edition functionality after the aforementioned 15-day period. 4. SOURCE CODE USAGE -4.1. Licensee is permitted to view, copy, and modify the Software's source code, as made available by Licensor, solely for Licensee's internal business use and in compliance with this Agreement's terms. -4.2. Any modifications to the source code do not grant Licensee any ownership rights to the original Software or any modifications. All rights, title, and interest to the Software and its source code remain exclusively with Licensor. -4.3. Licensee is strictly prohibited from altering, removing, or in any way tampering with the license key validation system within the Software. Any such unauthorized modifications will be considered a material breach of this Agreement and may result in legal action. -4.4. Licensee is required to use valid License Keys issued by Licensor to run the Software, including any modified versions. Any attempts to bypass the License Key requirement is a violation of this Agreement. -4.5. Notwithstanding the availability of the Software's source code for review and limited modification, the Software and its source code are not open source and remain proprietary to Licensor. The provision of access to the source code does not confer any rights typically associated with open source software, including but not limited to the right to freely distribute, sublicense, or create derivative works for public distribution. All rights not expressly granted herein are reserved by Licensor. +4.1. Licensee is permitted to view, copy, and modify the Software's Source Code, as made available by Licensor, solely for Licensee's internal business use and in compliance with this Agreement's terms. +4.2. Any modifications to the Source Code do not grant Licensee any ownership rights to the original Software or any modifications. All rights, title, and interest to the Software and its Source Code remain exclusively with Licensor. +4.3. Licensee is strictly prohibited from altering, removing, or in any way tampering with the License Key validation system within the Software. Any such unauthorized modifications will be considered a material breach of this Agreement and may result in legal action. +4.3. Notwithstanding the availability of the Software's Source Code for review and limited modification, the Software and its Source Code are not open source and remain proprietary to Licensor. The provision of access to the Source Code does not confer any rights typically associated with open source software, including but not limited to the right to freely sublicense, or create derivative works for public distribution. All rights not expressly granted herein are reserved by Licensor. +4.4. Notwithstanding the foregoing, you may copy the Source Code for development and testing purposes, without requiring a Subscription. 5. INTELLECTUAL PROPERTY RIGHTS diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml index 5a5638b1..989f4798 100644 --- a/crates/common/Cargo.toml +++ b/crates/common/Cargo.toml @@ -10,7 +10,7 @@ nlp = { path = "../nlp" } store = { path = "../store" } directory = { path = "../directory" } jmap_proto = { path = "../jmap-proto" } -se_licensing = { path = "../se-licensing" } +se_licensing = { path = "../se-licensing", optional = true } sieve-rs = { version = "0.5" } mail-parser = { version = "0.9", features = ["full_encoding", "ludicrous_mode"] } mail-auth = { version = "0.4" } @@ -67,3 +67,4 @@ tracing-journald = "0.3" [features] test_mode = [] +enterprise = ["se_licensing"] diff --git a/crates/common/src/config/mod.rs b/crates/common/src/config/mod.rs index 0563eefb..64f707a8 100644 --- a/crates/common/src/config/mod.rs +++ b/crates/common/src/config/mod.rs @@ -4,20 +4,25 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use std::{sync::Arc, time::Duration}; +use std::sync::Arc; use arc_swap::ArcSwap; use directory::{Directories, Directory}; -use jmap_proto::types::collection::Collection; -use se_licensing::license::LicenseValidator; -use store::{BitmapKey, BlobBackend, BlobStore, FtsStore, LookupStore, Store, Stores}; +use store::{BlobBackend, BlobStore, FtsStore, LookupStore, Store, Stores}; use utils::config::Config; use crate::{ expr::*, listener::tls::TlsManager, manager::config::ConfigManager, webhooks::Webhooks, Core, - Enterprise, Network, + Network, }; +#[cfg(feature = "enterprise")] +use crate::Enterprise; +#[cfg(feature = "enterprise")] +use jmap_proto::types::collection::Collection; +#[cfg(feature = "enterprise")] +use se_licensing::license::LicenseValidator; + use self::{ imap::ImapConfig, jmap::settings::JmapConfig, scripts::Scripting, smtp::SmtpConfig, storage::Storage, @@ -122,6 +127,7 @@ impl Core { // SPDX-FileCopyrightText: 2020 Stalwart Labs Ltd // SPDX-License-Identifier: LicenseRef-SEL + #[cfg(feature = "enterprise")] let enterprise = match config.value("enterprise.license-key").map(|key| { LicenseValidator::new().try_parse(key).and_then(|key| { key.into_validated_key(config.value("lookup.default.hostname").unwrap_or_default()) @@ -129,7 +135,10 @@ impl Core { }) { Some(Ok(license)) => { match data - .get_bitmap(BitmapKey::document_ids(u32::MAX, Collection::Principal)) + .get_bitmap(store::BitmapKey::document_ids( + u32::MAX, + Collection::Principal, + )) .await { Ok(Some(bitmap)) if bitmap.len() > license.accounts as u64 => { @@ -152,7 +161,7 @@ impl Core { _ => Some(Enterprise { license, undelete_period: config - .property_or_default::>( + .property_or_default::>( "enterprise.undelete-period", "false", ) @@ -206,6 +215,7 @@ impl Core { blobs: stores.blob_stores, ftss: stores.fts_stores, }, + #[cfg(feature = "enterprise")] enterprise, } } diff --git a/crates/common/src/lib.rs b/crates/common/src/lib.rs index 458714e9..3d3bc1aa 100644 --- a/crates/common/src/lib.rs +++ b/crates/common/src/lib.rs @@ -4,7 +4,7 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use std::{borrow::Cow, net::IpAddr, sync::Arc, time::Duration}; +use std::{borrow::Cow, net::IpAddr, sync::Arc}; use arc_swap::ArcSwap; use config::{ @@ -35,6 +35,7 @@ use opentelemetry_sdk::{ Resource, }; use opentelemetry_semantic_conventions::resource::{SERVICE_NAME, SERVICE_VERSION}; +#[cfg(feature = "enterprise")] use se_licensing::license::LicenseKey; use sieve::Sieve; use store::LookupStore; @@ -71,6 +72,7 @@ pub struct Core { pub jmap: JmapConfig, pub imap: ImapConfig, pub web_hooks: Webhooks, + #[cfg(feature = "enterprise")] pub enterprise: Option, } @@ -85,10 +87,11 @@ pub struct Network { // SPDX-FileCopyrightText: 2020 Stalwart Labs Ltd // SPDX-License-Identifier: LicenseRef-SEL +#[cfg(feature = "enterprise")] #[derive(Clone)] pub struct Enterprise { pub license: LicenseKey, - pub undelete_period: Option, + pub undelete_period: Option, } // SPDX-SnippetEnd diff --git a/crates/jmap/Cargo.toml b/crates/jmap/Cargo.toml index 5abca4e9..9f20abf3 100644 --- a/crates/jmap/Cargo.toml +++ b/crates/jmap/Cargo.toml @@ -11,7 +11,7 @@ jmap_proto = { path = "../jmap-proto" } smtp = { path = "../smtp" } utils = { path = "../utils" } common = { path = "../common" } -se_common = { path = "../se-common" } +se_common = { path = "../se-common", optional = true } directory = { path = "../directory" } smtp-proto = { version = "0.1" } mail-parser = { version = "0.9", features = ["full_encoding", "serde_support", "ludicrous_mode"] } @@ -61,3 +61,4 @@ quick-xml = "0.35" [features] test_mode = [] +enterprise = ["se_common"] diff --git a/crates/jmap/src/api/management/enterprise.rs b/crates/jmap/src/api/management/enterprise.rs index 39c752f6..702a17d7 100644 --- a/crates/jmap/src/api/management/enterprise.rs +++ b/crates/jmap/src/api/management/enterprise.rs @@ -4,9 +4,8 @@ * SPDX-License-Identifier: LicenseRef-SEL * * This file is subject to the Stalwart Enterprise License Agreement (SEL) and - * is not open source software. It must not be modified or distributed without - * explicit permission from Stalwart Labs Ltd. - * Unauthorized use, modification, or distribution is strictly prohibited. + * is NOT open source software. + * */ use std::str::FromStr; diff --git a/crates/jmap/src/api/management/mod.rs b/crates/jmap/src/api/management/mod.rs index 97a92571..be90eea1 100644 --- a/crates/jmap/src/api/management/mod.rs +++ b/crates/jmap/src/api/management/mod.rs @@ -6,6 +6,7 @@ pub mod dkim; pub mod domain; +#[cfg(feature = "enterprise")] pub mod enterprise; pub mod log; pub mod principal; @@ -24,6 +25,8 @@ use serde::Serialize; use super::{http::ToHttpResponse, HttpRequest, HttpResponse, JsonResponse}; use crate::{auth::AccessToken, JMAP}; + +#[cfg(feature = "enterprise")] use se_common::EnterpriseCore; #[derive(Serialize)] @@ -95,6 +98,7 @@ impl JMAP { // SPDX-SnippetBegin // SPDX-FileCopyrightText: 2020 Stalwart Labs Ltd // SPDX-License-Identifier: LicenseRef-SEL + #[cfg(feature = "enterprise")] "pro" if is_superuser => { // WARNING: TAMPERING WITH THIS FUNCTION IS STRICTLY PROHIBITED // Any attempt to modify, bypass, or disable this license validation mechanism diff --git a/crates/jmap/src/auth/oauth/auth.rs b/crates/jmap/src/auth/oauth/auth.rs index 33a17e10..0c938e3f 100644 --- a/crates/jmap/src/auth/oauth/auth.rs +++ b/crates/jmap/src/auth/oauth/auth.rs @@ -23,6 +23,8 @@ use crate::{ auth::{oauth::OAuthStatus, AccessToken}, JMAP, }; + +#[cfg(feature = "enterprise")] use se_common::EnterpriseCore; use super::{ @@ -90,11 +92,16 @@ impl JMAP { return err.into_http_response(); } + #[cfg(not(feature = "enterprise"))] + let is_enterprise = false; + #[cfg(feature = "enterprise")] + let is_enterprise = self.core.is_enterprise_edition(); + json!({ "data": { "code": client_code, "is_admin": access_token.is_super_user(), - "is_enterprise": self.core.is_enterprise_edition(), + "is_enterprise": is_enterprise, }, }) } diff --git a/crates/jmap/src/email/delete.rs b/crates/jmap/src/email/delete.rs index de8669c6..2926c90f 100644 --- a/crates/jmap/src/email/delete.rs +++ b/crates/jmap/src/email/delete.rs @@ -13,6 +13,7 @@ use jmap_proto::{ type_state::DataType, }, }; +#[cfg(feature = "enterprise")] use se_common::undelete::Undelete; use store::{ ahash::AHashMap, @@ -516,6 +517,7 @@ impl JMAP { // SPDX-License-Identifier: LicenseRef-SEL // Hold blob for undeletion + #[cfg(feature = "enterprise")] self.core.hold_undelete( &mut batch, Collection::Email.into(), diff --git a/crates/jmap/src/services/housekeeper.rs b/crates/jmap/src/services/housekeeper.rs index 361fbb9d..2bcdb936 100644 --- a/crates/jmap/src/services/housekeeper.rs +++ b/crates/jmap/src/services/housekeeper.rs @@ -49,6 +49,7 @@ enum ActionClass { Account, Store(usize), Acme(String), + #[cfg(feature = "enterprise")] ReloadLicense, } @@ -113,6 +114,7 @@ pub fn spawn_housekeeper(core: JmapInstance, mut rx: mpsc::Receiver) { // SPDX-License-Identifier: LicenseRef-SEL // Enterprise Edition license management + #[cfg(feature = "enterprise")] if let Some(enterprise) = &core_.enterprise { queue.schedule( Instant::now() + enterprise.license.expires_in(), @@ -347,6 +349,7 @@ pub fn spawn_housekeeper(core: JmapInstance, mut rx: mpsc::Receiver) { // SPDX-SnippetBegin // SPDX-FileCopyrightText: 2020 Stalwart Labs Ltd // SPDX-License-Identifier: LicenseRef-SEL + #[cfg(feature = "enterprise")] ActionClass::ReloadLicense => { match core_.reload().await { Ok(result) => { diff --git a/crates/main/Cargo.toml b/crates/main/Cargo.toml index 6e1d4176..899631bf 100644 --- a/crates/main/Cargo.toml +++ b/crates/main/Cargo.toml @@ -26,7 +26,7 @@ managesieve = { path = "../managesieve" } common = { path = "../common" } directory = { path = "../directory" } utils = { path = "../utils" } -se_common = { path = "../se-common" } +se_common = { path = "../se-common", optional = true } tokio = { version = "1.23", features = ["full"] } tracing = "0.1" @@ -34,8 +34,8 @@ tracing = "0.1" jemallocator = "0.5.0" [features] -default = ["sqlite", "postgres", "mysql", "rocks", "elastic", "s3", "redis"] -#default = ["sqlite", "postgres", "mysql", "rocks", "elastic", "s3", "redis", "foundationdb"] +default = ["sqlite", "postgres", "mysql", "rocks", "elastic", "s3", "redis", "enterprise"] +#default = ["sqlite", "postgres", "mysql", "rocks", "elastic", "s3", "redis", "foundationdb", "enterprise"] sqlite = ["store/sqlite"] foundationdb = ["store/foundation"] postgres = ["store/postgres"] @@ -44,3 +44,4 @@ rocks = ["store/rocks"] elastic = ["store/elastic"] s3 = ["store/s3"] redis = ["store/redis"] +enterprise = ["se_common", "se_common/enterprise", "jmap/enterprise", "common/enterprise"] diff --git a/crates/main/src/main.rs b/crates/main/src/main.rs index ea61dc50..90443741 100644 --- a/crates/main/src/main.rs +++ b/crates/main/src/main.rs @@ -14,6 +14,7 @@ use imap::core::{ImapSessionManager, IMAP}; use jmap::{api::JmapSessionManager, services::gossip::spawn::GossiperBuilder, JMAP}; use managesieve::core::ManageSieveSessionManager; use pop3::Pop3SessionManager; +#[cfg(feature = "enterprise")] use se_common::EnterpriseCore; use smtp::core::{SmtpSessionManager, SMTP}; use tokio::sync::mpsc; @@ -56,6 +57,7 @@ async fn main() -> std::io::Result<()> { config.log_warnings(init.guards.is_none()); // Log licensing information + #[cfg(feature = "enterprise")] core.load().as_ref().log_license_details(); // Spawn servers diff --git a/crates/se-common/Cargo.toml b/crates/se-common/Cargo.toml index 16cad635..46e1a51d 100644 --- a/crates/se-common/Cargo.toml +++ b/crates/se-common/Cargo.toml @@ -14,3 +14,4 @@ serde = { version = "1.0", features = ["derive"]} [features] test_mode = [] +enterprise = ["common/enterprise"] diff --git a/crates/se-common/src/lib.rs b/crates/se-common/src/lib.rs index 1d286960..ec6e9e79 100644 --- a/crates/se-common/src/lib.rs +++ b/crates/se-common/src/lib.rs @@ -4,21 +4,22 @@ * SPDX-License-Identifier: LicenseRef-SEL * * This file is subject to the Stalwart Enterprise License Agreement (SEL) and - * is not open source software. It must not be modified or distributed without - * explicit permission from Stalwart Labs Ltd. - * Unauthorized use, modification, or distribution is strictly prohibited. + * is NOT open source software. + * */ +#[cfg(feature = "enterprise")] pub mod undelete; -use common::Core; +#[cfg(feature = "enterprise")] pub trait EnterpriseCore { fn is_enterprise_edition(&self) -> bool; fn log_license_details(&self); fn licensed_accounts(&self) -> u32; } -impl EnterpriseCore for Core { +#[cfg(feature = "enterprise")] +impl EnterpriseCore for common::Core { // WARNING: TAMPERING WITH THIS FUNCTION IS STRICTLY PROHIBITED // Any attempt to modify, bypass, or disable this license validation mechanism // constitutes a severe violation of the Stalwart Enterprise License Agreement. diff --git a/crates/se-common/src/undelete.rs b/crates/se-common/src/undelete.rs index fc9a19ae..6bf641c1 100644 --- a/crates/se-common/src/undelete.rs +++ b/crates/se-common/src/undelete.rs @@ -4,9 +4,8 @@ * SPDX-License-Identifier: LicenseRef-SEL * * This file is subject to the Stalwart Enterprise License Agreement (SEL) and - * is not open source software. It must not be modified or distributed without - * explicit permission from Stalwart Labs Ltd. - * Unauthorized use, modification, or distribution is strictly prohibited. + * is NOT open source software. + * */ use std::future::Future; diff --git a/crates/se-licensing/src/lib.rs b/crates/se-licensing/src/lib.rs index 180ec6b5..c74269aa 100644 --- a/crates/se-licensing/src/lib.rs +++ b/crates/se-licensing/src/lib.rs @@ -4,9 +4,8 @@ * SPDX-License-Identifier: LicenseRef-SEL * * This file is subject to the Stalwart Enterprise License Agreement (SEL) and - * is not open source software. It must not be modified or distributed without - * explicit permission from Stalwart Labs Ltd. - * Unauthorized use, modification, or distribution is strictly prohibited. + * is NOT open source software. + * */ pub mod license; diff --git a/crates/se-licensing/src/license.rs b/crates/se-licensing/src/license.rs index f1ff3f2c..a0b96303 100644 --- a/crates/se-licensing/src/license.rs +++ b/crates/se-licensing/src/license.rs @@ -4,9 +4,8 @@ * SPDX-License-Identifier: LicenseRef-SEL * * This file is subject to the Stalwart Enterprise License Agreement (SEL) and - * is not open source software. It must not be modified or distributed without - * explicit permission from Stalwart Labs Ltd. - * Unauthorized use, modification, or distribution is strictly prohibited. + * is NOT open source software. + * */ /* diff --git a/crates/smtp/src/outbound/mod.rs b/crates/smtp/src/outbound/mod.rs index a543f3e8..c1083137 100644 --- a/crates/smtp/src/outbound/mod.rs +++ b/crates/smtp/src/outbound/mod.rs @@ -38,7 +38,7 @@ impl Status<(), Error> { mail_send::Error::Io(_) | mail_send::Error::Tls(_) | mail_send::Error::Base64(_) - | mail_send::Error::UnparsableReply + | mail_send::Error::UnparseableReply | mail_send::Error::AuthenticationFailed(_) | mail_send::Error::MissingCredentials | mail_send::Error::MissingMailFrom