fix(email): mark required fields on incoming mail to match outgoing SMTP
The IMAP card was restyled to match SMTP but didn't carry the required-field markers. Aligned the required set (protocol differences kept): - red asterisks on Host *, Port *, Username * (SMTP marks Host/Port/From-Email; IMAP has no From-Email but always needs a login) - client-side guard mirroring handleSaveSmtp (block save without host/port/user) - backend POST /incoming-config now requires imap_user (the poller's getImapConfig returns null without it) - en/de requiredFields string
This commit is contained in:
@@ -141,6 +141,9 @@ router.post('/incoming-config', [
|
||||
requirePermission('email.edit'),
|
||||
body('imap_host').notEmpty().withMessage('IMAP host is required'),
|
||||
body('imap_port').isInt({ min: 1, max: 65535 }).withMessage('Invalid port number'),
|
||||
// IMAP always needs a login (unlike SMTP relay) — the poller's
|
||||
// getImapConfig() returns null without a username, so require it.
|
||||
body('imap_user').notEmpty().withMessage('IMAP username is required'),
|
||||
], async (req, res) => {
|
||||
try {
|
||||
const errors = validationResult(req);
|
||||
|
||||
@@ -31,7 +31,15 @@ export const IncomingMailConfigCard: React.FC = () => {
|
||||
const set = (k: keyof IncomingMailConfig, v: any) => setCfg((c) => ({ ...c, [k]: v }));
|
||||
|
||||
const save = useMutation({
|
||||
mutationFn: () => emailService.updateIncomingConfig(cfg),
|
||||
mutationFn: () => {
|
||||
// Mirror the SMTP card's client-side required guard. Host + port +
|
||||
// username are needed for the poller to authenticate (getImapConfig
|
||||
// returns null without host+user).
|
||||
if (!cfg.imap_host || !cfg.imap_port || !cfg.imap_user) {
|
||||
return Promise.reject(new Error(t('email.incoming.requiredFields', 'Host, port and username are required.')));
|
||||
}
|
||||
return emailService.updateIncomingConfig(cfg);
|
||||
},
|
||||
onSuccess: () => { toast.success(t('email.incoming.savedToast', 'Incoming mail settings saved.')); qc.invalidateQueries({ queryKey: ['incoming-mail-config'] }); },
|
||||
onError: (e: any) => toast.error(e?.response?.data?.error || e?.response?.data?.errors?.[0]?.msg || e.message || 'Failed'),
|
||||
});
|
||||
@@ -66,7 +74,7 @@ export const IncomingMailConfigCard: React.FC = () => {
|
||||
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<label className={labelCls}>{t('email.incoming.host', 'IMAP Host')}</label>
|
||||
<label className={labelCls}>{t('email.incoming.host', 'IMAP Host')} <span className="text-red-500">*</span></label>
|
||||
<Input
|
||||
type="text"
|
||||
value={cfg.imap_host}
|
||||
@@ -78,7 +86,7 @@ export const IncomingMailConfigCard: React.FC = () => {
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className={labelCls}>{t('email.incoming.port', 'Port')}</label>
|
||||
<label className={labelCls}>{t('email.incoming.port', 'Port')} <span className="text-red-500">*</span></label>
|
||||
<Input type="number" value={cfg.imap_port} onChange={(e) => set('imap_port', parseInt(e.target.value, 10) || 0)} placeholder="993" />
|
||||
</div>
|
||||
<div>
|
||||
@@ -91,7 +99,7 @@ export const IncomingMailConfigCard: React.FC = () => {
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className={labelCls}>{t('email.incoming.user', 'Username')}</label>
|
||||
<label className={labelCls}>{t('email.incoming.user', 'Username')} <span className="text-red-500">*</span></label>
|
||||
<Input
|
||||
type="text"
|
||||
value={cfg.imap_user}
|
||||
|
||||
@@ -2492,6 +2492,7 @@
|
||||
"foldersDetected": "{{count}} Ordner gefunden.",
|
||||
"noFolders": "Der Server hat keine Ordner zurückgegeben.",
|
||||
"detectFailed": "Ordner konnten nicht erkannt werden.",
|
||||
"requiredFields": "Host, Port und Benutzername sind erforderlich.",
|
||||
"savedToast": "Einstellungen für eingehende E-Mails gespeichert."
|
||||
},
|
||||
"received": {
|
||||
|
||||
@@ -2065,6 +2065,7 @@
|
||||
"foldersDetected": "{{count}} folders found.",
|
||||
"noFolders": "No folders returned by the server.",
|
||||
"detectFailed": "Could not detect folders.",
|
||||
"requiredFields": "Host, port and username are required.",
|
||||
"savedToast": "Incoming mail settings saved."
|
||||
},
|
||||
"received": {
|
||||
|
||||
Reference in New Issue
Block a user