Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions crates/admin/src/meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ impl From<AccountV3> for AccountModel {
updated_at: value.updated_at,
created_by: value.created_by,
use_dangerous: value.use_dangerous,
uidonly_enabled: false,
pgp_key: value.pgp_key,
imap_quota_window: None,
imap_quota_bytes: None,
Expand Down Expand Up @@ -666,6 +667,7 @@ impl From<MailBox> for bichon_core::cache::imap::mailbox::MailBox {
uid_next: value.uid_next,
uid_validity: value.uid_validity,
highest_uid: None,
uidonly_source_scope: None,
}
}
}
Expand Down
34 changes: 34 additions & 0 deletions crates/core/src/account/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,9 @@ pub struct Account {
pub updated_at: i64,
pub created_by: u64, //user id
pub use_dangerous: bool,
/// UIDONLY acquisition is opt-in because it changes remote message identity.
#[serde(default)]
pub uidonly_enabled: bool,
pub pgp_key: Option<String>,
pub imap_quota_bytes: Option<u64>,
pub imap_quota_window: Option<QuotaWindow>,
Expand Down Expand Up @@ -345,6 +348,7 @@ impl Account {
created_at: utc_now!(),
updated_at: utc_now!(),
use_dangerous: request.use_dangerous,
uidonly_enabled: request.uidonly_enabled.unwrap_or_default(),
pgp_key: request.pgp_key,
created_by: user_id,
download_batch_size: request.download_batch_size,
Expand Down Expand Up @@ -668,6 +672,10 @@ impl Account {
new.use_dangerous = use_dangerous;
}

if let Some(uidonly_enabled) = request.uidonly_enabled {
new.uidonly_enabled = uidonly_enabled;
}

if let Some(pgp_key) = request.pgp_key {
new.pgp_key = Some(pgp_key);
}
Expand Down Expand Up @@ -704,6 +712,32 @@ impl Account {
mod tests {
use super::*;

#[test]
fn uidonly_setting_defaults_off_and_only_changes_explicitly() {
let account = Account::new(1, AccountCreateRequest::default()).unwrap();
assert!(!account.uidonly_enabled);
let update = |old: &Account, value| {
Account::apply_update_fields(
old,
AccountUpdateRequest {
uidonly_enabled: value,
..Default::default()
},
)
.unwrap()
};
let enabled = update(&account, Some(true));
assert!(enabled.uidonly_enabled);
assert!(update(&enabled, None).uidonly_enabled);
assert!(!update(&enabled, Some(false)).uidonly_enabled);

let mut legacy = serde_json::to_value(enabled).unwrap();
legacy.as_object_mut().unwrap().remove("uidonly_enabled");
assert!(!serde_json::from_value::<Account>(legacy)
.unwrap()
.uidonly_enabled);
}

// ── FilterRule ───────────────────────────────────────────────────

#[test]
Expand Down
5 changes: 5 additions & 0 deletions crates/core/src/account/payload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ pub struct AccountCreateRequest {
pub download_batch_size: Option<u32>,
pub max_email_size_bytes: Option<u64>,
pub use_dangerous: bool,
/// Explicitly enables UIDONLY acquisition when required by the server.
/// Omitted values remain disabled for backward compatibility.
pub uidonly_enabled: Option<bool>,
pub pgp_key: Option<String>,
pub imap_quota_bytes: Option<u64>,
pub imap_quota_window: Option<QuotaWindow>,
Expand Down Expand Up @@ -188,6 +191,8 @@ pub struct AccountUpdateRequest {
pub download_batch_size: Option<u32>,
pub max_email_size_bytes: Option<u64>,
pub use_dangerous: Option<bool>,
/// Enables or disables UIDONLY acquisition for this account.
pub uidonly_enabled: Option<bool>,

pub pgp_key: Option<String>,
pub imap_quota_bytes: Option<u64>,
Expand Down
2 changes: 2 additions & 0 deletions crates/core/src/account/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ pub struct AccountResp {
pub created_user_name: String,
pub created_user_email: String,
pub use_dangerous: bool,
pub uidonly_enabled: bool,
pub pgp_key: Option<String>,
pub imap_quota_bytes: Option<u64>,
pub imap_quota_window: Option<QuotaWindow>,
Expand Down Expand Up @@ -90,6 +91,7 @@ impl AccountResp {
.map(|u| u.email.clone())
.unwrap_or_else(|| "N/A".to_string()),
use_dangerous: account.use_dangerous,
uidonly_enabled: account.uidonly_enabled,
pgp_key: account.pgp_key,
imap_quota_bytes: account.imap_quota_bytes,
imap_quota_window: account.imap_quota_window,
Expand Down
Loading