Mail Widget
This commit is contained in:
parent
42dad815dd
commit
7f9b128d47
@ -960,6 +960,14 @@ export async function getEmails(
|
|||||||
skip
|
skip
|
||||||
);
|
);
|
||||||
|
|
||||||
|
logger.debug('[EMAIL] Graph API returned emails', {
|
||||||
|
userId,
|
||||||
|
folder,
|
||||||
|
mailCredentialId: graphCheck.mailCredentialId,
|
||||||
|
count: graphResult.value?.length || 0,
|
||||||
|
hasNextLink: !!graphResult['@odata.nextLink'],
|
||||||
|
});
|
||||||
|
|
||||||
// Get mailboxes (folders)
|
// Get mailboxes (folders)
|
||||||
const graphFolders = await fetchGraphMailFolders(graphCheck.mailCredentialId);
|
const graphFolders = await fetchGraphMailFolders(graphCheck.mailCredentialId);
|
||||||
const mailboxes = graphFolders.map(f => f.displayName);
|
const mailboxes = graphFolders.map(f => f.displayName);
|
||||||
@ -969,6 +977,21 @@ export async function getEmails(
|
|||||||
convertGraphMessageToEmailMessage(msg, folder, accountId || 'default')
|
convertGraphMessageToEmailMessage(msg, folder, accountId || 'default')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Ensure emails are sorted by date (newest first) - Graph API should already do this, but double-check
|
||||||
|
emails.sort((a, b) => {
|
||||||
|
const dateA = a.date instanceof Date ? a.date.getTime() : new Date(a.date).getTime();
|
||||||
|
const dateB = b.date instanceof Date ? b.date.getTime() : new Date(b.date).getTime();
|
||||||
|
return dateB - dateA; // Descending order (newest first)
|
||||||
|
});
|
||||||
|
|
||||||
|
logger.debug('[EMAIL] Converted and sorted emails', {
|
||||||
|
userId,
|
||||||
|
folder,
|
||||||
|
count: emails.length,
|
||||||
|
firstEmailDate: emails[0]?.date,
|
||||||
|
lastEmailDate: emails[emails.length - 1]?.date,
|
||||||
|
});
|
||||||
|
|
||||||
// Calculate total (Graph API doesn't provide total count directly, so we estimate)
|
// Calculate total (Graph API doesn't provide total count directly, so we estimate)
|
||||||
const totalEmails = graphResult['@odata.nextLink']
|
const totalEmails = graphResult['@odata.nextLink']
|
||||||
? (page * perPage) + 1 // Has more pages
|
? (page * perPage) + 1 // Has more pages
|
||||||
|
|||||||
@ -99,13 +99,15 @@ export interface GraphMailFolder {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch emails from a Microsoft mailbox folder using Graph API
|
* Fetch emails from a Microsoft mailbox folder using Graph API
|
||||||
|
* Note: Microsoft Graph API doesn't support $skip for pagination, only $top and $skipToken
|
||||||
*/
|
*/
|
||||||
export async function fetchGraphEmails(
|
export async function fetchGraphEmails(
|
||||||
mailCredentialId: string,
|
mailCredentialId: string,
|
||||||
folderId: string = 'Inbox',
|
folderId: string = 'Inbox',
|
||||||
top: number = 50,
|
top: number = 50,
|
||||||
skip: number = 0,
|
skip: number = 0,
|
||||||
filter?: string
|
filter?: string,
|
||||||
|
skipToken?: string
|
||||||
): Promise<{
|
): Promise<{
|
||||||
value: GraphMailMessage[];
|
value: GraphMailMessage[];
|
||||||
'@odata.nextLink'?: string;
|
'@odata.nextLink'?: string;
|
||||||
@ -117,19 +119,47 @@ export async function fetchGraphEmails(
|
|||||||
let url = `/me/mailFolders/${folderId}/messages`;
|
let url = `/me/mailFolders/${folderId}/messages`;
|
||||||
const params = new URLSearchParams({
|
const params = new URLSearchParams({
|
||||||
'$top': top.toString(),
|
'$top': top.toString(),
|
||||||
'$skip': skip.toString(),
|
|
||||||
'$orderby': 'receivedDateTime desc',
|
'$orderby': 'receivedDateTime desc',
|
||||||
'$select': 'id,subject,from,toRecipients,ccRecipients,body,bodyPreview,receivedDateTime,sentDateTime,isRead,hasAttachments,importance,flag',
|
'$select': 'id,subject,from,toRecipients,ccRecipients,body,bodyPreview,receivedDateTime,sentDateTime,isRead,hasAttachments,importance,flag',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Microsoft Graph API supports $skip for messages endpoint, but it's more reliable to use $skipToken
|
||||||
|
// For the first page (skip=0), don't use $skip
|
||||||
|
// For subsequent pages, we can use $skip but $skipToken is preferred
|
||||||
|
if (skip > 0 && !skipToken) {
|
||||||
|
params.append('$skip', skip.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use skipToken if provided (for server-driven pagination from @odata.nextLink)
|
||||||
|
// This is the preferred method for pagination in Graph API
|
||||||
|
if (skipToken) {
|
||||||
|
params.append('$skiptoken', skipToken);
|
||||||
|
}
|
||||||
|
|
||||||
if (filter) {
|
if (filter) {
|
||||||
params.append('$filter', filter);
|
params.append('$filter', filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
url += `?${params.toString()}`;
|
url += `?${params.toString()}`;
|
||||||
|
|
||||||
|
logger.debug('Fetching emails from Microsoft Graph API', {
|
||||||
|
mailCredentialId,
|
||||||
|
folderId,
|
||||||
|
top,
|
||||||
|
skip,
|
||||||
|
skipToken: skipToken ? 'present' : 'none',
|
||||||
|
url,
|
||||||
|
});
|
||||||
|
|
||||||
const response = await client.get(url);
|
const response = await client.get(url);
|
||||||
|
|
||||||
|
logger.debug('Microsoft Graph API response', {
|
||||||
|
mailCredentialId,
|
||||||
|
folderId,
|
||||||
|
emailCount: response.data?.value?.length || 0,
|
||||||
|
hasNextLink: !!response.data?.['@odata.nextLink'],
|
||||||
|
});
|
||||||
|
|
||||||
return response.data;
|
return response.data;
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
logger.error('Error fetching emails from Microsoft Graph', {
|
logger.error('Error fetching emails from Microsoft Graph', {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user