feat(mail): define standard IMAP folder mappings

This commit is contained in:
2026-08-19 21:27:42 +02:00
parent 4cf2bfeb3e
commit 9d1352ba30
10 changed files with 300 additions and 16 deletions
+61 -1
View File
@@ -16,7 +16,7 @@ import { renderToStaticMarkup } from "react-dom/server";
import CredentialPanel from "../src/components/CredentialPanel";
import PasswordField from "../src/components/PasswordField";
import MessageDisplayPanel, { buildSafeMessageHtmlDocument } from "../src/components/MessageDisplayPanel";
import MailServerSettingsPanel, { MailServerFolderLookupResultView, resolveMailServerSettingsActiveSection } from "../src/components/mail/MailServerSettingsPanel";
import MailServerSettingsPanel, { MailServerFolderLookupResultView, mailImapSettingsPayload, normalizeMailImapFolderMappings, resolveMailServerSettingsActiveSection } from "../src/components/mail/MailServerSettingsPanel";
import EmailAddressInput from "../src/components/email/EmailAddressInput";
import { PlatformLanguageProvider } from "../src/i18n/LanguageContext";
@@ -146,6 +146,66 @@ assert(imapSettingsPanel.includes('placeholder="Saved IMAP password"'), "IMAP sa
assert(!imapSettingsPanel.includes("Folders loaded"), "folder lookup result is not rendered in the IMAP tab");
assert(!imapSettingsPanel.includes("Default sent folder"), "default sent folder field is not rendered");
assertDeepEqual(
normalizeMailImapFolderMappings({ inbox: " INBOX ", sent: "Sent Items", junk: " " }),
{ inbox: "INBOX", sent: "Sent Items", drafts: null, trash: null, archive: null, junk: null },
"standard IMAP mappings are normalized without inventing folder names"
);
assertDeepEqual(
mailImapSettingsPayload(
{
host: "imap.example.org",
port: 993,
security: "tls",
sent_folder: "Legacy Sent",
folder_mappings: { sent: "Mapped Sent", archive: "Archive" },
timeout_seconds: 30
},
{ fallbackSecurity: "tls" }
),
{
host: "imap.example.org",
port: 993,
security: "tls",
sent_folder: "Mapped Sent",
folder_mappings: { inbox: null, sent: "Mapped Sent", drafts: null, trash: null, archive: "Archive", junk: null },
timeout_seconds: 30
},
"the typed Sent mapping remains synchronized with the legacy append field"
);
const mappedImapSettingsPanel = renderToStaticMarkup(
<MailServerSettingsPanel
initialSection="imap"
visibleSections={["imap"]}
mode="server"
smtp={{}}
imap={{
host: "imap.example.org",
port: 993,
security: "tls",
sent_folder: "Sent",
folder_mappings: { inbox: "INBOX", sent: "Sent" },
timeout_seconds: 30
}}
onSmtpChange={noop}
onImapChange={noop}
onLookupImapFolders={noop}
imapFolderLookupResult={{
ok: true,
protocol: "imap",
message: "Folders loaded",
detected_sent_folder: "Sent",
detected_folder_mappings: { inbox: "INBOX", sent: "Sent", drafts: "Drafts" },
folders: [{ name: "INBOX" }, { name: "Sent" }, { name: "Drafts" }]
}}
/>
);
assert(mappedImapSettingsPanel.includes("i18n:govoplan-core.standard_folder_mappings"), "profile IMAP settings render the shared standard-folder editor");
assert(mappedImapSettingsPanel.includes("i18n:govoplan-core.detect_folders"), "profile IMAP settings expose folder discovery");
assert(mappedImapSettingsPanel.includes("i18n:govoplan-core.use_detected_folder_mappings"), "detected standard mappings can be applied together");
assert(mappedImapSettingsPanel.includes('<option value="Drafts"></option>'), "discovered folder names populate mapping suggestions");
const folderLookupError = renderToStaticMarkup(
<MailServerFolderLookupResultView result={{ ok: false, protocol: "imap", message: "IMAP lookup timed out", folders: [] }} />
);