fix: handle attachment cleanup errors safely and surface messages

This commit is contained in:
Til Wegener
2025-08-14 08:10:58 +00:00
parent cfdfe42fb8
commit cba7e05d98
3 changed files with 48 additions and 20 deletions

View File

@@ -47,8 +47,11 @@ export class ArchivedEmailController {
return res.status(204).send();
} catch (error) {
console.error(`Delete archived email ${req.params.id} error:`, error);
if (error instanceof Error && error.message === 'Archived email not found') {
return res.status(404).json({ message: error.message });
if (error instanceof Error) {
if (error.message === 'Archived email not found') {
return res.status(404).json({ message: error.message });
}
return res.status(500).json({ message: error.message });
}
return res.status(500).json({ message: 'An internal server error occurred' });
}

View File

@@ -158,10 +158,9 @@ export class ArchivedEmailService {
const storage = new StorageService();
// Load attachments before deleting the email
let emailAttachmentsResult: { attachmentId: string; storagePath: string }[] = [];
// Load and handle attachments before deleting the email itself
if (email.hasAttachments) {
emailAttachmentsResult = await db
const emailAttachmentsResult = await db
.select({
attachmentId: attachments.id,
storagePath: attachments.storagePath,
@@ -169,24 +168,46 @@ export class ArchivedEmailService {
.from(emailAttachments)
.innerJoin(attachments, eq(emailAttachments.attachmentId, attachments.id))
.where(eq(emailAttachments.emailId, emailId));
try {
for (const attachment of emailAttachmentsResult) {
const [refCount] = await db
.select({ count: count(emailAttachments.emailId) })
.from(emailAttachments)
.where(eq(emailAttachments.attachmentId, attachment.attachmentId));
if (refCount.count === 1) {
await storage.delete(attachment.storagePath);
await db
.delete(emailAttachments)
.where(
and(
eq(emailAttachments.emailId, emailId),
eq(emailAttachments.attachmentId, attachment.attachmentId)
)
);
await db
.delete(attachments)
.where(eq(attachments.id, attachment.attachmentId));
} else {
await db
.delete(emailAttachments)
.where(
and(
eq(emailAttachments.emailId, emailId),
eq(emailAttachments.attachmentId, attachment.attachmentId)
)
);
}
}
} catch {
throw new Error('Failed to delete email attachments');
}
}
// Delete the email file from storage
await storage.delete(email.storagePath);
// Handle attachments: delete only if not referenced elsewhere
for (const attachment of emailAttachmentsResult) {
const [refCount] = await db
.select({ count: count(emailAttachments.emailId) })
.from(emailAttachments)
.where(eq(emailAttachments.attachmentId, attachment.attachmentId));
if (refCount.count === 1) {
await storage.delete(attachment.storagePath);
await db.delete(attachments).where(eq(attachments.id, attachment.attachmentId));
}
}
const searchService = new SearchService();
await searchService.deleteDocuments('emails', [emailId]);

View File

@@ -48,9 +48,13 @@
method: 'DELETE'
});
if (!response.ok) {
throw new Error('Failed to delete email');
const errorData = await response.json().catch(() => null);
const message = errorData?.message || 'Failed to delete email';
console.error('Delete failed:', message);
alert(message);
return;
}
await goto('/dashboard/archived-emails');
await goto('/dashboard/archived-emails', { invalidateAll: true });
} catch (error) {
console.error('Delete failed:', error);
} finally {