attachments courrier
This commit is contained in:
parent
3dd9193c20
commit
807200d9e4
@ -210,81 +210,137 @@ export async function fetchGraphEmail(
|
|||||||
hasAttachments: message.hasAttachments,
|
hasAttachments: message.hasAttachments,
|
||||||
attachmentsInResponse: !!message.attachments,
|
attachmentsInResponse: !!message.attachments,
|
||||||
attachmentsCount: message.attachments?.length || 0,
|
attachmentsCount: message.attachments?.length || 0,
|
||||||
|
attachmentsType: typeof message.attachments,
|
||||||
|
attachmentsIsArray: Array.isArray(message.attachments),
|
||||||
|
attachmentsKeys: message.attachments ? Object.keys(message.attachments) : [],
|
||||||
mailCredentialIdHash: Buffer.from(mailCredentialId).toString('base64').slice(0, 12),
|
mailCredentialIdHash: Buffer.from(mailCredentialId).toString('base64').slice(0, 12),
|
||||||
});
|
});
|
||||||
|
|
||||||
// If email has attachments but they weren't included in the response, fetch them separately
|
// Handle case where $expand returns attachments in a different structure
|
||||||
if (message.hasAttachments && (!message.attachments || message.attachments.length === 0)) {
|
// Sometimes attachments might be in message.attachments.value instead of message.attachments
|
||||||
try {
|
if (message.attachments && !Array.isArray(message.attachments) && message.attachments.value) {
|
||||||
logger.debug('Fetching attachments list from Graph API', {
|
logger.debug('Attachments found in .value property', {
|
||||||
|
messageId,
|
||||||
|
count: message.attachments.value?.length || 0,
|
||||||
|
});
|
||||||
|
message.attachments = message.attachments.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process attachments - either from initial response or fetch separately
|
||||||
|
if (message.hasAttachments) {
|
||||||
|
// If attachments are already in the response, process them
|
||||||
|
if (message.attachments && Array.isArray(message.attachments) && message.attachments.length > 0) {
|
||||||
|
logger.debug('Processing attachments from initial response', {
|
||||||
messageId,
|
messageId,
|
||||||
mailCredentialIdHash: Buffer.from(mailCredentialId).toString('base64').slice(0, 12),
|
attachmentsCount: message.attachments.length,
|
||||||
});
|
|
||||||
|
|
||||||
// Fetch attachments separately - don't use $select as it may cause issues
|
|
||||||
// Microsoft Graph API will return all attachment properties by default
|
|
||||||
const attachmentsResponse = await client.get(`/me/messages/${messageId}/attachments`);
|
|
||||||
|
|
||||||
const attachments = attachmentsResponse.data.value || [];
|
|
||||||
|
|
||||||
logger.debug('Fetched attachments from Graph API', {
|
|
||||||
messageId,
|
|
||||||
attachmentsCount: attachments.length,
|
|
||||||
mailCredentialIdHash: Buffer.from(mailCredentialId).toString('base64').slice(0, 12),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Process attachments - fetch content if not included
|
// Process attachments - fetch content if not included
|
||||||
if (attachments.length > 0) {
|
const attachmentsWithContent = await Promise.all(
|
||||||
const attachmentsWithContent = await Promise.all(
|
message.attachments.map(async (attachment: any) => {
|
||||||
attachments.map(async (attachment: any) => {
|
// If contentBytes is missing, fetch the attachment content
|
||||||
// If contentBytes is missing, fetch the attachment content
|
if (!attachment.contentBytes && attachment.id) {
|
||||||
if (!attachment.contentBytes && attachment.id) {
|
try {
|
||||||
try {
|
logger.debug('Fetching attachment content from Graph API', {
|
||||||
logger.debug('Fetching attachment content from Graph API', {
|
messageId,
|
||||||
messageId,
|
attachmentId: attachment.id,
|
||||||
attachmentId: attachment.id,
|
attachmentName: attachment.name,
|
||||||
attachmentName: attachment.name,
|
});
|
||||||
});
|
|
||||||
|
const attachmentData = await fetchGraphAttachment(mailCredentialId, messageId, attachment.id);
|
||||||
const attachmentData = await fetchGraphAttachment(mailCredentialId, messageId, attachment.id);
|
return {
|
||||||
return {
|
...attachment,
|
||||||
...attachment,
|
contentBytes: attachmentData.contentBytes,
|
||||||
contentBytes: attachmentData.contentBytes,
|
};
|
||||||
};
|
} catch (error) {
|
||||||
} catch (error) {
|
logger.error('Error fetching attachment content', {
|
||||||
logger.error('Error fetching attachment content', {
|
messageId,
|
||||||
messageId,
|
attachmentId: attachment.id,
|
||||||
attachmentId: attachment.id,
|
error: error instanceof Error ? error.message : String(error),
|
||||||
error: error instanceof Error ? error.message : String(error),
|
});
|
||||||
});
|
// Return attachment without content if fetch fails
|
||||||
// Return attachment without content if fetch fails
|
return attachment;
|
||||||
return attachment;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Already has contentBytes, return as-is
|
}
|
||||||
return attachment;
|
// Already has contentBytes, return as-is
|
||||||
})
|
return attachment;
|
||||||
);
|
})
|
||||||
|
);
|
||||||
message.attachments = attachmentsWithContent;
|
|
||||||
} else {
|
message.attachments = attachmentsWithContent;
|
||||||
logger.warn('Email has hasAttachments=true but no attachments returned', {
|
} else {
|
||||||
|
// Attachments not in initial response, fetch them separately
|
||||||
|
try {
|
||||||
|
logger.debug('Fetching attachments list from Graph API', {
|
||||||
messageId,
|
messageId,
|
||||||
mailCredentialIdHash: Buffer.from(mailCredentialId).toString('base64').slice(0, 12),
|
mailCredentialIdHash: Buffer.from(mailCredentialId).toString('base64').slice(0, 12),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Fetch attachments separately - don't use $select as it may cause issues
|
||||||
|
// Microsoft Graph API will return all attachment properties by default
|
||||||
|
const attachmentsResponse = await client.get(`/me/messages/${messageId}/attachments`);
|
||||||
|
|
||||||
|
const attachments = attachmentsResponse.data.value || [];
|
||||||
|
|
||||||
|
logger.debug('Fetched attachments from Graph API', {
|
||||||
|
messageId,
|
||||||
|
attachmentsCount: attachments.length,
|
||||||
|
mailCredentialIdHash: Buffer.from(mailCredentialId).toString('base64').slice(0, 12),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Process attachments - fetch content if not included
|
||||||
|
if (attachments.length > 0) {
|
||||||
|
const attachmentsWithContent = await Promise.all(
|
||||||
|
attachments.map(async (attachment: any) => {
|
||||||
|
// If contentBytes is missing, fetch the attachment content
|
||||||
|
if (!attachment.contentBytes && attachment.id) {
|
||||||
|
try {
|
||||||
|
logger.debug('Fetching attachment content from Graph API', {
|
||||||
|
messageId,
|
||||||
|
attachmentId: attachment.id,
|
||||||
|
attachmentName: attachment.name,
|
||||||
|
});
|
||||||
|
|
||||||
|
const attachmentData = await fetchGraphAttachment(mailCredentialId, messageId, attachment.id);
|
||||||
|
return {
|
||||||
|
...attachment,
|
||||||
|
contentBytes: attachmentData.contentBytes,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Error fetching attachment content', {
|
||||||
|
messageId,
|
||||||
|
attachmentId: attachment.id,
|
||||||
|
error: error instanceof Error ? error.message : String(error),
|
||||||
|
});
|
||||||
|
// Return attachment without content if fetch fails
|
||||||
|
return attachment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Already has contentBytes, return as-is
|
||||||
|
return attachment;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
message.attachments = attachmentsWithContent;
|
||||||
|
} else {
|
||||||
|
logger.warn('Email has hasAttachments=true but no attachments returned', {
|
||||||
|
messageId,
|
||||||
|
mailCredentialIdHash: Buffer.from(mailCredentialId).toString('base64').slice(0, 12),
|
||||||
|
});
|
||||||
|
message.attachments = [];
|
||||||
|
}
|
||||||
|
} catch (attachmentsError: any) {
|
||||||
|
logger.error('Error fetching attachments from Graph API', {
|
||||||
|
messageId,
|
||||||
|
error: attachmentsError instanceof Error ? attachmentsError.message : String(attachmentsError),
|
||||||
|
status: attachmentsError.response?.status,
|
||||||
|
statusText: attachmentsError.response?.statusText,
|
||||||
|
responseData: attachmentsError.response?.data,
|
||||||
|
url: `/me/messages/${messageId}/attachments`,
|
||||||
|
});
|
||||||
|
// Continue without attachments if fetch fails
|
||||||
message.attachments = [];
|
message.attachments = [];
|
||||||
}
|
}
|
||||||
} catch (attachmentsError: any) {
|
|
||||||
logger.error('Error fetching attachments from Graph API', {
|
|
||||||
messageId,
|
|
||||||
error: attachmentsError instanceof Error ? attachmentsError.message : String(attachmentsError),
|
|
||||||
status: attachmentsError.response?.status,
|
|
||||||
statusText: attachmentsError.response?.statusText,
|
|
||||||
responseData: attachmentsError.response?.data,
|
|
||||||
url: `/me/messages/${messageId}/attachments`,
|
|
||||||
});
|
|
||||||
// Continue without attachments if fetch fails
|
|
||||||
message.attachments = [];
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
message.attachments = [];
|
message.attachments = [];
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user