diff --git a/app/api/mail/send/route.ts b/app/api/mail/send/route.ts index 71f816d..a068aa5 100644 --- a/app/api/mail/send/route.ts +++ b/app/api/mail/send/route.ts @@ -9,6 +9,9 @@ interface StoredCredentials { port: number; } +// Maximum attachment size in bytes (10MB) +const MAX_ATTACHMENT_SIZE = 10 * 1024 * 1024; + function getStoredCredentials(): StoredCredentials | null { const cookieStore = cookies(); const credentialsCookie = cookieStore.get('imap_credentials'); @@ -40,6 +43,28 @@ export async function POST(request: Request) { const { to, cc, bcc, subject, body, attachments } = await request.json(); + // Check attachment sizes + if (attachments?.length) { + const oversizedAttachments = attachments.filter((attachment: any) => { + // Calculate size from base64 content + const size = Math.ceil((attachment.content.length * 3) / 4); + return size > MAX_ATTACHMENT_SIZE; + }); + + if (oversizedAttachments.length > 0) { + return NextResponse.json( + { + error: 'Attachment size limit exceeded', + details: { + maxSize: MAX_ATTACHMENT_SIZE, + oversizedFiles: oversizedAttachments.map((a: any) => a.name) + } + }, + { status: 400 } + ); + } + } + // Create a transporter using SMTP with the same credentials // Use port 465 for SMTP (Infomaniak's SMTP port) const transporter = createTransport({ diff --git a/app/mail/page.tsx b/app/mail/page.tsx index 9b6d1b8..edd3c48 100644 --- a/app/mail/page.tsx +++ b/app/mail/page.tsx @@ -1184,8 +1184,15 @@ export default function MailPage() { if (!e.target.files) return; const newAttachments: Attachment[] = []; + const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB in bytes + const oversizedFiles: string[] = []; for (const file of e.target.files) { + if (file.size > MAX_FILE_SIZE) { + oversizedFiles.push(file.name); + continue; + } + try { // Read file as base64 const base64Content = await new Promise((resolve) => { @@ -1208,7 +1215,13 @@ export default function MailPage() { } } - setAttachments([...attachments, ...newAttachments]); + if (oversizedFiles.length > 0) { + alert(`The following files exceed the 10MB size limit and were not attached:\n${oversizedFiles.join('\n')}`); + } + + if (newAttachments.length > 0) { + setAttachments([...attachments, ...newAttachments]); + } }; // Add handleSend function for email composition @@ -1230,27 +1243,29 @@ export default function MailPage() { bcc: composeBcc, subject: composeSubject, body: composeBody, - attachments: attachments + attachments: attachments, }), }); + const data = await response.json(); + if (!response.ok) { - throw new Error('Failed to send email'); + if (data.error === 'Attachment size limit exceeded') { + alert(`Error: ${data.error}\nThe following files are too large:\n${data.details.oversizedFiles.join('\n')}`); + } else { + alert(`Error sending email: ${data.error}`); + } + return; } // Clear compose form and close modal - setShowCompose(false); setComposeTo(''); setComposeCc(''); setComposeBcc(''); setComposeSubject(''); setComposeBody(''); setAttachments([]); - setShowCc(false); - setShowBcc(false); - - // Reload emails to show sent email - loadEmails(); + setShowCompose(false); } catch (error) { console.error('Error sending email:', error); alert('Failed to send email. Please try again.'); @@ -1347,7 +1362,7 @@ export default function MailPage() { .replace(/]*>/gi, '\n') .replace(/<\/p>/gi, '') .replace(/<[^>]+>/g, '') - .replace(/ |‌|»|«|>|<|&/g, match => { + .replace(/ |‌|»|«|>/g, match => { switch (match) { case ' ': return ' '; case '‌': return '';