feat: support importing emails from .zip archives
This commit is contained in:
@@ -57,6 +57,7 @@ import { FilePreviewModal } from "@/components/files/file-preview-modal";
|
|||||||
import { isFilePreviewable } from "@/lib/file-preview";
|
import { isFilePreviewable } from "@/lib/file-preview";
|
||||||
import { appendPlainTextSignature } from "@/lib/signature-utils";
|
import { appendPlainTextSignature } from "@/lib/signature-utils";
|
||||||
import { computeReplyThreadingHeaders } from "@/lib/email-threading";
|
import { computeReplyThreadingHeaders } from "@/lib/email-threading";
|
||||||
|
import { EML_IMPORT_ACCEPT, expandImportableEmails } from "@/lib/eml-import";
|
||||||
import { resolveReplyFrom } from "@/lib/reply-identity";
|
import { resolveReplyFrom } from "@/lib/reply-identity";
|
||||||
import { Search, Filter, ChevronDown, X, Paperclip, Star, Mail, MailOpen, RotateCcw, PenSquare, PenLine, CheckSquare, Square, AlertTriangle } from "lucide-react";
|
import { Search, Filter, ChevronDown, X, Paperclip, Star, Mail, MailOpen, RotateCcw, PenSquare, PenLine, CheckSquare, Square, AlertTriangle } from "lucide-react";
|
||||||
import { ResizeHandle } from "@/components/layout/resize-handle";
|
import { ResizeHandle } from "@/components/layout/resize-handle";
|
||||||
@@ -1753,17 +1754,24 @@ export default function Home() {
|
|||||||
|
|
||||||
const input = document.createElement('input');
|
const input = document.createElement('input');
|
||||||
input.type = 'file';
|
input.type = 'file';
|
||||||
input.accept = '.eml,message/rfc822';
|
input.accept = EML_IMPORT_ACCEPT;
|
||||||
input.multiple = true;
|
input.multiple = true;
|
||||||
input.onchange = async (e) => {
|
input.onchange = async (e) => {
|
||||||
const files = Array.from((e.target as HTMLInputElement).files ?? []);
|
const files = Array.from((e.target as HTMLInputElement).files ?? []);
|
||||||
if (files.length === 0) return;
|
if (files.length === 0) return;
|
||||||
|
|
||||||
|
let emails;
|
||||||
|
try {
|
||||||
|
emails = await expandImportableEmails(files);
|
||||||
|
} catch {
|
||||||
|
toast.error(t('notifications.import_email_error'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let imported = 0;
|
let imported = 0;
|
||||||
let failed = 0;
|
let failed = 0;
|
||||||
for (const file of files) {
|
for (const { blob } of emails) {
|
||||||
try {
|
try {
|
||||||
const blob = new Blob([await file.arrayBuffer()], { type: 'message/rfc822' });
|
|
||||||
await client.importRawEmail(blob, { [targetMailboxId]: true }, { '$seen': true });
|
await client.importRawEmail(blob, { [targetMailboxId]: true }, { '$seen': true });
|
||||||
imported++;
|
imported++;
|
||||||
} catch {
|
} catch {
|
||||||
@@ -1775,7 +1783,7 @@ export default function Home() {
|
|||||||
toast.success(t('notifications.import_email_success'));
|
toast.success(t('notifications.import_email_success'));
|
||||||
if (selectedMailbox) await fetchEmails(client, selectedMailbox);
|
if (selectedMailbox) await fetchEmails(client, selectedMailbox);
|
||||||
}
|
}
|
||||||
if (failed > 0) {
|
if (failed > 0 || (imported === 0 && emails.length === 0)) {
|
||||||
toast.error(t('notifications.import_email_error'));
|
toast.error(t('notifications.import_email_error'));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { useState, useEffect, useLayoutEffect, useMemo, useRef, useCallback } fr
|
|||||||
import DOMPurify from "dompurify";
|
import DOMPurify from "dompurify";
|
||||||
import { Email, ContactCard, Mailbox } from "@/lib/jmap/types";
|
import { Email, ContactCard, Mailbox } from "@/lib/jmap/types";
|
||||||
import { emailExportFilename, attachmentDownloadFilename, DEFAULT_EMAIL_TEMPLATE, DEFAULT_ATTACHMENT_TEMPLATE } from "@/lib/download-filename";
|
import { emailExportFilename, attachmentDownloadFilename, DEFAULT_EMAIL_TEMPLATE, DEFAULT_ATTACHMENT_TEMPLATE } from "@/lib/download-filename";
|
||||||
|
import { EML_IMPORT_ACCEPT, expandImportableEmails } from "@/lib/eml-import";
|
||||||
import { EMAIL_IFRAME_SANITIZE_CONFIG, collapseBlockedImageContainers, escapeHtml, plainTextToSafeHtml, sanitizeEmailHtml, sanitizePlainTextRenderedHtml } from "@/lib/email-sanitization";
|
import { EMAIL_IFRAME_SANITIZE_CONFIG, collapseBlockedImageContainers, escapeHtml, plainTextToSafeHtml, sanitizeEmailHtml, sanitizePlainTextRenderedHtml } from "@/lib/email-sanitization";
|
||||||
import { hasMeaningfulHtmlBody } from "@/lib/signature-utils";
|
import { hasMeaningfulHtmlBody } from "@/lib/signature-utils";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
@@ -3096,28 +3097,48 @@ export function EmailViewer({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Import email from .eml file
|
// Import email from .eml file or .zip archive containing .eml files
|
||||||
const handleImportEmail = () => {
|
const handleImportEmail = () => {
|
||||||
if (!client) return;
|
if (!client) return;
|
||||||
const input = document.createElement('input');
|
const input = document.createElement('input');
|
||||||
input.type = 'file';
|
input.type = 'file';
|
||||||
input.accept = '.eml,message/rfc822';
|
input.accept = EML_IMPORT_ACCEPT;
|
||||||
|
input.multiple = true;
|
||||||
input.onchange = async (e) => {
|
input.onchange = async (e) => {
|
||||||
const file = (e.target as HTMLInputElement).files?.[0];
|
const files = Array.from((e.target as HTMLInputElement).files ?? []);
|
||||||
if (!file) return;
|
if (files.length === 0) return;
|
||||||
|
const { selectedMailbox, mailboxes, fetchEmails } = useEmailStore.getState();
|
||||||
|
const mailbox = mailboxes.find(mb => mb.id === selectedMailbox);
|
||||||
|
const mailboxId = mailbox?.originalId || selectedMailbox;
|
||||||
|
if (!mailboxId) {
|
||||||
|
toast.error(tNotifications('import_email_error'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let emails;
|
||||||
try {
|
try {
|
||||||
const { selectedMailbox, mailboxes, fetchEmails } = useEmailStore.getState();
|
emails = await expandImportableEmails(files);
|
||||||
const mailbox = mailboxes.find(mb => mb.id === selectedMailbox);
|
} catch {
|
||||||
const mailboxId = mailbox?.originalId || selectedMailbox;
|
toast.error(tNotifications('import_email_error'));
|
||||||
if (!mailboxId) {
|
return;
|
||||||
toast.error(tNotifications('import_email_error'));
|
}
|
||||||
return;
|
|
||||||
|
let imported = 0;
|
||||||
|
let failed = 0;
|
||||||
|
for (const { blob } of emails) {
|
||||||
|
try {
|
||||||
|
await client.importRawEmail(blob, { [mailboxId]: true }, { '$seen': true });
|
||||||
|
imported++;
|
||||||
|
} catch {
|
||||||
|
failed++;
|
||||||
}
|
}
|
||||||
const blob = new Blob([await file.arrayBuffer()], { type: 'message/rfc822' });
|
}
|
||||||
await client.importRawEmail(blob, { [mailboxId]: true }, { '$seen': true });
|
|
||||||
|
if (imported > 0) {
|
||||||
toast.success(tNotifications('import_email_success'));
|
toast.success(tNotifications('import_email_success'));
|
||||||
await fetchEmails(client);
|
await fetchEmails(client);
|
||||||
} catch {
|
}
|
||||||
|
if (failed > 0 || emails.length === 0) {
|
||||||
toast.error(tNotifications('import_email_error'));
|
toast.error(tNotifications('import_email_error'));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
export interface ImportableEmail {
|
||||||
|
name: string;
|
||||||
|
blob: Blob;
|
||||||
|
}
|
||||||
|
|
||||||
|
const EMAIL_MIME = "message/rfc822";
|
||||||
|
|
||||||
|
function isEmlName(name: string): boolean {
|
||||||
|
return /\.eml$/i.test(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isZipName(name: string): boolean {
|
||||||
|
return /\.zip$/i.test(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function extractEmlsFromZip(file: File): Promise<ImportableEmail[]> {
|
||||||
|
const { default: JSZip } = await import("jszip");
|
||||||
|
const zip = await JSZip.loadAsync(await file.arrayBuffer());
|
||||||
|
const out: ImportableEmail[] = [];
|
||||||
|
const entries = Object.values(zip.files);
|
||||||
|
for (const entry of entries) {
|
||||||
|
if (entry.dir) continue;
|
||||||
|
if (!isEmlName(entry.name)) continue;
|
||||||
|
const data = await entry.async("arraybuffer");
|
||||||
|
out.push({
|
||||||
|
name: entry.name.split(/[\\/]/).pop() || entry.name,
|
||||||
|
blob: new Blob([data], { type: EMAIL_MIME }),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function expandImportableEmails(
|
||||||
|
files: File[],
|
||||||
|
): Promise<ImportableEmail[]> {
|
||||||
|
const out: ImportableEmail[] = [];
|
||||||
|
for (const file of files) {
|
||||||
|
if (isZipName(file.name) || file.type === "application/zip") {
|
||||||
|
out.push(...(await extractEmlsFromZip(file)));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const blob = new Blob([await file.arrayBuffer()], { type: EMAIL_MIME });
|
||||||
|
out.push({ name: file.name, blob });
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const EML_IMPORT_ACCEPT = ".eml,.zip,message/rfc822,application/zip";
|
||||||
@@ -270,7 +270,7 @@
|
|||||||
"print": "Tisk",
|
"print": "Tisk",
|
||||||
"view_source": "Zobrazit zdrojový kód",
|
"view_source": "Zobrazit zdrojový kód",
|
||||||
"export_email": "Exportovat jako .eml",
|
"export_email": "Exportovat jako .eml",
|
||||||
"import_email": "Importovat .eml",
|
"import_email": "Importovat .eml nebo .zip",
|
||||||
"keyboard_shortcuts": "Klávesové zkratky (?)",
|
"keyboard_shortcuts": "Klávesové zkratky (?)",
|
||||||
"email_source": "Zdrojový kód zprávy",
|
"email_source": "Zdrojový kód zprávy",
|
||||||
"draft_banner": "Tato zpráva je koncept",
|
"draft_banner": "Tato zpráva je koncept",
|
||||||
@@ -1794,7 +1794,7 @@
|
|||||||
"new_subfolder": "Nová podsložka...",
|
"new_subfolder": "Nová podsložka...",
|
||||||
"new_folder": "Nová složka...",
|
"new_folder": "Nová složka...",
|
||||||
"rename": "Přejmenovat...",
|
"rename": "Přejmenovat...",
|
||||||
"import_email": "Importovat .eml...",
|
"import_email": "Importovat .eml nebo .zip...",
|
||||||
"empty_folder": "Vyprázdnit složku",
|
"empty_folder": "Vyprázdnit složku",
|
||||||
"empty_folder_generic": "Vyprázdnit složku",
|
"empty_folder_generic": "Vyprázdnit složku",
|
||||||
"delete_folder": "Smazat složku",
|
"delete_folder": "Smazat složku",
|
||||||
|
|||||||
@@ -270,7 +270,7 @@
|
|||||||
"print": "Udskriv",
|
"print": "Udskriv",
|
||||||
"view_source": "Vis kilde",
|
"view_source": "Vis kilde",
|
||||||
"export_email": "Eksportér som .eml",
|
"export_email": "Eksportér som .eml",
|
||||||
"import_email": "Importér .eml",
|
"import_email": "Importér .eml eller .zip",
|
||||||
"keyboard_shortcuts": "Tastaturgenveje (?)",
|
"keyboard_shortcuts": "Tastaturgenveje (?)",
|
||||||
"email_source": "E-mail-kilde",
|
"email_source": "E-mail-kilde",
|
||||||
"draft_banner": "Denne besked er en kladde",
|
"draft_banner": "Denne besked er en kladde",
|
||||||
@@ -1794,7 +1794,7 @@
|
|||||||
"new_subfolder": "Ny undermappe...",
|
"new_subfolder": "Ny undermappe...",
|
||||||
"new_folder": "Ny mappe...",
|
"new_folder": "Ny mappe...",
|
||||||
"rename": "Omdøb...",
|
"rename": "Omdøb...",
|
||||||
"import_email": "Importér .eml...",
|
"import_email": "Importér .eml eller .zip...",
|
||||||
"empty_folder": "Tøm mappe",
|
"empty_folder": "Tøm mappe",
|
||||||
"empty_folder_generic": "Tøm mappe",
|
"empty_folder_generic": "Tøm mappe",
|
||||||
"delete_folder": "Slet mappe",
|
"delete_folder": "Slet mappe",
|
||||||
|
|||||||
@@ -270,7 +270,7 @@
|
|||||||
"print": "Drucken",
|
"print": "Drucken",
|
||||||
"view_source": "Quelltext anzeigen",
|
"view_source": "Quelltext anzeigen",
|
||||||
"export_email": "Als .eml exportieren",
|
"export_email": "Als .eml exportieren",
|
||||||
"import_email": ".eml importieren",
|
"import_email": ".eml oder .zip importieren",
|
||||||
"keyboard_shortcuts": "Tastaturkürzel (?)",
|
"keyboard_shortcuts": "Tastaturkürzel (?)",
|
||||||
"email_source": "E-Mail-Quelltext",
|
"email_source": "E-Mail-Quelltext",
|
||||||
"draft_banner": "Diese Nachricht ist ein Entwurf",
|
"draft_banner": "Diese Nachricht ist ein Entwurf",
|
||||||
@@ -1794,7 +1794,7 @@
|
|||||||
"new_subfolder": "Neuer Unterordner...",
|
"new_subfolder": "Neuer Unterordner...",
|
||||||
"new_folder": "Neuer Ordner...",
|
"new_folder": "Neuer Ordner...",
|
||||||
"rename": "Umbenennen...",
|
"rename": "Umbenennen...",
|
||||||
"import_email": ".eml importieren...",
|
"import_email": ".eml oder .zip importieren...",
|
||||||
"empty_folder": "Ordner leeren",
|
"empty_folder": "Ordner leeren",
|
||||||
"empty_folder_generic": "Ordner leeren",
|
"empty_folder_generic": "Ordner leeren",
|
||||||
"delete_folder": "Ordner löschen",
|
"delete_folder": "Ordner löschen",
|
||||||
|
|||||||
@@ -270,7 +270,7 @@
|
|||||||
"print": "Print",
|
"print": "Print",
|
||||||
"view_source": "View source",
|
"view_source": "View source",
|
||||||
"export_email": "Export as .eml",
|
"export_email": "Export as .eml",
|
||||||
"import_email": "Import .eml",
|
"import_email": "Import .eml or .zip",
|
||||||
"keyboard_shortcuts": "Keyboard shortcuts (?)",
|
"keyboard_shortcuts": "Keyboard shortcuts (?)",
|
||||||
"email_source": "Email Source",
|
"email_source": "Email Source",
|
||||||
"draft_banner": "This message is a draft",
|
"draft_banner": "This message is a draft",
|
||||||
@@ -1794,7 +1794,7 @@
|
|||||||
"new_subfolder": "New subfolder...",
|
"new_subfolder": "New subfolder...",
|
||||||
"new_folder": "New folder...",
|
"new_folder": "New folder...",
|
||||||
"rename": "Rename...",
|
"rename": "Rename...",
|
||||||
"import_email": "Import .eml...",
|
"import_email": "Import .eml or .zip...",
|
||||||
"empty_folder": "Empty folder",
|
"empty_folder": "Empty folder",
|
||||||
"empty_folder_generic": "Empty folder",
|
"empty_folder_generic": "Empty folder",
|
||||||
"delete_folder": "Delete folder",
|
"delete_folder": "Delete folder",
|
||||||
|
|||||||
@@ -270,7 +270,7 @@
|
|||||||
"print": "Imprimir",
|
"print": "Imprimir",
|
||||||
"view_source": "Ver código fuente",
|
"view_source": "Ver código fuente",
|
||||||
"export_email": "Exportar como .eml",
|
"export_email": "Exportar como .eml",
|
||||||
"import_email": "Importar .eml",
|
"import_email": "Importar .eml o .zip",
|
||||||
"keyboard_shortcuts": "Atajos de teclado (?)",
|
"keyboard_shortcuts": "Atajos de teclado (?)",
|
||||||
"email_source": "Código Fuente del Correo",
|
"email_source": "Código Fuente del Correo",
|
||||||
"draft_banner": "Este mensaje es un borrador",
|
"draft_banner": "Este mensaje es un borrador",
|
||||||
@@ -1794,7 +1794,7 @@
|
|||||||
"new_subfolder": "Nueva subcarpeta...",
|
"new_subfolder": "Nueva subcarpeta...",
|
||||||
"new_folder": "Nueva carpeta...",
|
"new_folder": "Nueva carpeta...",
|
||||||
"rename": "Renombrar...",
|
"rename": "Renombrar...",
|
||||||
"import_email": "Importar .eml...",
|
"import_email": "Importar .eml o .zip...",
|
||||||
"empty_folder": "Vaciar carpeta",
|
"empty_folder": "Vaciar carpeta",
|
||||||
"empty_folder_generic": "Vaciar carpeta",
|
"empty_folder_generic": "Vaciar carpeta",
|
||||||
"delete_folder": "Eliminar carpeta",
|
"delete_folder": "Eliminar carpeta",
|
||||||
|
|||||||
@@ -270,7 +270,7 @@
|
|||||||
"print": "Imprimer",
|
"print": "Imprimer",
|
||||||
"view_source": "Voir la source",
|
"view_source": "Voir la source",
|
||||||
"export_email": "Exporter en .eml",
|
"export_email": "Exporter en .eml",
|
||||||
"import_email": "Importer un .eml",
|
"import_email": "Importer .eml ou .zip",
|
||||||
"keyboard_shortcuts": "Raccourcis clavier (?)",
|
"keyboard_shortcuts": "Raccourcis clavier (?)",
|
||||||
"email_source": "Source de l'email",
|
"email_source": "Source de l'email",
|
||||||
"draft_banner": "Ce message est un brouillon",
|
"draft_banner": "Ce message est un brouillon",
|
||||||
@@ -1794,7 +1794,7 @@
|
|||||||
"new_subfolder": "Nouveau sous-dossier...",
|
"new_subfolder": "Nouveau sous-dossier...",
|
||||||
"new_folder": "Nouveau dossier...",
|
"new_folder": "Nouveau dossier...",
|
||||||
"rename": "Renommer...",
|
"rename": "Renommer...",
|
||||||
"import_email": "Importer un .eml...",
|
"import_email": "Importer .eml ou .zip...",
|
||||||
"empty_folder": "Vider le dossier",
|
"empty_folder": "Vider le dossier",
|
||||||
"empty_folder_generic": "Vider le dossier",
|
"empty_folder_generic": "Vider le dossier",
|
||||||
"delete_folder": "Supprimer le dossier",
|
"delete_folder": "Supprimer le dossier",
|
||||||
|
|||||||
@@ -270,7 +270,7 @@
|
|||||||
"print": "Stampa",
|
"print": "Stampa",
|
||||||
"view_source": "Visualizza sorgente",
|
"view_source": "Visualizza sorgente",
|
||||||
"export_email": "Esporta come .eml",
|
"export_email": "Esporta come .eml",
|
||||||
"import_email": "Importa .eml",
|
"import_email": "Importa .eml o .zip",
|
||||||
"keyboard_shortcuts": "Scorciatoie da tastiera (?)",
|
"keyboard_shortcuts": "Scorciatoie da tastiera (?)",
|
||||||
"email_source": "Sorgente del messaggio",
|
"email_source": "Sorgente del messaggio",
|
||||||
"draft_banner": "Questo messaggio è una bozza",
|
"draft_banner": "Questo messaggio è una bozza",
|
||||||
@@ -1794,7 +1794,7 @@
|
|||||||
"new_subfolder": "Nuova sottocartella...",
|
"new_subfolder": "Nuova sottocartella...",
|
||||||
"new_folder": "Nuova cartella...",
|
"new_folder": "Nuova cartella...",
|
||||||
"rename": "Rinomina...",
|
"rename": "Rinomina...",
|
||||||
"import_email": "Importa .eml...",
|
"import_email": "Importa .eml o .zip...",
|
||||||
"empty_folder": "Svuota cartella",
|
"empty_folder": "Svuota cartella",
|
||||||
"empty_folder_generic": "Svuota cartella",
|
"empty_folder_generic": "Svuota cartella",
|
||||||
"delete_folder": "Elimina cartella",
|
"delete_folder": "Elimina cartella",
|
||||||
|
|||||||
@@ -270,7 +270,7 @@
|
|||||||
"print": "印刷",
|
"print": "印刷",
|
||||||
"view_source": "ソースを表示",
|
"view_source": "ソースを表示",
|
||||||
"export_email": ".emlとしてエクスポート",
|
"export_email": ".emlとしてエクスポート",
|
||||||
"import_email": ".emlをインポート",
|
"import_email": ".eml または .zip をインポート",
|
||||||
"keyboard_shortcuts": "キーボードショートカット (?)",
|
"keyboard_shortcuts": "キーボードショートカット (?)",
|
||||||
"email_source": "メールソース",
|
"email_source": "メールソース",
|
||||||
"draft_banner": "このメッセージは下書きです",
|
"draft_banner": "このメッセージは下書きです",
|
||||||
@@ -1794,7 +1794,7 @@
|
|||||||
"new_subfolder": "新しいサブフォルダー...",
|
"new_subfolder": "新しいサブフォルダー...",
|
||||||
"new_folder": "新しいフォルダー...",
|
"new_folder": "新しいフォルダー...",
|
||||||
"rename": "名前を変更...",
|
"rename": "名前を変更...",
|
||||||
"import_email": ".eml をインポート...",
|
"import_email": ".eml または .zip をインポート...",
|
||||||
"empty_folder": "フォルダーを空にする",
|
"empty_folder": "フォルダーを空にする",
|
||||||
"empty_folder_generic": "フォルダーを空にする",
|
"empty_folder_generic": "フォルダーを空にする",
|
||||||
"delete_folder": "フォルダーを削除",
|
"delete_folder": "フォルダーを削除",
|
||||||
|
|||||||
@@ -270,7 +270,7 @@
|
|||||||
"print": "인쇄",
|
"print": "인쇄",
|
||||||
"view_source": "원본 보기",
|
"view_source": "원본 보기",
|
||||||
"export_email": ".eml 파일로 내보내기",
|
"export_email": ".eml 파일로 내보내기",
|
||||||
"import_email": ".eml 파일 가져오기",
|
"import_email": ".eml 또는 .zip 가져오기",
|
||||||
"keyboard_shortcuts": "단축키 (?)",
|
"keyboard_shortcuts": "단축키 (?)",
|
||||||
"email_source": "메일 원본",
|
"email_source": "메일 원본",
|
||||||
"draft_banner": "작성 중인 임시보관 메일이에요",
|
"draft_banner": "작성 중인 임시보관 메일이에요",
|
||||||
@@ -1794,7 +1794,7 @@
|
|||||||
"new_subfolder": "새 하위 폴더...",
|
"new_subfolder": "새 하위 폴더...",
|
||||||
"new_folder": "새 폴더...",
|
"new_folder": "새 폴더...",
|
||||||
"rename": "이름 바꾸기...",
|
"rename": "이름 바꾸기...",
|
||||||
"import_email": ".eml 가져오기...",
|
"import_email": ".eml 또는 .zip 가져오기...",
|
||||||
"empty_folder": "폴더 비우기",
|
"empty_folder": "폴더 비우기",
|
||||||
"empty_folder_generic": "폴더 비우기",
|
"empty_folder_generic": "폴더 비우기",
|
||||||
"delete_folder": "폴더 삭제",
|
"delete_folder": "폴더 삭제",
|
||||||
|
|||||||
@@ -270,7 +270,7 @@
|
|||||||
"print": "Drukāt",
|
"print": "Drukāt",
|
||||||
"view_source": "Skatīt avota kodu",
|
"view_source": "Skatīt avota kodu",
|
||||||
"export_email": "Eksportēt kā .eml",
|
"export_email": "Eksportēt kā .eml",
|
||||||
"import_email": "Importēt .eml",
|
"import_email": "Importēt .eml vai .zip",
|
||||||
"keyboard_shortcuts": "Īsinājumtaustiņi (?)",
|
"keyboard_shortcuts": "Īsinājumtaustiņi (?)",
|
||||||
"email_source": "Vēstules avota kods",
|
"email_source": "Vēstules avota kods",
|
||||||
"draft_banner": "Šī vēstule ir melnraksts",
|
"draft_banner": "Šī vēstule ir melnraksts",
|
||||||
@@ -1794,7 +1794,7 @@
|
|||||||
"new_subfolder": "Jauna apakšmape...",
|
"new_subfolder": "Jauna apakšmape...",
|
||||||
"new_folder": "Jauna mape...",
|
"new_folder": "Jauna mape...",
|
||||||
"rename": "Pārsaukt...",
|
"rename": "Pārsaukt...",
|
||||||
"import_email": "Importēt .eml...",
|
"import_email": "Importēt .eml vai .zip...",
|
||||||
"empty_folder": "Iztukšot mapi",
|
"empty_folder": "Iztukšot mapi",
|
||||||
"empty_folder_generic": "Iztukšot mapi",
|
"empty_folder_generic": "Iztukšot mapi",
|
||||||
"delete_folder": "Dzēst mapi",
|
"delete_folder": "Dzēst mapi",
|
||||||
|
|||||||
@@ -270,7 +270,7 @@
|
|||||||
"print": "Afdrukken",
|
"print": "Afdrukken",
|
||||||
"view_source": "Bron bekijken",
|
"view_source": "Bron bekijken",
|
||||||
"export_email": "Exporteren als .eml",
|
"export_email": "Exporteren als .eml",
|
||||||
"import_email": ".eml importeren",
|
"import_email": ".eml of .zip importeren",
|
||||||
"keyboard_shortcuts": "Sneltoetsen (?)",
|
"keyboard_shortcuts": "Sneltoetsen (?)",
|
||||||
"email_source": "E-mailbron",
|
"email_source": "E-mailbron",
|
||||||
"draft_banner": "Dit bericht is een concept",
|
"draft_banner": "Dit bericht is een concept",
|
||||||
@@ -1794,7 +1794,7 @@
|
|||||||
"new_subfolder": "Nieuwe submap...",
|
"new_subfolder": "Nieuwe submap...",
|
||||||
"new_folder": "Nieuwe map...",
|
"new_folder": "Nieuwe map...",
|
||||||
"rename": "Hernoemen...",
|
"rename": "Hernoemen...",
|
||||||
"import_email": ".eml importeren...",
|
"import_email": ".eml of .zip importeren...",
|
||||||
"empty_folder": "Map leegmaken",
|
"empty_folder": "Map leegmaken",
|
||||||
"empty_folder_generic": "Map leegmaken",
|
"empty_folder_generic": "Map leegmaken",
|
||||||
"delete_folder": "Map verwijderen",
|
"delete_folder": "Map verwijderen",
|
||||||
|
|||||||
@@ -270,7 +270,7 @@
|
|||||||
"print": "Drukuj",
|
"print": "Drukuj",
|
||||||
"view_source": "Pokaż źródło",
|
"view_source": "Pokaż źródło",
|
||||||
"export_email": "Eksportuj jako .eml",
|
"export_email": "Eksportuj jako .eml",
|
||||||
"import_email": "Importuj .eml",
|
"import_email": "Importuj .eml lub .zip",
|
||||||
"keyboard_shortcuts": "Skróty klawiszowe (?)",
|
"keyboard_shortcuts": "Skróty klawiszowe (?)",
|
||||||
"email_source": "Źródło wiadomości",
|
"email_source": "Źródło wiadomości",
|
||||||
"draft_banner": "Ta wiadomość jest szkicem",
|
"draft_banner": "Ta wiadomość jest szkicem",
|
||||||
@@ -1794,7 +1794,7 @@
|
|||||||
"new_subfolder": "Nowy podfolder...",
|
"new_subfolder": "Nowy podfolder...",
|
||||||
"new_folder": "Nowy folder...",
|
"new_folder": "Nowy folder...",
|
||||||
"rename": "Zmień nazwę...",
|
"rename": "Zmień nazwę...",
|
||||||
"import_email": "Importuj .eml...",
|
"import_email": "Importuj .eml lub .zip...",
|
||||||
"empty_folder": "Opróżnij folder",
|
"empty_folder": "Opróżnij folder",
|
||||||
"empty_folder_generic": "Opróżnij folder",
|
"empty_folder_generic": "Opróżnij folder",
|
||||||
"delete_folder": "Usuń folder",
|
"delete_folder": "Usuń folder",
|
||||||
|
|||||||
@@ -270,7 +270,7 @@
|
|||||||
"print": "Imprimir",
|
"print": "Imprimir",
|
||||||
"view_source": "Ver código-fonte",
|
"view_source": "Ver código-fonte",
|
||||||
"export_email": "Exportar como .eml",
|
"export_email": "Exportar como .eml",
|
||||||
"import_email": "Importar .eml",
|
"import_email": "Importar .eml ou .zip",
|
||||||
"keyboard_shortcuts": "Atalhos de teclado (?)",
|
"keyboard_shortcuts": "Atalhos de teclado (?)",
|
||||||
"email_source": "Código-fonte do E-mail",
|
"email_source": "Código-fonte do E-mail",
|
||||||
"draft_banner": "Esta mensagem é um rascunho",
|
"draft_banner": "Esta mensagem é um rascunho",
|
||||||
@@ -1794,7 +1794,7 @@
|
|||||||
"new_subfolder": "Nova subpasta...",
|
"new_subfolder": "Nova subpasta...",
|
||||||
"new_folder": "Nova pasta...",
|
"new_folder": "Nova pasta...",
|
||||||
"rename": "Renomear...",
|
"rename": "Renomear...",
|
||||||
"import_email": "Importar .eml...",
|
"import_email": "Importar .eml ou .zip...",
|
||||||
"empty_folder": "Esvaziar pasta",
|
"empty_folder": "Esvaziar pasta",
|
||||||
"empty_folder_generic": "Esvaziar pasta",
|
"empty_folder_generic": "Esvaziar pasta",
|
||||||
"delete_folder": "Excluir pasta",
|
"delete_folder": "Excluir pasta",
|
||||||
|
|||||||
@@ -270,7 +270,7 @@
|
|||||||
"print": "Распечатать",
|
"print": "Распечатать",
|
||||||
"view_source": "Просмотреть исходный код",
|
"view_source": "Просмотреть исходный код",
|
||||||
"export_email": "Экспортировать как .eml",
|
"export_email": "Экспортировать как .eml",
|
||||||
"import_email": "Импортировать .eml",
|
"import_email": "Импортировать .eml или .zip",
|
||||||
"keyboard_shortcuts": "Сочетания клавиш (?)",
|
"keyboard_shortcuts": "Сочетания клавиш (?)",
|
||||||
"email_source": "Исходный код письма",
|
"email_source": "Исходный код письма",
|
||||||
"draft_banner": "Это письмо является черновиком",
|
"draft_banner": "Это письмо является черновиком",
|
||||||
@@ -1794,7 +1794,7 @@
|
|||||||
"new_subfolder": "Новая вложенная папка...",
|
"new_subfolder": "Новая вложенная папка...",
|
||||||
"new_folder": "Новая папка...",
|
"new_folder": "Новая папка...",
|
||||||
"rename": "Переименовать...",
|
"rename": "Переименовать...",
|
||||||
"import_email": "Импортировать .eml...",
|
"import_email": "Импортировать .eml или .zip...",
|
||||||
"empty_folder": "Очистить папку",
|
"empty_folder": "Очистить папку",
|
||||||
"empty_folder_generic": "Очистить папку",
|
"empty_folder_generic": "Очистить папку",
|
||||||
"delete_folder": "Удалить папку",
|
"delete_folder": "Удалить папку",
|
||||||
|
|||||||
@@ -270,7 +270,7 @@
|
|||||||
"print": "Yazdır",
|
"print": "Yazdır",
|
||||||
"view_source": "Kaynağı görüntüle",
|
"view_source": "Kaynağı görüntüle",
|
||||||
"export_email": ".eml olarak dışa aktar",
|
"export_email": ".eml olarak dışa aktar",
|
||||||
"import_email": ".eml içe aktar",
|
"import_email": ".eml veya .zip içe aktar",
|
||||||
"keyboard_shortcuts": "Klavye kısayolları (?)",
|
"keyboard_shortcuts": "Klavye kısayolları (?)",
|
||||||
"email_source": "E-posta Kaynağı",
|
"email_source": "E-posta Kaynağı",
|
||||||
"draft_banner": "Bu ileti bir taslaktır",
|
"draft_banner": "Bu ileti bir taslaktır",
|
||||||
@@ -1794,7 +1794,7 @@
|
|||||||
"new_subfolder": "Yeni alt klasör...",
|
"new_subfolder": "Yeni alt klasör...",
|
||||||
"new_folder": "Yeni klasör...",
|
"new_folder": "Yeni klasör...",
|
||||||
"rename": "Yeniden adlandır...",
|
"rename": "Yeniden adlandır...",
|
||||||
"import_email": ".eml içe aktar...",
|
"import_email": ".eml veya .zip içe aktar...",
|
||||||
"empty_folder": "Klasörü boşalt",
|
"empty_folder": "Klasörü boşalt",
|
||||||
"empty_folder_generic": "Klasörü boşalt",
|
"empty_folder_generic": "Klasörü boşalt",
|
||||||
"delete_folder": "Klasörü sil",
|
"delete_folder": "Klasörü sil",
|
||||||
|
|||||||
@@ -270,7 +270,7 @@
|
|||||||
"print": "Роздрукувати",
|
"print": "Роздрукувати",
|
||||||
"view_source": "Переглянути джерело",
|
"view_source": "Переглянути джерело",
|
||||||
"export_email": "Експортувати як .eml",
|
"export_email": "Експортувати як .eml",
|
||||||
"import_email": "Імпорт .eml",
|
"import_email": "Імпорт .eml або .zip",
|
||||||
"keyboard_shortcuts": "Комбінації клавіш (?)",
|
"keyboard_shortcuts": "Комбінації клавіш (?)",
|
||||||
"email_source": "Джерело електронної пошти",
|
"email_source": "Джерело електронної пошти",
|
||||||
"draft_banner": "Це повідомлення є чернеткою",
|
"draft_banner": "Це повідомлення є чернеткою",
|
||||||
@@ -1794,7 +1794,7 @@
|
|||||||
"new_subfolder": "Нова вкладена папка...",
|
"new_subfolder": "Нова вкладена папка...",
|
||||||
"new_folder": "Нова папка...",
|
"new_folder": "Нова папка...",
|
||||||
"rename": "Перейменувати...",
|
"rename": "Перейменувати...",
|
||||||
"import_email": "Імпортувати .eml...",
|
"import_email": "Імпортувати .eml або .zip...",
|
||||||
"empty_folder": "Очистити папку",
|
"empty_folder": "Очистити папку",
|
||||||
"empty_folder_generic": "Очистити папку",
|
"empty_folder_generic": "Очистити папку",
|
||||||
"delete_folder": "Видалити папку",
|
"delete_folder": "Видалити папку",
|
||||||
|
|||||||
@@ -270,7 +270,7 @@
|
|||||||
"print": "打印",
|
"print": "打印",
|
||||||
"view_source": "查看源码",
|
"view_source": "查看源码",
|
||||||
"export_email": "导出为 .eml",
|
"export_email": "导出为 .eml",
|
||||||
"import_email": "导入 .eml",
|
"import_email": "导入 .eml 或 .zip",
|
||||||
"keyboard_shortcuts": "键盘快捷键(?)",
|
"keyboard_shortcuts": "键盘快捷键(?)",
|
||||||
"email_source": "邮件源码",
|
"email_source": "邮件源码",
|
||||||
"draft_banner": "这是一封草稿邮件",
|
"draft_banner": "这是一封草稿邮件",
|
||||||
@@ -1794,7 +1794,7 @@
|
|||||||
"new_subfolder": "新建子文件夹...",
|
"new_subfolder": "新建子文件夹...",
|
||||||
"new_folder": "新建文件夹...",
|
"new_folder": "新建文件夹...",
|
||||||
"rename": "重命名...",
|
"rename": "重命名...",
|
||||||
"import_email": "导入 .eml...",
|
"import_email": "导入 .eml 或 .zip...",
|
||||||
"empty_folder": "清空文件夹",
|
"empty_folder": "清空文件夹",
|
||||||
"empty_folder_generic": "清空文件夹",
|
"empty_folder_generic": "清空文件夹",
|
||||||
"delete_folder": "删除文件夹",
|
"delete_folder": "删除文件夹",
|
||||||
|
|||||||
Reference in New Issue
Block a user