Import upstream v0.16.22, stripped
Upstream commit: 474dd0229cb20cf513036619781ed97bd8073c3f Enterprise-only files removed or emptied: 63 Enterprise-only snippets removed: 117 in 50 files Dangling module declarations removed: 5 Cargo edits turning enterprise off: 14 Verification: clean Enterprise feature gates left for rebuilt features: 19 in 18 files Produced by tools/fork/strip.py. The full report is in docs/fork/strip-reports/ on main.
This commit is contained in:
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use ahash::{AHashMap, AHashSet};
|
||||
use nlp::language::Language;
|
||||
use registry::{
|
||||
schema::{
|
||||
enums::{
|
||||
CompressionAlgo, SearchCalendarField, SearchContactField, SearchEmailField,
|
||||
StorageQuota,
|
||||
},
|
||||
prelude::ObjectType,
|
||||
structs::{
|
||||
AddressBook, Authentication, Calendar, DataRetention, Domain, Email, FileStorage, Jmap,
|
||||
Search, SieveUserInterpreter, SystemSettings,
|
||||
},
|
||||
},
|
||||
types::EnumImpl,
|
||||
};
|
||||
use std::time::Duration;
|
||||
use store::{
|
||||
registry::bootstrap::Bootstrap,
|
||||
search::{CalendarSearchField, ContactSearchField, EmailSearchField, SearchField},
|
||||
write::SearchIndex,
|
||||
};
|
||||
use types::special_use::SpecialUse;
|
||||
use utils::cron::SimpleCron;
|
||||
|
||||
use crate::storage::ObjectQuota;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct EmailConfig {
|
||||
pub default_language: Language,
|
||||
pub default_domain_id: u32,
|
||||
pub default_domain_name: String,
|
||||
|
||||
pub mailbox_max_depth: usize,
|
||||
pub mailbox_name_max_len: usize,
|
||||
|
||||
pub mail_attachments_max_size: usize,
|
||||
pub mail_max_size: usize,
|
||||
pub mail_autoexpunge_after: Option<u64>,
|
||||
pub email_submission_autoexpunge_after: Option<u64>,
|
||||
|
||||
pub changes_max_history: Option<usize>,
|
||||
pub share_notification_max_history: Option<Duration>,
|
||||
|
||||
pub sieve_max_script_name: usize,
|
||||
|
||||
pub default_folders: Vec<DefaultFolder>,
|
||||
pub shared_folder: String,
|
||||
|
||||
pub encrypt: bool,
|
||||
pub encrypt_append: bool,
|
||||
|
||||
pub index_batch_size: usize,
|
||||
pub index_fields: AHashMap<SearchIndex, AHashSet<SearchField>>,
|
||||
|
||||
pub max_objects: ObjectQuota,
|
||||
pub compression: CompressionAlgo,
|
||||
|
||||
pub account_purge_frequency: SimpleCron,
|
||||
pub data_purge_frequency: SimpleCron,
|
||||
pub blob_purge_frequency: SimpleCron,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DefaultFolder {
|
||||
pub name: String,
|
||||
pub aliases: Vec<String>,
|
||||
pub special_use: SpecialUse,
|
||||
pub subscribe: bool,
|
||||
pub create: bool,
|
||||
}
|
||||
|
||||
impl EmailConfig {
|
||||
pub async fn parse(bp: &mut Bootstrap) -> Self {
|
||||
let email = bp.setting_infallible::<Email>().await;
|
||||
let dr = bp.setting_infallible::<DataRetention>().await;
|
||||
let sieve = bp.setting_infallible::<SieveUserInterpreter>().await;
|
||||
let search = bp.setting_infallible::<Search>().await;
|
||||
let jmap = bp.setting_infallible::<Jmap>().await;
|
||||
let file = bp.setting_infallible::<FileStorage>().await;
|
||||
let calendar = bp.setting_infallible::<Calendar>().await;
|
||||
let address_book = bp.setting_infallible::<AddressBook>().await;
|
||||
let system = bp.setting_infallible::<SystemSettings>().await;
|
||||
let auth = bp.setting_infallible::<Authentication>().await;
|
||||
|
||||
// Obtain default domain name
|
||||
let default_domain_name = if system.default_domain_id.is_valid()
|
||||
&& let Some(default_domain) =
|
||||
bp.get_infallible::<Domain>(system.default_domain_id).await
|
||||
{
|
||||
default_domain.name
|
||||
} else {
|
||||
if system.default_domain_id.is_valid() {
|
||||
bp.build_error(
|
||||
ObjectType::SystemSettings.singleton(),
|
||||
format!(
|
||||
"Default domain with ID {} not found",
|
||||
system.default_domain_id
|
||||
),
|
||||
);
|
||||
}
|
||||
"localhost.local".to_string()
|
||||
};
|
||||
|
||||
// Parse default object quotas
|
||||
let mut max_objects = ObjectQuota::default();
|
||||
for (item, max) in [
|
||||
(StorageQuota::MaxEmails, email.max_messages),
|
||||
(StorageQuota::MaxMailboxes, email.max_mailboxes),
|
||||
(StorageQuota::MaxSieveScripts, sieve.max_scripts),
|
||||
(StorageQuota::MaxEmailIdentities, email.max_identities),
|
||||
(StorageQuota::MaxEmailSubmissions, email.max_submissions),
|
||||
(StorageQuota::MaxMaskedAddresses, email.max_masked_addresses),
|
||||
(StorageQuota::MaxAppPasswords, auth.max_app_passwords),
|
||||
(StorageQuota::MaxApiKeys, auth.max_api_keys),
|
||||
(StorageQuota::MaxPublicKeys, email.max_public_keys),
|
||||
(StorageQuota::MaxPushSubscriptions, jmap.max_subscriptions),
|
||||
(StorageQuota::MaxCalendars, calendar.max_calendars),
|
||||
(StorageQuota::MaxCalendarEvents, calendar.max_events),
|
||||
(
|
||||
StorageQuota::MaxParticipantIdentities,
|
||||
calendar.max_participant_identities,
|
||||
),
|
||||
(
|
||||
StorageQuota::MaxCalendarEventNotifications,
|
||||
calendar.max_event_notifications,
|
||||
),
|
||||
(
|
||||
StorageQuota::MaxAddressBooks,
|
||||
address_book.max_address_books,
|
||||
),
|
||||
(StorageQuota::MaxContactCards, address_book.max_contacts),
|
||||
(StorageQuota::MaxFiles, file.max_files),
|
||||
(StorageQuota::MaxFolders, file.max_folders),
|
||||
] {
|
||||
if let Some(max) = max {
|
||||
max_objects.set(item, max as u32);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse default folders
|
||||
let mut default_folders = Vec::new();
|
||||
let mut shared_folder = "Shared Folders".to_string();
|
||||
for (special_use, folder) in email.default_folders {
|
||||
let special_use = match special_use {
|
||||
registry::schema::enums::SpecialUse::Inbox => SpecialUse::Inbox,
|
||||
registry::schema::enums::SpecialUse::Trash => SpecialUse::Trash,
|
||||
registry::schema::enums::SpecialUse::Junk => SpecialUse::Junk,
|
||||
registry::schema::enums::SpecialUse::Drafts => SpecialUse::Drafts,
|
||||
registry::schema::enums::SpecialUse::Archive => SpecialUse::Archive,
|
||||
registry::schema::enums::SpecialUse::Sent => SpecialUse::Sent,
|
||||
registry::schema::enums::SpecialUse::Important => SpecialUse::Important,
|
||||
registry::schema::enums::SpecialUse::Memos => SpecialUse::Memos,
|
||||
registry::schema::enums::SpecialUse::Scheduled => SpecialUse::Scheduled,
|
||||
registry::schema::enums::SpecialUse::Snoozed => SpecialUse::Snoozed,
|
||||
registry::schema::enums::SpecialUse::Shared => {
|
||||
shared_folder = folder.name;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
default_folders.push(DefaultFolder {
|
||||
name: folder.name,
|
||||
aliases: folder.aliases.into_inner(),
|
||||
special_use,
|
||||
subscribe: folder.subscribe,
|
||||
create: folder.create
|
||||
|| matches!(
|
||||
special_use,
|
||||
SpecialUse::Inbox | SpecialUse::Trash | SpecialUse::Junk
|
||||
),
|
||||
});
|
||||
}
|
||||
for (special_use, name) in [
|
||||
(SpecialUse::Inbox, "Inbox"),
|
||||
(SpecialUse::Trash, "Deleted Items"),
|
||||
(SpecialUse::Junk, "Junk Mail"),
|
||||
(SpecialUse::Drafts, "Drafts"),
|
||||
(SpecialUse::Sent, "Sent Items"),
|
||||
] {
|
||||
if !default_folders.iter().any(|f| f.special_use == special_use) {
|
||||
default_folders.push(DefaultFolder {
|
||||
name: name.to_string(),
|
||||
aliases: Vec::new(),
|
||||
special_use,
|
||||
subscribe: true,
|
||||
create: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Search Index settings
|
||||
let mut index_fields = AHashMap::new();
|
||||
if search.index_email {
|
||||
index_fields.insert(
|
||||
SearchIndex::Email,
|
||||
search
|
||||
.index_email_fields
|
||||
.into_iter()
|
||||
.map(|field| {
|
||||
SearchField::Email(match field {
|
||||
SearchEmailField::From => EmailSearchField::From,
|
||||
SearchEmailField::To => EmailSearchField::To,
|
||||
SearchEmailField::Cc => EmailSearchField::Cc,
|
||||
SearchEmailField::Bcc => EmailSearchField::Bcc,
|
||||
SearchEmailField::Subject => EmailSearchField::Subject,
|
||||
SearchEmailField::Body => EmailSearchField::Body,
|
||||
SearchEmailField::Attachment => EmailSearchField::Attachment,
|
||||
SearchEmailField::ReceivedAt => EmailSearchField::ReceivedAt,
|
||||
SearchEmailField::SentAt => EmailSearchField::SentAt,
|
||||
SearchEmailField::Size => EmailSearchField::Size,
|
||||
SearchEmailField::HasAttachment => EmailSearchField::HasAttachment,
|
||||
SearchEmailField::Headers => EmailSearchField::Headers,
|
||||
})
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
if search.index_contacts {
|
||||
index_fields.insert(
|
||||
SearchIndex::Contacts,
|
||||
search
|
||||
.index_contact_fields
|
||||
.into_iter()
|
||||
.map(|field| {
|
||||
SearchField::Contact(match field {
|
||||
SearchContactField::Member => ContactSearchField::Member,
|
||||
SearchContactField::Kind => ContactSearchField::Kind,
|
||||
SearchContactField::Name => ContactSearchField::Name,
|
||||
SearchContactField::Nickname => ContactSearchField::Nickname,
|
||||
SearchContactField::Organization => ContactSearchField::Organization,
|
||||
SearchContactField::Email => ContactSearchField::Email,
|
||||
SearchContactField::Phone => ContactSearchField::Phone,
|
||||
SearchContactField::OnlineService => ContactSearchField::OnlineService,
|
||||
SearchContactField::Address => ContactSearchField::Address,
|
||||
SearchContactField::Note => ContactSearchField::Note,
|
||||
SearchContactField::Uid => ContactSearchField::Uid,
|
||||
})
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
if search.index_calendar {
|
||||
index_fields.insert(
|
||||
SearchIndex::Calendar,
|
||||
search
|
||||
.index_calendar_fields
|
||||
.into_iter()
|
||||
.map(|field| {
|
||||
SearchField::Calendar(match field {
|
||||
SearchCalendarField::Title => CalendarSearchField::Title,
|
||||
SearchCalendarField::Description => CalendarSearchField::Description,
|
||||
SearchCalendarField::Location => CalendarSearchField::Location,
|
||||
SearchCalendarField::Owner => CalendarSearchField::Owner,
|
||||
SearchCalendarField::Attendee => CalendarSearchField::Attendee,
|
||||
SearchCalendarField::Start => CalendarSearchField::Start,
|
||||
SearchCalendarField::Uid => CalendarSearchField::Uid,
|
||||
})
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
|
||||
EmailConfig {
|
||||
default_language: Language::from_iso_639(search.default_language.as_str())
|
||||
.unwrap_or(Language::English),
|
||||
mailbox_max_depth: email.max_mailbox_depth as usize,
|
||||
mailbox_name_max_len: email.max_mailbox_name_length as usize,
|
||||
mail_attachments_max_size: email.max_attachment_size as usize,
|
||||
mail_max_size: email.max_message_size as usize,
|
||||
mail_autoexpunge_after: dr.expunge_trash_after.map(|d| d.into_inner().as_secs()),
|
||||
email_submission_autoexpunge_after: dr
|
||||
.expunge_submissions_after
|
||||
.map(|d| d.into_inner().as_secs()),
|
||||
changes_max_history: dr.max_changes_history.map(|v| v as usize),
|
||||
share_notification_max_history: dr.expunge_share_notify_after.map(|v| v.into_inner()),
|
||||
sieve_max_script_name: sieve.max_script_name_length as usize,
|
||||
encrypt: email.encrypt_at_rest,
|
||||
encrypt_append: email.encrypt_on_append,
|
||||
index_batch_size: search.index_batch_size as usize,
|
||||
index_fields,
|
||||
max_objects,
|
||||
default_folders,
|
||||
shared_folder,
|
||||
account_purge_frequency: dr.expunge_schedule.into(),
|
||||
data_purge_frequency: dr.data_cleanup_schedule.into(),
|
||||
blob_purge_frequency: dr.blob_cleanup_schedule.into(),
|
||||
compression: email.compression_algorithm,
|
||||
default_domain_id: system.default_domain_id.id() as u32,
|
||||
default_domain_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user