feat: Verschluesselung waehlbar, dazu zwei Layout-Fehler
Verschluesselung: Bisher gab es nur den Schalter use_ssl – also implizites TLS auf 993 oder gar nichts. STARTTLS auf 143 fehlte ganz, und das bieten viele Anbieter an. Jetzt ein Feld mit drei Werten, der Port zieht bei der Auswahl mit, und "keine" warnt, dass Zugangsdaten im Klartext gehen. Layout: Die Postfach-Karte steht in einer schmalen Spalte; der waagerechte Aufbau brach dort auf ein Wort je Zeile um und die Knoepfe lagen ueber dem Titel. Jetzt gestapelt. Die Einstellungsseite nutzte ein Raster, das die Karten zeilenweise ausrichtet – die zweite Reihe begann erst unter der hoechsten Karte der ersten, weshalb "Backup zurueckladen" allein weit unten stand. Jetzt fliessen die Karten spaltenweise, und die Spalten sind breiter: vier schmale Karten nebeneinander waren auf dem Notebook nicht lesbar. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,7 +6,7 @@ import { useConfirm } from "../../confirm";
|
||||
import Icon from "../../components/Icon";
|
||||
|
||||
const LEER = {
|
||||
name: "", host: "", port: 993, use_ssl: true, username: "", password: "",
|
||||
name: "", host: "", port: 993, security: "ssl", username: "", password: "",
|
||||
folder: "INBOX", done_folder: "", mark_seen: true, is_active: true, poll_minutes: 15,
|
||||
};
|
||||
|
||||
@@ -116,32 +116,32 @@ export default function Postfaecher() {
|
||||
<p className="muted small">{t("mailbox.intro")}</p>
|
||||
|
||||
{quellen.map((q) => (
|
||||
<div key={q.id} className="account-row" style={{ alignItems: "flex-start" }}>
|
||||
<div className="named-text grow">
|
||||
<div><strong>{q.name || q.host}</strong></div>
|
||||
<div className="named-sub">
|
||||
{q.username} · {q.folder}
|
||||
{q.last_error
|
||||
? ` · ${t("mailbox.lastError")}: ${q.last_error}`
|
||||
: q.last_poll_at ? ` · ${t("mailbox.lastPoll")}` : ` · ${t("mailbox.neverPolled")}`}
|
||||
</div>
|
||||
<div className="named-sub">
|
||||
{(absender[q.id] || []).length === 0
|
||||
? t("mailbox.noSenders")
|
||||
: (absender[q.id] || []).map((a) => {
|
||||
const konto = konten.find((k) => k.id === a.account_id);
|
||||
return `${a.from_contains || "*"} → ${konto ? konto.name : t("mailbox.noAccount")}`;
|
||||
}).join(" · ")}
|
||||
</div>
|
||||
<SenderForm konten={konten} onAdd={(d) => absenderAnlegen(q, d)} t={t} />
|
||||
<div key={q.id} className="mail-source">
|
||||
<div><strong>{q.name || q.host}</strong></div>
|
||||
<div className="muted small">{q.username} · {q.folder} · {q.security.toUpperCase()}</div>
|
||||
<div className="muted small">
|
||||
{q.last_error
|
||||
? `${t("mailbox.lastError")}: ${q.last_error}`
|
||||
: q.last_poll_at ? t("mailbox.lastPoll") : t("mailbox.neverPolled")}
|
||||
</div>
|
||||
<div className="row-actions">
|
||||
<div className="muted small" style={{ marginTop: "var(--sp-2)" }}>
|
||||
{(absender[q.id] || []).length === 0
|
||||
? t("mailbox.noSenders")
|
||||
: (absender[q.id] || []).map((a) => {
|
||||
const konto = konten.find((k) => k.id === a.account_id);
|
||||
return `${a.from_contains || "*"} → ${konto ? konto.name : t("mailbox.noAccount")}`;
|
||||
}).join(" · ")}
|
||||
</div>
|
||||
<SenderForm konten={konten} onAdd={(d) => absenderAnlegen(q, d)} t={t} />
|
||||
<div className="btn-pair" style={{ marginTop: "var(--sp-2)" }}>
|
||||
<button className="btn sm" disabled={busy} onClick={() => testen(q)}>{t("mailbox.test")}</button>
|
||||
<button className="btn sm primary" disabled={busy} onClick={() => abrufen(q)}>{t("mailbox.fetchNow")}</button>
|
||||
<button className="btn sm ghost" onClick={() => { setForm({ ...LEER, ...q, password: "" }); setOrdner(null); }}>
|
||||
<button className="btn sm ghost" title={t("common.edit")}
|
||||
onClick={() => { setForm({ ...LEER, ...q, password: "" }); setOrdner(null); }}>
|
||||
<Icon name="edit" size={15} />
|
||||
</button>
|
||||
<button className="btn sm danger" onClick={() => loeschen(q)}><Icon name="trash" size={15} /></button>
|
||||
<button className="btn sm danger" title={t("common.delete")}
|
||||
onClick={() => loeschen(q)}><Icon name="trash" size={15} /></button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
@@ -162,6 +162,22 @@ export default function Postfaecher() {
|
||||
<input value={form.host} required onChange={(e) => setzen({ host: e.target.value })}
|
||||
placeholder="imap.example.com" />
|
||||
</label>
|
||||
<label className="field">
|
||||
<span>{t("mailbox.security")}</span>
|
||||
<select value={form.security}
|
||||
onChange={(e) => {
|
||||
// Der uebliche Port haengt an der Verschluesselung – gleich
|
||||
// mitziehen, damit die haeufigste Fehlerquelle wegfaellt.
|
||||
const art = e.target.value;
|
||||
const port = art === "ssl" ? 993 : 143;
|
||||
setzen({ security: art, port });
|
||||
}}>
|
||||
<option value="ssl">{t("mailbox.secSsl")}</option>
|
||||
<option value="starttls">{t("mailbox.secStarttls")}</option>
|
||||
<option value="none">{t("mailbox.secNone")}</option>
|
||||
</select>
|
||||
</label>
|
||||
{form.security === "none" && <p className="muted small">{t("mailbox.secNoneWarn")}</p>}
|
||||
<label className="field">
|
||||
<span>{t("mailbox.port")}</span>
|
||||
<input type="number" value={form.port}
|
||||
@@ -216,16 +232,17 @@ function SenderForm({ konten, onAdd, t }) {
|
||||
const [von, setVon] = useState("");
|
||||
const [konto, setKonto] = useState("");
|
||||
return (
|
||||
<div className="field-inline" style={{ marginTop: "var(--sp-2)", marginBottom: 0 }}>
|
||||
<input placeholder={t("mailbox.fromPlaceholder")} value={von}
|
||||
<div style={{ marginTop: "var(--sp-2)" }}>
|
||||
<input style={{ width: "100%" }} placeholder={t("mailbox.fromPlaceholder")} value={von}
|
||||
onChange={(e) => setVon(e.target.value)} />
|
||||
<select value={konto} onChange={(e) => setKonto(e.target.value)}>
|
||||
<select style={{ width: "100%", marginTop: 4 }} value={konto}
|
||||
onChange={(e) => setKonto(e.target.value)}>
|
||||
<option value="">{t("mailbox.noAccount")}</option>
|
||||
{konten.map((k) => <option key={k.id} value={k.id}>{k.name}</option>)}
|
||||
</select>
|
||||
<button type="button" className="btn sm" disabled={!von.trim()}
|
||||
<button type="button" className="btn sm" style={{ marginTop: 4 }} disabled={!von.trim()}
|
||||
onClick={() => { onAdd({ from_contains: von.trim(), account_id: konto ? Number(konto) : null }); setVon(""); }}>
|
||||
<Icon name="plus" size={14} />
|
||||
<Icon name="plus" size={14} /> {t("mailbox.addSender")}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user