diff --git a/app/[locale]/page.tsx b/app/[locale]/page.tsx index 74fa0bc1..4786426b 100644 --- a/app/[locale]/page.tsx +++ b/app/[locale]/page.tsx @@ -1504,6 +1504,43 @@ export default function Home() { } }; + const handleImportEmailFromContextMenu = (mailboxId: string) => { + if (!client) return; + const mailbox = mailboxes.find(mb => mb.id === mailboxId); + if (!mailbox) return; + const targetMailboxId = mailbox.originalId || mailbox.id; + + const input = document.createElement('input'); + input.type = 'file'; + input.accept = '.eml,message/rfc822'; + input.multiple = true; + input.onchange = async (e) => { + const files = Array.from((e.target as HTMLInputElement).files ?? []); + if (files.length === 0) return; + + let imported = 0; + let failed = 0; + for (const file of files) { + try { + const blob = new Blob([await file.arrayBuffer()], { type: 'message/rfc822' }); + await client.importRawEmail(blob, { [targetMailboxId]: true }, { '$seen': true }); + imported++; + } catch { + failed++; + } + } + + if (imported > 0) { + toast.success(t('notifications.import_email_success')); + if (selectedMailbox) await fetchEmails(client, selectedMailbox); + } + if (failed > 0) { + toast.error(t('notifications.import_email_error')); + } + }; + input.click(); + }; + const handleRefreshMailboxes = async () => { if (!client) return; try { @@ -1894,6 +1931,7 @@ export default function Home() { onCreateFolder={handleCreateFolderFromContextMenu} onRenameFolder={handleRenameFolderFromContextMenu} onDeleteFolder={handleDeleteFolderFromContextMenu} + onImportEmail={handleImportEmailFromContextMenu} onRefreshMailboxes={handleRefreshMailboxes} onCompose={() => { setComposerMode('compose'); diff --git a/components/layout/mailbox-context-menu.tsx b/components/layout/mailbox-context-menu.tsx index 0f497d96..5807d085 100644 --- a/components/layout/mailbox-context-menu.tsx +++ b/components/layout/mailbox-context-menu.tsx @@ -20,6 +20,7 @@ import { Pencil, FolderX, RefreshCw, + Upload, } from "lucide-react"; interface Position { @@ -84,6 +85,7 @@ interface MailboxContextMenuProps { onCreateFolder?: () => void; onRenameFolder?: (mailboxId: string) => void; onDeleteFolder?: (mailboxId: string) => void; + onImportEmail?: (mailboxId: string) => void; onRefresh?: () => void; } @@ -102,6 +104,7 @@ export function MailboxContextMenu({ onCreateFolder, onRenameFolder, onDeleteFolder, + onImportEmail, onRefresh, }: MailboxContextMenuProps) { const t = useTranslations("mailbox_context_menu"); @@ -149,6 +152,7 @@ export function MailboxContextMenu({ const canCreateChild = mailbox.myRights?.mayCreateChild !== false; const canSetSeen = mailbox.myRights?.maySetSeen !== false; const canRemoveItems = mailbox.myRights?.mayRemoveItems !== false; + const canAddItems = mailbox.myRights?.mayAddItems !== false; const fullPath = getMailboxPath(mailbox, mailboxes); @@ -190,6 +194,15 @@ export function MailboxContextMenu({ + handleAction(() => onImportEmail?.(mailbox.id))} + disabled={!onImportEmail || !canAddItems} + /> + + + void; onRenameFolder?: (mailboxId: string) => void; onDeleteFolder?: (mailboxId: string) => void; + onImportEmail?: (mailboxId: string) => void; onRefreshMailboxes?: () => void; className?: string; } @@ -636,6 +637,7 @@ export function Sidebar({ onCreateFolder, onRenameFolder, onDeleteFolder, + onImportEmail, onRefreshMailboxes, className, }: SidebarProps) { @@ -1037,6 +1039,7 @@ export function Sidebar({ onCreateFolder={onCreateFolder} onRenameFolder={onRenameFolder} onDeleteFolder={onDeleteFolder} + onImportEmail={onImportEmail} onRefresh={onRefreshMailboxes} /> diff --git a/locales/en/common.json b/locales/en/common.json index 8d6cd951..2aeef7dd 100644 --- a/locales/en/common.json +++ b/locales/en/common.json @@ -1684,6 +1684,7 @@ "new_subfolder": "New subfolder...", "new_folder": "New folder...", "rename": "Rename...", + "import_email": "Import .eml...", "empty_folder": "Empty folder", "empty_folder_generic": "Empty folder", "delete_folder": "Delete folder",