fix(email): match IMAP card to SMTP styling + auto-detect mailbox folders

- IncomingMailConfigCard rebuilt to mirror the outgoing SMTP card: Card
  padding=md, icon inputs (Server/User/Lock), password eye toggle, stacked
  full-width fields, full-width primary Save button
- Folder is now a dropdown auto-populated by a 'Detect' button instead of a
  free-text path: backend emailIntakeService.listFolders() lists IMAP
  mailboxes (POST /admin/email/incoming-config/folders, accepts current form
  creds, masked password falls back to stored); UI auto-selects the inbox
  (special-use) folder
- en/de strings added
This commit is contained in:
Luca
2026-06-12 01:11:31 +02:00
parent 7e0098edcd
commit abb23f01c7
6 changed files with 203 additions and 27 deletions
+13
View File
@@ -88,6 +88,13 @@ export interface IncomingMailConfig {
imap_folder: string;
}
export interface ImapFolder {
path: string;
name: string;
/** IMAP special-use flag, e.g. '\\Inbox', '\\Sent' — used to auto-select. */
specialUse: string | null;
}
export interface ReceivedEmail {
id: number;
message_id: string | null;
@@ -125,6 +132,12 @@ export const emailService = {
async updateIncomingConfig(config: IncomingMailConfig): Promise<void> {
await api.post('/admin/email/incoming-config', config);
},
// Auto-detect mailbox folders. Sends the current form values so detection
// works before the config is saved (masked password falls back server-side).
async listIncomingFolders(config?: Partial<IncomingMailConfig>): Promise<ImapFolder[]> {
const response = await api.post<{ folders: ImapFolder[] }>('/admin/email/incoming-config/folders', config || {});
return response.data.folders;
},
async listReceived(params: { page?: number; pageSize?: number } = {}): Promise<ReceivedEmailsResponse> {
const response = await api.get<ReceivedEmailsResponse>('/admin/email/received', { params });
return response.data;