feat: add email recipient history to user settings and implement management in InboxDetailPage
Build and Push Multi-Platform Images / build-and-push (push) Successful in 36s

This commit is contained in:
2026-05-10 21:32:19 +02:00
parent 36322ae4c3
commit 351938aa5c
4 changed files with 56 additions and 3 deletions
@@ -10,6 +10,7 @@ export interface UserSettingsData {
smtpFromName: string | null;
mailSignatureHtml: string | null;
defaultLabelTemplateId: number | null;
emailRecipientHistory: string[] | null;
}
export interface SenderOption {
@@ -659,6 +659,7 @@ function SendEmailDialog({ open, fileId, fileName, documents, thumbUrls, onClose
const [filenames, setFilenames] = useState<string[]>([]);
const [senders, setSenders] = useState<SenderOption[]>([]);
const [selectedSender, setSelectedSender] = useState<string>('default');
const [recipientHistory, setRecipientHistory] = useState<string[]>([]);
const editorRef = useRef<WysiwygEditorHandle>(null);
useEffect(() => {
@@ -672,6 +673,7 @@ function SendEmailDialog({ open, fileId, fileName, documents, thumbUrls, onClose
);
userSettingsApi.get().then((settings) => {
editorRef.current?.setContent(settings.mailSignatureHtml ?? '');
setRecipientHistory(settings.emailRecipientHistory ?? []);
}).catch(() => {});
userSettingsApi.getSenders().then((s) => {
setSenders(s);
@@ -679,12 +681,21 @@ function SendEmailDialog({ open, fileId, fileName, documents, thumbUrls, onClose
}).catch(() => setSenders([]));
}, [open, documents, fileName, form]);
const removeRecipient = (addr: string, e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
const updated = recipientHistory.filter((a) => a !== addr);
setRecipientHistory(updated);
userSettingsApi.update({ emailRecipientHistory: updated }).catch(() => {});
};
const handleOk = async () => {
try {
const values = await form.validateFields();
setSubmitting(true);
const addresses: string[] = values.to ?? [];
await inboxApi.sendEmail(fileId, {
to: values.to,
to: addresses.join(', '),
subject: values.subject,
body: editorRef.current?.getText() ?? '',
html: editorRef.current?.getHTML(),
@@ -694,6 +705,12 @@ function SendEmailDialog({ open, fileId, fileName, documents, thumbUrls, onClose
})),
sender: senders.length > 1 ? selectedSender : undefined,
});
const updated = [
...addresses,
...recipientHistory.filter((a) => !addresses.includes(a)),
].slice(0, 20);
setRecipientHistory(updated);
userSettingsApi.update({ emailRecipientHistory: updated }).catch(() => {});
message.success('E-Mail wurde gesendet');
onClose();
} catch (err: any) {
@@ -726,8 +743,36 @@ function SendEmailDialog({ open, fileId, fileName, documents, thumbUrls, onClose
/>
</Form.Item>
)}
<Form.Item name="to" label="Empfänger" rules={[{ required: true, message: 'Bitte Empfänger angeben' }, { type: 'email', message: 'Ungültige E-Mail-Adresse' }]}>
<Input placeholder="empfaenger@beispiel.de" />
<Form.Item
name="to"
label="Empfänger"
rules={[{
validator: (_: unknown, value: string[]) => {
if (!value?.length) return Promise.reject('Bitte mindestens einen Empfänger angeben');
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const bad = value.find((v) => !re.test(v));
return bad ? Promise.reject(`Ungültige Adresse: ${bad}`) : Promise.resolve();
},
}]}
>
<Select
mode="tags"
placeholder="empfaenger@beispiel.de"
tokenSeparators={[',', ';']}
options={recipientHistory.map((addr) => ({ value: addr, label: addr }))}
optionRender={(option) => (
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 8 }}>
<span>{option.label}</span>
<Button
type="text"
size="small"
icon={<DeleteOutlined />}
onClick={(e) => removeRecipient(option.value as string, e)}
/>
</div>
)}
notFoundContent={<span style={{ color: '#999', fontSize: 12 }}>Kein Verlauf vorhanden</span>}
/>
</Form.Item>
<Form.Item name="subject" label="Betreff" rules={[{ required: true, message: 'Bitte Betreff angeben' }]}>
<Input />