From 74cd2ab96fe91f2ddec779636692852bce8d2a17 Mon Sep 17 00:00:00 2001 From: rustmailer Date: Sat, 22 Nov 2025 22:38:09 +0800 Subject: [PATCH] feat(graph api): Support Graph API for fetch_remote_messages --- .../cache/vendor/outlook/sync/client.rs | 4 +- src/modules/cache/vendor/outlook/sync/flow.rs | 12 ++-- src/modules/message/list.rs | 64 ++++++++++++++++++- .../features/mailbox/components/mail-list.tsx | 2 +- 4 files changed, 71 insertions(+), 11 deletions(-) diff --git a/src/modules/cache/vendor/outlook/sync/client.rs b/src/modules/cache/vendor/outlook/sync/client.rs index f95aee6..12c9f61 100644 --- a/src/modules/cache/vendor/outlook/sync/client.rs +++ b/src/modules/cache/vendor/outlook/sync/client.rs @@ -139,8 +139,8 @@ impl OutlookClient { account_id: u64, use_proxy: Option, folder_id: &str, - page: u32, - page_size: u32, + page: u64, + page_size: u64, after: Option<&str>, ) -> RustMailerResult { assert!(page > 0, "page must be greater than 0"); diff --git a/src/modules/cache/vendor/outlook/sync/flow.rs b/src/modules/cache/vendor/outlook/sync/flow.rs index dc8cb3b..faeb9c4 100644 --- a/src/modules/cache/vendor/outlook/sync/flow.rs +++ b/src/modules/cache/vendor/outlook/sync/flow.rs @@ -22,7 +22,7 @@ pub async fn fetch_and_save_since_date( let account_id = account.id; let use_proxy = account.use_proxy; let folder_limit = account.folder_limit.unwrap_or(u32::max_value()); - let mut page = 1; + let mut page = 1u32; let page_size = ENVELOPE_BATCH_SIZE; loop { @@ -34,8 +34,8 @@ pub async fn fetch_and_save_since_date( account_id, use_proxy, &folder.folder_id, - page, - page_size, + page as u64, + page_size as u64, Some(date), ) .await?; @@ -100,7 +100,7 @@ pub async fn fetch_and_save_full_folder( ) .await?; } - let mut page = 1; + let mut page = 1u32; loop { // Stop if we have already fetched enough messages if inserted_count as u32 >= total_to_fetch { @@ -110,8 +110,8 @@ pub async fn fetch_and_save_full_folder( account_id, use_proxy, &folder.folder_id, - page, - page_size, + page as u64, + page_size as u64, None, ) .await?; diff --git a/src/modules/message/list.rs b/src/modules/message/list.rs index f4fa2ab..f240619 100644 --- a/src/modules/message/list.rs +++ b/src/modules/message/list.rs @@ -11,7 +11,9 @@ use crate::{ model::Envelope, vendor::{ gmail::sync::{client::GmailClient, envelope::GmailEnvelope, labels::GmailLabels}, - outlook::sync::{envelope::OutlookEnvelope, folders::OutlookFolder}, + outlook::sync::{ + client::OutlookClient, envelope::OutlookEnvelope, folders::OutlookFolder, + }, }, }, common::{decode_page_token, parallel::run_with_limit}, @@ -19,6 +21,7 @@ use crate::{ envelope::extractor::extract_envelope, error::{code::ErrorCode, RustMailerResult}, rest::response::{CursorDataPage, DataPage}, + utils::mailbox_id, }, raise_error, }; @@ -189,7 +192,64 @@ async fn fetch_remote_messages( total_pages: Some(total_pages), }) } - MailerType::GraphApi => todo!(), + MailerType::GraphApi => { + let folders = OutlookClient::list_mailfolders(account.id, account.use_proxy).await?; + let folder = folders + .into_iter() + .find(|f| f.display_name == mailbox_name) + .ok_or_else(|| raise_error!("".into(), ErrorCode::InvalidParameter))?; + let total_items = folder + .total_item_count + .ok_or_else(|| raise_error!("".into(), ErrorCode::InvalidParameter))?; + + if total_items == 0 { + return Ok(CursorDataPage::new( + None, + Some(page_size), + 0, + Some(0), + vec![], + )); + } + + let total_pages = (total_items as f64 / page_size as f64).ceil() as u64; + let page = decode_page_token(next_page_token)?; + let resp = OutlookClient::list_messages( + account.id, + account.use_proxy, + &folder.id, + page, + page_size, + None, + ) + .await?; + + let envelopes: Vec = resp + .value + .into_iter() + .map(|m| { + let mut envelope: OutlookEnvelope = m.try_into()?; + envelope.account_id = account.id; + envelope.folder_id = mailbox_id(account.id, &folder.id); + envelope.folder_name = mailbox_name.to_string(); + Ok(envelope) + }) + .collect::>>()?; + + let next_page_token = if page == total_pages { + None + } else { + Some(base64_encode_url_safe!((page + 1).to_string())) + }; + + Ok(CursorDataPage::new( + next_page_token, + Some(page_size), + total_items as u64, + Some(total_pages), + envelopes.into_iter().map(Into::into).collect(), + )) + } } } diff --git a/web/src/features/mailbox/components/mail-list.tsx b/web/src/features/mailbox/components/mail-list.tsx index 08a33a8..9b25876 100644 --- a/web/src/features/mailbox/components/mail-list.tsx +++ b/web/src/features/mailbox/components/mail-list.tsx @@ -44,7 +44,7 @@ export function MailList({ if (isLoading) { return (
- {Array.from({ length: 8 }).map((_, i) => ( + {Array.from({ length: 20 }).map((_, i) => (