This commit is contained in:
Tomas Dvorak
2025-10-29 21:20:16 +01:00
parent 823fabee02
commit 16e4533202
61 changed files with 2308 additions and 942 deletions
+110 -34
View File
@@ -770,7 +770,11 @@ func (s *emailService) SendEmail(data *EmailData) error {
// Website and contact (best-effort)
vm["ClubURL"] = strings.TrimSpace(set.ClubURL)
vm["WebsiteURL"] = strings.TrimSpace(set.CanonicalBaseURL)
contactEmail := strings.TrimSpace(s.config.AdminEmail)
// Prefer club contact email from Settings, then AdminEmail, then SMTPFrom
contactEmail := strings.TrimSpace(getStringField(set, "ContactEmail"))
if contactEmail == "" {
contactEmail = strings.TrimSpace(s.config.AdminEmail)
}
if contactEmail == "" {
contactEmail = strings.TrimSpace(s.config.SMTPFrom)
}
@@ -781,6 +785,42 @@ func (s *emailService) SendEmail(data *EmailData) error {
}
vm["ContactURL"] = contactURL
// Provide recipient and link fallbacks for templates
if _, ok := vm["RecipientEmail"]; !ok {
if len(data.To) > 0 {
vm["RecipientEmail"] = strings.TrimSpace(data.To[0])
}
}
if _, ok := vm["UnsubscribeURL"]; !ok {
if v, ok2 := vm["UnsubscribeLink"]; ok2 {
if s, ok3 := v.(string); ok3 && strings.TrimSpace(s) != "" {
vm["UnsubscribeURL"] = strings.TrimSpace(s)
}
}
}
if _, ok := vm["ManageURL"]; !ok {
if v, ok2 := vm["UnsubscribeURL"]; ok2 {
if s, ok3 := v.(string); ok3 && strings.TrimSpace(s) != "" {
vm["ManageURL"] = strings.TrimSpace(s)
}
} else if v2, ok4 := vm["UnsubscribeLink"]; ok4 {
if s, ok5 := v2.(string); ok5 && strings.TrimSpace(s) != "" {
vm["ManageURL"] = strings.TrimSpace(s)
}
} else if v3, ok6 := vm["SetupURL"]; ok6 {
if s, ok7 := v3.(string); ok7 && strings.TrimSpace(s) != "" {
vm["ManageURL"] = strings.TrimSpace(s)
}
}
}
if _, ok := vm["UnsubscribeURL"]; !ok {
if v, ok2 := vm["SetupURL"]; ok2 {
if s, ok3 := v.(string); ok3 && strings.TrimSpace(s) != "" {
vm["UnsubscribeURL"] = strings.TrimSpace(s)
}
}
}
// Parse base + template with functions
basePath := filepath.Join(s.config.EmailTemplateDir, "base.html")
templatePath := filepath.Join(s.config.EmailTemplateDir, data.Template+".html")
@@ -867,42 +907,76 @@ func (s *emailService) SendEmail(data *EmailData) error {
}
func (s *emailService) SendContactForm(data *ContactFormData) error {
templateData := struct {
Name string
Email string
Subject string
Message string
Time string
IP string
Agent string
}{
Name: data.Name,
Email: data.Email,
Subject: data.Subject,
Message: data.Message,
Time: time.Now().Format(time.RFC1123Z),
IP: data.IPAddress,
Agent: data.UserAgent,
}
templateData := struct {
Name string
Email string
Subject string
Message string
Time string
IP string
Agent string
}{
Name: data.Name,
Email: data.Email,
Subject: data.Subject,
Message: data.Message,
Time: time.Now().Format(time.RFC1123Z),
IP: data.IPAddress,
Agent: data.UserAgent,
}
emailData := &EmailData{
Subject: "New Contact Form: " + data.Subject,
To: []string{s.config.AdminEmail},
Template: "contact_form",
Data: templateData,
From: s.config.SMTPFrom,
FromName: s.config.SMTPFromName,
}
// Build recipients: admin email + optional auto-forward list from Settings
recipients := make([]string, 0, 4)
if v := strings.TrimSpace(s.config.AdminEmail); v != "" {
recipients = append(recipients, v)
}
// Load settings to check auto-forwarding
var set models.Settings
if s.db != nil {
_ = s.db.First(&set).Error
if set.ContactForwardEnabled && strings.TrimSpace(set.ContactForwardList) != "" {
parts := strings.FieldsFunc(set.ContactForwardList, func(r rune) bool { return r == ',' || r == ';' || r == ' ' || r == '\n' || r == '\t' })
for _, p := range parts {
if v := strings.TrimSpace(p); v != "" {
recipients = append(recipients, v)
}
}
}
}
// Deduplicate and ensure at least one recipient
uniq := make(map[string]struct{})
dedup := make([]string, 0, len(recipients))
for _, e := range recipients {
v := strings.ToLower(strings.TrimSpace(e))
if v == "" { continue }
if _, ok := uniq[v]; ok { continue }
uniq[v] = struct{}{}
dedup = append(dedup, e)
}
if len(dedup) == 0 {
if v := strings.TrimSpace(s.config.SMTPFrom); v != "" {
dedup = []string{v}
}
}
emailData := &EmailData{
Subject: "Nová zpráva z formuláře: " + data.Subject,
To: dedup,
Template: "contact_form",
Data: templateData,
From: s.config.SMTPFrom,
FromName: s.config.SMTPFromName,
}
// Send confirmation to user
if data.Email != "" {
confirmationData := &EmailData{
Subject: "We've received your message",
To: []string{data.Email},
Template: "contact_confirmation",
Data: struct {
Name string
Message string
confirmationData := &EmailData{
Subject: "Obdrželi jsme vaši zprávu",
To: []string{data.Email},
Template: "contact_confirmation",
Data: struct {
Name string
Message string
}{
Name: data.Name,
Message: data.Message,
@@ -1048,6 +1122,7 @@ func (s *emailService) SendNewsletter(data *NewsletterData) error {
ClubURL string
ContactEmail string
ContactURL string
RecipientEmail string
}{
Subject: data.Subject,
Content: data.Content,
@@ -1073,13 +1148,14 @@ func (s *emailService) SendNewsletter(data *NewsletterData) error {
}
return makeAbs("/email/click", url.Values{"m": {fmt.Sprintf("%d", elog.ID)}, "t": {trackTok}, "u": {clubURL}})
}(),
ContactEmail: contactEmail,
ContactEmail: contactEmail,
ContactURL: func() string {
if contactURL == "" {
return ""
}
return makeAbs("/email/click", url.Values{"m": {fmt.Sprintf("%d", elog.ID)}, "t": {trackTok}, "u": {contactURL}})
}(),
RecipientEmail: recipient,
}
// Wrap socials if present