mirror of
https://github.com/rustmailer/bichon.git
synced 2026-08-31 01:52:30 +00:00
86 lines
2.5 KiB
Rust
86 lines
2.5 KiB
Rust
use crate::{
|
|
encode_mailbox_name, raise_error,
|
|
{
|
|
account::migration::{AccountModel, AccountType},
|
|
envelope::extractor::reattach_eml_content,
|
|
error::{code::ErrorCode, BichonResult},
|
|
imap::executor::ImapExecutor,
|
|
},
|
|
};
|
|
//use poem_openapi::Object;
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
const MAX_RESTORE_COUNT: usize = 100;
|
|
|
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
|
|
#[cfg_attr(feature = "web-api", derive(poem_openapi::Object))]
|
|
pub struct RestoreMessagesRequest {
|
|
/// envelope IDs to restore (max 100)
|
|
pub envelope_ids: Vec<String>,
|
|
}
|
|
|
|
pub async fn restore_emails(account_id: u64, envelope_ids: Vec<String>) -> BichonResult<()> {
|
|
if envelope_ids.len() > MAX_RESTORE_COUNT {
|
|
return Err(raise_error!(
|
|
format!(
|
|
"Too many messages to restore: {} (max {})",
|
|
envelope_ids.len(),
|
|
MAX_RESTORE_COUNT
|
|
),
|
|
ErrorCode::InvalidParameter
|
|
));
|
|
}
|
|
|
|
let account = AccountModel::check_account_exists(account_id)?;
|
|
if !matches!(account.account_type, AccountType::IMAP) {
|
|
return Err(raise_error!(
|
|
"Account type is not IMAP".into(),
|
|
ErrorCode::Incompatible
|
|
));
|
|
}
|
|
|
|
let mut failed = Vec::new();
|
|
let mut session = ImapExecutor::create_connection(account_id).await?;
|
|
for envelope_id in envelope_ids {
|
|
let result: BichonResult<()> = async {
|
|
let (envelope, eml) = reattach_eml_content(account_id, envelope_id.clone())?;
|
|
if let Some(mailbox_name) = envelope.mailbox_name {
|
|
ImapExecutor::append(
|
|
&mut session,
|
|
encode_mailbox_name!(&mailbox_name),
|
|
None,
|
|
None,
|
|
&eml,
|
|
)
|
|
.await?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
.await;
|
|
|
|
if let Err(err) = result {
|
|
tracing::warn!(
|
|
account_id = account_id,
|
|
message_id = &envelope_id,
|
|
error = ?err,
|
|
"Failed to restore email"
|
|
);
|
|
failed.push(envelope_id);
|
|
}
|
|
}
|
|
|
|
if !failed.is_empty() {
|
|
tracing::info!(
|
|
account_id = account_id,
|
|
failed_count = failed.len(),
|
|
failed_message_ids = ?failed,
|
|
"Restore emails finished with partial failures"
|
|
);
|
|
}
|
|
|
|
session.logout().await.ok();
|
|
|
|
Ok(())
|
|
}
|