mirror of
https://github.com/rustmailer/rustmailer.git
synced 2026-09-10 00:04:05 +00:00
- Introduced `MailerType` enum in Account model - Enables selection of different mailer backends (e.g., Gmail API)
195 lines
6.3 KiB
Rust
195 lines
6.3 KiB
Rust
// Copyright © 2025 rustmailer.com
|
|
// Licensed under RustMailer License Agreement v1.0
|
|
// Unauthorized copying, modification, or distribution is prohibited.
|
|
|
|
use crate::modules::{
|
|
account::{since::DateSince, v2::AccountV2},
|
|
cache::imap::{
|
|
mailbox::MailBox,
|
|
manager::EnvelopeFlagsManager,
|
|
sync::flow::{fetch_and_save_full_mailbox, fetch_and_save_since_date},
|
|
},
|
|
error::RustMailerResult,
|
|
};
|
|
use std::time::Instant;
|
|
use tracing::{error, info, warn};
|
|
|
|
pub async fn rebuild_cache(
|
|
account: &AccountV2,
|
|
remote_mailboxes: &[MailBox],
|
|
) -> RustMailerResult<()> {
|
|
let start_time = Instant::now();
|
|
let mut total_inserted = 0;
|
|
|
|
MailBox::batch_insert(remote_mailboxes).await?;
|
|
for mailbox in remote_mailboxes {
|
|
if mailbox.exists == 0 {
|
|
info!(
|
|
"Account {}: Mailbox '{}' on the remote server has no emails. Skipping fetch for this mailbox.",
|
|
account.id, &mailbox.name
|
|
);
|
|
continue;
|
|
}
|
|
// total_inserted +=
|
|
// fetch_and_save_full_mailbox(account, mailbox, mailbox.exists, true).await?;
|
|
match fetch_and_save_full_mailbox(account, mailbox, mailbox.exists, true).await {
|
|
Ok(inserted) => {
|
|
total_inserted += inserted;
|
|
}
|
|
Err(e) => {
|
|
warn!(
|
|
"Account {}: Failed to sync mailbox '{}'. Error: {}. Removing mailbox entry.",
|
|
account.id, &mailbox.name, e
|
|
);
|
|
if let Err(del_err) = MailBox::delete(mailbox.id).await {
|
|
error!(
|
|
"Account {}: Failed to delete mailbox '{}' after sync error: {}",
|
|
account.id, &mailbox.name, del_err
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// commit(account).await?;
|
|
|
|
let elapsed_time = start_time.elapsed().as_secs();
|
|
info!(
|
|
"Rebuild account cache completed: {} envelopes inserted. {} secs elapsed. \
|
|
This is a full data fetch as there was no local cache data available.",
|
|
total_inserted, elapsed_time
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn rebuild_cache_since_date(
|
|
account: &AccountV2,
|
|
remote_mailboxes: &[MailBox],
|
|
date_since: &DateSince,
|
|
) -> RustMailerResult<()> {
|
|
let start_time = Instant::now();
|
|
let mut total_inserted = 0;
|
|
let date = date_since.since_date()?;
|
|
|
|
MailBox::batch_insert(remote_mailboxes).await?;
|
|
|
|
for mailbox in remote_mailboxes {
|
|
if mailbox.exists == 0 {
|
|
info!(
|
|
"Account {}: Mailbox '{}' on the remote server has no emails. Skipping fetch for this mailbox.",
|
|
account.id, &mailbox.name
|
|
);
|
|
continue;
|
|
}
|
|
|
|
match fetch_and_save_since_date(
|
|
account.id,
|
|
date.as_str(),
|
|
mailbox,
|
|
true,
|
|
account.minimal_sync(),
|
|
)
|
|
.await
|
|
{
|
|
Ok(inserted) => {
|
|
total_inserted += inserted;
|
|
}
|
|
Err(e) => {
|
|
warn!(
|
|
"Account {}: Failed to sync mailbox '{}'. Error: {}. Removing mailbox entry.",
|
|
account.id, &mailbox.name, e
|
|
);
|
|
if let Err(del_err) = MailBox::delete(mailbox.id).await {
|
|
error!(
|
|
"Account {}: Failed to delete mailbox '{}' after sync error: {}",
|
|
account.id, &mailbox.name, del_err
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
let elapsed_time = start_time.elapsed().as_secs();
|
|
info!(
|
|
"Rebuild account cache completed: {} envelopes inserted. {} secs elapsed. \
|
|
Data fetched from server starting from the specified date: {}.",
|
|
total_inserted, elapsed_time, date
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn should_rebuild_cache(
|
|
account: &AccountV2,
|
|
mailbox_count: usize,
|
|
local_envelope_count: usize,
|
|
) -> RustMailerResult<bool> {
|
|
// If both remote mailboxes and local envelopes exist, no rebuild is needed.
|
|
if mailbox_count > 0 && local_envelope_count > 0 {
|
|
return Ok(false);
|
|
}
|
|
// If there are remote mailboxes but no local envelopes, clear the mailboxes.
|
|
if mailbox_count > 0 {
|
|
let mailboxes = MailBox::list_all(account.id).await?;
|
|
MailBox::batch_delete(mailboxes).await?;
|
|
}
|
|
if local_envelope_count > 0 {
|
|
EnvelopeFlagsManager::clean_account(account.id).await?
|
|
}
|
|
// If either remote mailboxes or local envelopes were missing, cache rebuild is required.
|
|
Ok(true)
|
|
}
|
|
|
|
pub async fn rebuild_mailbox_cache(
|
|
account: &AccountV2,
|
|
local_mailbox: &MailBox,
|
|
remote_mailbox: &MailBox,
|
|
) -> RustMailerResult<()> {
|
|
EnvelopeFlagsManager::clean_mailbox(account.id, local_mailbox.id).await?;
|
|
if remote_mailbox.exists == 0 {
|
|
info!(
|
|
"Account {}: Mailbox '{}' has no emails on the remote server. The mailbox is empty, no envelopes to fetch.",
|
|
account.id,
|
|
&local_mailbox.name
|
|
);
|
|
return Ok(()); // Skip if the mailbox has no emails
|
|
}
|
|
|
|
let inserted_count =
|
|
fetch_and_save_full_mailbox(account, remote_mailbox, remote_mailbox.exists, false).await?;
|
|
info!(
|
|
"Account {}: Successfully rebuild mailbox cache, inserted {} envelopes for mailbox '{}'.",
|
|
account.id, inserted_count, &local_mailbox.name
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn rebuild_mailbox_cache_since_date(
|
|
account: &AccountV2,
|
|
local_mailbox_id: u64,
|
|
date_since: &DateSince,
|
|
remote: &MailBox,
|
|
) -> RustMailerResult<()> {
|
|
EnvelopeFlagsManager::clean_mailbox(account.id, local_mailbox_id).await?;
|
|
if remote.exists == 0 {
|
|
info!(
|
|
"Account {}: Mailbox '{}' has no emails on the remote server. The mailbox is empty, no envelopes to fetch.",
|
|
account.id,
|
|
&remote.name
|
|
);
|
|
return Ok(()); // Skip if the mailbox has no emails
|
|
}
|
|
|
|
let count = fetch_and_save_since_date(
|
|
account.id,
|
|
date_since.since_date()?.as_str(),
|
|
remote,
|
|
false,
|
|
account.minimal_sync(),
|
|
)
|
|
.await?;
|
|
info!(
|
|
"Account {}: Successfully rebuild mailbox cache, inserted {} envelopes for mailbox '{}'.",
|
|
account.id, count, &remote.name
|
|
);
|
|
Ok(())
|
|
}
|