Add login rename and password reset flow

This commit is contained in:
DonVoo 2026-07-13 01:19:47 +02:00
parent b625c95c29
commit e7611b2d49
4 changed files with 362 additions and 28 deletions

View file

@ -1,13 +1,100 @@
package backend
// SMTP wird AUSSCHLIESSLICH fuers manuelle Weiterleiten einzelner Mails aus dem
// Viewer benutzt (Cfg.ForwardSMTP). Der Postfach-Umzug laeuft NIE ueber SMTP,
// sondern ueber IMAP APPEND (05-imap-target.go) -- sonst gingen Datum, Flags
// und Ordnerstruktur verloren.
import (
"crypto/tls"
"fmt"
"net"
"net/smtp"
"strings"
)
// SMTP wird AUSSCHLIESSLICH fuers manuelle Weiterleiten einzelner Mails und
// App-Benachrichtigungen wie Passwort-Reset benutzt. Der Postfach-Umzug laeuft
// NIE ueber SMTP, sondern ueber IMAP APPEND (05-imap-target.go).
func SendPlainMail(to []string, subject, body string) error {
cfg := Cfg.ForwardSMTP
if strings.TrimSpace(cfg.Host) == "" || cfg.Port == 0 || strings.TrimSpace(cfg.From) == "" {
return fmt.Errorf("forward_smtp ist nicht vollstaendig konfiguriert")
}
from := cfg.From
if strings.TrimSpace(cfg.User) != "" {
from = cfg.User
}
message := []byte("From: " + cfg.From + "\r\n" +
"To: " + strings.Join(to, ", ") + "\r\n" +
"Subject: " + subject + "\r\n" +
"Content-Type: text/plain; charset=utf-8\r\n" +
"\r\n" + body)
addr := net.JoinHostPort(cfg.Host, fmt.Sprint(cfg.Port))
auth := smtp.Auth(nil)
if cfg.User != "" || cfg.Pass != "" {
auth = smtp.PlainAuth("", cfg.User, cfg.Pass, cfg.Host)
}
if cfg.Port == 465 {
return sendTLS(addr, cfg.Host, auth, from, to, message)
}
return sendStartTLS(addr, cfg.Host, auth, from, to, message)
}
func sendStartTLS(addr, host string, auth smtp.Auth, from string, to []string, message []byte) error {
c, err := smtp.Dial(addr)
if err != nil {
return err
}
defer c.Close()
if ok, _ := c.Extension("STARTTLS"); ok {
if err := c.StartTLS(&tls.Config{ServerName: host, MinVersion: tls.VersionTLS12}); err != nil {
return err
}
}
return smtpClientSend(c, auth, from, to, message)
}
func sendTLS(addr, host string, auth smtp.Auth, from string, to []string, message []byte) error {
conn, err := tls.Dial("tcp", addr, &tls.Config{ServerName: host, MinVersion: tls.VersionTLS12})
if err != nil {
return err
}
c, err := smtp.NewClient(conn, host)
if err != nil {
_ = conn.Close()
return err
}
defer c.Close()
return smtpClientSend(c, auth, from, to, message)
}
func smtpClientSend(c *smtp.Client, auth smtp.Auth, from string, to []string, message []byte) error {
if auth != nil {
if err := c.Auth(auth); err != nil {
return err
}
}
if err := c.Mail(from); err != nil {
return err
}
for _, rcpt := range to {
if err := c.Rcpt(rcpt); err != nil {
return err
}
}
w, err := c.Data()
if err != nil {
return err
}
if _, err := w.Write(message); err != nil {
_ = w.Close()
return err
}
if err := w.Close(); err != nil {
return err
}
return c.Quit()
}
// ForwardMessage leitet den mbox-Rohtext an einen Empfaenger weiter.
func ForwardMessage(rawMessage []byte, to []string, extraNote string) error {
// TODO Codex: net/smtp (stdlib) mit STARTTLS + AUTH gegen Cfg.ForwardSMTP.
// Original als Anhang oder inline weiterleiten, From = Cfg.ForwardSMTP.From.
return nil
body := extraNote + "\n\n" + string(rawMessage)
return SendPlainMail(to, "Weitergeleitete Nachricht aus Mail-Graveyard", body)
}