Add polished answer notifications (#1)

Sends a branded Resend email when a question receives its first answer, records accepted and failed sends, and adds collapsed answer editing with cancel behavior.

Co-authored-by: codegirl-007 <s.raide@gmail.com>
This commit was merged in pull request #1.
This commit is contained in:
2026-08-27 06:55:24 +00:00
committed by codegirl007
parent 35c8c9f391
commit 418ef93da5
28 changed files with 827 additions and 74 deletions
+52
View File
@@ -0,0 +1,52 @@
package store
import (
"fmt"
"net/mail"
"strings"
"unicode/utf8"
)
const (
minEmailLen = 3
maxEmailLen = 254
)
// NormalizeEmail trims and lowercases an address for storage/comparison.
func NormalizeEmail(s string) string {
return strings.ToLower(strings.TrimSpace(s))
}
// ValidateEmail returns a normalized address or an error message suitable for UI.
func ValidateEmail(raw string) (normalized string, errMsg string) {
normalized = NormalizeEmail(raw)
if normalized == "" {
return "", "Email is required."
}
n := utf8.RuneCountInString(normalized)
if n < minEmailLen || len(normalized) > maxEmailLen {
return "", "Enter a valid email address."
}
addr, err := mail.ParseAddress(normalized)
if err != nil || addr.Address != normalized {
return "", "Enter a valid email address."
}
at := strings.LastIndex(normalized, "@")
if at < 1 || at == len(normalized)-1 {
return "", "Enter a valid email address."
}
domain := normalized[at+1:]
if !strings.Contains(domain, ".") || strings.HasPrefix(domain, ".") || strings.HasSuffix(domain, ".") {
return "", "Enter a valid email address."
}
return normalized, ""
}
// MustValidateEmail is like ValidateEmail but returns a Go error.
func MustValidateEmail(raw string) (string, error) {
n, msg := ValidateEmail(raw)
if msg != "" {
return "", fmt.Errorf("%s", msg)
}
return n, nil
}