updated webclient setttings

This commit is contained in:
2026-08-15 21:49:25 +01:00
parent 15678c1b6e
commit f60dbcc6b0
41 changed files with 3147 additions and 770 deletions
+46 -8
View File
@@ -26,21 +26,50 @@ import (
const maxComposeUploadBytes = 25 << 20 // 25MB, matching a typical provider's attachment cap
// sendAsAddresses returns a mailbox's active, send-as-capable aliases — the set of
// extra "From" addresses compose (and, for signatures, per-alias defaults) offers
// alongside the mailbox's own primary address.
func (a *App) sendAsAddresses(mbox *db.Mailbox) []string {
aliases, _ := a.DB.ListAliasesForMailbox(mbox.ID)
var out []string
for _, al := range aliases {
if al.CanSendAs && al.IsActive {
out = append(out, al.Email)
}
}
return out
}
// composeFormData builds the template data every compose-page render needs
// regardless of why it's rendering (a fresh GET, a reply/forward prefill, or
// redisplaying the form after a failed send) — shared so those three paths can't
// drift out of sync with each other.
func (a *App) composeFormData(mbox *db.Mailbox) M {
aliases, _ := a.DB.ListAliasesForMailbox(mbox.ID)
var sendAsOptions []string
for _, al := range aliases {
if al.CanSendAs && al.IsActive {
sendAsOptions = append(sendAsOptions, al.Email)
}
}
sendAsOptions := a.sendAsAddresses(mbox)
identities, _ := a.DB.ListSMIMEIdentities(mbox.ID)
pgpContacts, _ := a.DB.ListPGPContacts(mbox.ID)
signatures, _ := a.DB.ListSignatures(mbox.ID)
// One default-signature-id lookup per (address, new-or-reply) pair, embedded as a
// JS map so compose can swap the inserted signature live when the From-alias
// picker changes — see webmail_compose.html's from-select handler. Otherwise a
// per-alias default (Settings > Signatures) would only ever apply to the mailbox's
// own primary address, since that's the only "from" compose knows about at
// initial page load (the alias picker itself is client-side only).
addresses := append([]string{mbox.Email}, sendAsOptions...)
sigDefaults := make(map[string]map[string]int64, len(addresses))
for _, addr := range addresses {
entry := map[string]int64{"new": 0, "reply": 0}
if sig, err := a.DB.GetDefaultSignature(mbox.ID, false, addr); err == nil && sig != nil {
entry["new"] = sig.ID
}
if sig, err := a.DB.GetDefaultSignature(mbox.ID, true, addr); err == nil && sig != nil {
entry["reply"] = sig.ID
}
sigDefaults[addr] = entry
}
sigDefaultsJSON, _ := json.Marshal(sigDefaults)
return M{
"mailbox": mbox, "send_as_options": sendAsOptions, "smime_identities": identities, "pgp_contacts": pgpContacts,
"signatures": signatures,
@@ -48,6 +77,9 @@ func (a *App) composeFormData(mbox *db.Mailbox) M {
// $.default_signature_id .ID}} comparison never has to handle a nil operand —
// 0 is a safe "no default" sentinel since real ids start at 1 (AUTOINCREMENT).
"default_signature_id": int64(0),
// See json.Marshal HTML-escaping note on webmailRulesList's identical pattern —
// safe to mark template.JS since json.Marshal already escapes <, >, &.
"signature_defaults_json": template.JS(sigDefaultsJSON),
}
}
@@ -84,6 +116,12 @@ func (a *App) webmailComposeForm(w http.ResponseWriter, r *http.Request) {
uidStr, mode = q.Get("draft"), "draft"
}
// Exposed to JS so the from-select handler knows which slot ("new" or "reply") of
// signature_defaults_json to use when the picked address changes — a draft is
// treated like "new" here (matching the auto-insertion skip below: a draft's
// signature situation, if any, is whatever was already saved in it).
data["compose_for_reply"] = mode == "reply" || mode == "replyall" || mode == "forward"
if mode != "" && folder != "" {
if parsed := a.webmailLoadForPrefill(mbox.ID, folder, int64(atoi(uidStr))); parsed != nil {
switch mode {
@@ -126,7 +164,7 @@ func (a *App) webmailComposeForm(w http.ResponseWriter, r *http.Request) {
// when it was saved, or none, and re-adding one here would duplicate it.
if mode != "draft" {
forReply := mode == "reply" || mode == "replyall" || mode == "forward"
if sig, err := a.DB.GetDefaultSignature(mbox.ID, forReply); err == nil && sig != nil {
if sig, err := a.DB.GetDefaultSignature(mbox.ID, forReply, ""); err == nil && sig != nil {
data["default_signature_id"] = sig.ID
if wrapped := wrapSignatureHTML(sig.ContentHTML); wrapped != "" {
existing, _ := data["body_html"].(template.HTML)