updated layout for webmail and added http dns letsencrypt

This commit is contained in:
2026-08-15 12:35:44 +01:00
parent 310700407e
commit f283c90f11
49 changed files with 3359 additions and 431 deletions
+25 -6
View File
@@ -638,8 +638,14 @@ func (a *App) webmailComposeSend(w http.ResponseWriter, r *http.Request) {
results = append(results, a.deliverWebmailComposeLocally(rcpt, localTypes[i], from, subject, signed, messageID))
}
if _, err := a.Mailstore.StoreMessage(mbox.ID, "Sent", []byte(signed), messageID, from, subject); err != nil {
if sentUID, err := a.Mailstore.StoreMessage(mbox.ID, "Sent", []byte(signed), messageID, from, subject); err != nil {
a.Logger.Error("store sent copy for mailbox %d: %v", mbox.ID, err)
} else if err := a.DB.SetMessageFlags(mbox.ID, sentUID, `\Seen`); err != nil {
// Mail you just sent yourself was never "unread" to begin with — StoreMessage
// has no way to set initial flags, so this mirrors deliverWebmailComposeLocally's
// existing store-then-mark-read pattern rather than threading a flags param
// through StoreMessage for what only these two Sent/Drafts call sites need.
a.Logger.Error("mark sent copy %d read for mailbox %d: %v", sentUID, mbox.ID, err)
}
// Sending a draft removes it from Drafts, same as any real mail client.
@@ -649,12 +655,13 @@ func (a *App) webmailComposeSend(w http.ResponseWriter, r *http.Request) {
}
}
loggedBody := plainText
// Privacy default (matches the inbound SMTP path — see session.go's Data()): the
// admin-visible log never gets the body content, webmail-sent mail included. There's
// no per-mailbox "store content" opt-in for outbound webmail sends the way there is
// for inbound senders/IPs, and it would be redundant anyway — the sender's own Sent
// folder already keeps the real, encrypted-at-rest copy of what they sent.
loggedBody := "[content not stored by default — see the sender's Sent folder for the full message]"
if wantEncrypt {
// The whole point of checking "Encrypt" is that nobody but the recipient (and
// the sender's own Sent copy) can read it — logging the plaintext into the
// admin-visible email log would defeat that even though the wire content is
// genuinely encrypted.
loggedBody = "[PGP encrypted — plaintext not logged]"
}
if _, err := a.Relay.LogEmail(a.Cfg, a.requestIP(r), from, strings.Join(toAddrs, ", "), strings.Join(ccAddrs, ", "), strings.Join(bccAddrs, ", "),
@@ -664,6 +671,7 @@ func (a *App) webmailComposeSend(w http.ResponseWriter, r *http.Request) {
allSucceeded := len(results) > 0
var failures []string
var failed []relay.Result
for _, res := range results {
if res.Status != "success" {
allSucceeded = false
@@ -672,12 +680,20 @@ func (a *App) webmailComposeSend(w http.ResponseWriter, r *http.Request) {
reason = res.ServerResponse
}
failures = append(failures, res.Recipient+": "+reason)
failed = append(failed, res)
}
}
if allSucceeded {
setFlash(w, "success", "Message sent")
} else {
setFlash(w, "error", "Sent, but delivery failed — "+strings.Join(failures, "; "))
// There's no separate "sending MTA" here to retry/bounce it the way a real
// inbound SMTP client would — the flash message above only exists for the
// moment right after clicking Send, so a persistent copy lands in the
// sender's own INBOX too, same as a real bounce from any other mail provider.
if err := a.Relay.SendBounce(from, subject, messageID, failed); err != nil {
a.Logger.Error("send bounce to %s: %v", from, err)
}
}
http.Redirect(w, r, MailboxPrefix+"/mail/Sent", http.StatusFound)
}
@@ -745,6 +761,9 @@ func (a *App) webmailComposeSaveDraft(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, MailboxPrefix+"/mail/compose", http.StatusFound)
return
}
if err := a.DB.SetMessageFlags(mbox.ID, newUID, `\Seen`); err != nil {
a.Logger.Error("mark draft %d read for mailbox %d: %v", newUID, mbox.ID, err)
}
// Replace, don't accumulate: re-saving an open draft deletes the previous copy.
if draftIDStr := r.FormValue("draft_id"); draftIDStr != "" {