mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-03 18:22:57 +00:00
dev day #100 - WE ARE FUCKING DONE, hotfixes incoming but we did it in 100 days, lets fucking go guys, anyone reading this...i love you
This commit is contained in:
+45
-63
@@ -19,6 +19,7 @@ import (
|
||||
"fotbal-club/internal/config"
|
||||
"fotbal-club/internal/models"
|
||||
"fotbal-club/pkg/logger"
|
||||
"fotbal-club/pkg/utils"
|
||||
|
||||
"github.com/vanng822/go-premailer/premailer"
|
||||
"gopkg.in/mail.v2"
|
||||
@@ -476,11 +477,10 @@ func (s *emailService) SendPasswordReset(to string, resetLink string, useOverrid
|
||||
if clubID := strings.TrimSpace(set.ClubID); clubID != "" {
|
||||
// Use PNG format for better email client compatibility (SVG not widely supported)
|
||||
clubLogo = fmt.Sprintf("https://logoapi.sportcreative.eu/logos/%s?format=png&width=400", clubID)
|
||||
} else {
|
||||
clubLogo = "https://via.placeholder.com/400x400.png?text=Logo"
|
||||
}
|
||||
}
|
||||
if clubLogo == "" {
|
||||
clubLogo = "https://via.placeholder.com/400x400.png?text=Logo"
|
||||
}
|
||||
primaryColor := strings.TrimSpace(set.PrimaryColor)
|
||||
if primaryColor == "" {
|
||||
primaryColor = "#1e3a8a"
|
||||
@@ -870,24 +870,26 @@ func (s *emailService) SendContactForm(data *ContactFormData) error {
|
||||
Agent: data.UserAgent,
|
||||
}
|
||||
|
||||
// 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
|
||||
// Build recipients (deduped later):
|
||||
// 1) Club contact email from DB Settings (preferred default)
|
||||
// 2) CONTACT_EMAIL from env (Config.ContactEmail)
|
||||
// 3) ADMIN_EMAIL from env (Config.AdminEmail)
|
||||
recipients := make([]string, 0, 8)
|
||||
// Load settings for contact email and forwarding list
|
||||
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)
|
||||
}
|
||||
}
|
||||
if v := strings.TrimSpace(set.ContactEmail); v != "" {
|
||||
recipients = append(recipients, v)
|
||||
}
|
||||
}
|
||||
// Add environment-provided contact/admin fallbacks
|
||||
if v := strings.TrimSpace(s.config.ContactEmail); v != "" {
|
||||
recipients = append(recipients, v)
|
||||
}
|
||||
if v := strings.TrimSpace(s.config.AdminEmail); v != "" {
|
||||
recipients = append(recipients, v)
|
||||
}
|
||||
// Deduplicate and ensure at least one recipient
|
||||
uniq := make(map[string]struct{})
|
||||
dedup := make([]string, 0, len(recipients))
|
||||
@@ -951,8 +953,6 @@ func (s *emailService) SendNewsletter(d *NewsletterData) error {
|
||||
if subj == "" || html == "" {
|
||||
return fmt.Errorf("newsletter subject and content are required")
|
||||
}
|
||||
// Build dialer and effective From dynamically
|
||||
dialer, effFrom, effFromName := s.buildDialerAndFrom()
|
||||
// Prepare recipient list (dedupe and sanitize)
|
||||
uniq := map[string]struct{}{}
|
||||
recips := make([]string, 0, len(d.Recipients))
|
||||
@@ -984,7 +984,7 @@ func (s *emailService) SendNewsletter(d *NewsletterData) error {
|
||||
}
|
||||
frontendBase := strings.TrimSuffix(s.config.FrontendBaseURL, "/")
|
||||
|
||||
// Send to each recipient
|
||||
// Send to each recipient using the standard email template wrapper (base.html + newsletter.html)
|
||||
var errs []error
|
||||
for _, to := range recips {
|
||||
// Create delivery log (best-effort)
|
||||
@@ -1001,7 +1001,7 @@ func (s *emailService) SendNewsletter(d *NewsletterData) error {
|
||||
_ = s.db.Create(&logRec).Error
|
||||
}
|
||||
|
||||
// Rewrite links for tracking and add open pixel
|
||||
// Rewrite links for tracking and add open pixel (rendered inside the template)
|
||||
trackedHTML := rewriteLinksForTracking(html, makeAbs, int(logRec.ID), token, frontendBase, s.config.PublicAPIBaseURL)
|
||||
pixelURL := makeAbs("/email/open.gif", url.Values{
|
||||
"m": {fmt.Sprintf("%d", logRec.ID)},
|
||||
@@ -1010,60 +1010,42 @@ func (s *emailService) SendNewsletter(d *NewsletterData) error {
|
||||
if strings.TrimSpace(trackedHTML) == "" {
|
||||
trackedHTML = html
|
||||
}
|
||||
trackedHTML = trackedHTML + fmt.Sprintf("<img src=\"%s\" width=\"1\" height=\"1\" style=\"display:none;\" alt=\"\" />", pixelURL)
|
||||
|
||||
m := mail.NewMessage()
|
||||
// Properly encode UTF-8 From name
|
||||
name := strings.TrimSpace(effFromName)
|
||||
if i := strings.Index(name, "<"); i >= 0 {
|
||||
name = strings.TrimSpace(name[:i])
|
||||
// Build manage/unsubscribe URLs (best‑effort)
|
||||
manageURL := ""
|
||||
if v, err := utils.GenerateSubscriberToken(strings.ToLower(strings.TrimSpace(to)), 60*24*30); err == nil && frontendBase != "" {
|
||||
manageURL = frontendBase + "/newsletter/preferences?token=" + v
|
||||
}
|
||||
addr := strings.TrimSpace(effFrom)
|
||||
if !strings.Contains(addr, "@") {
|
||||
addr = strings.TrimSpace(s.config.SMTPFrom)
|
||||
unsubscribeURL := ""
|
||||
if frontendBase != "" {
|
||||
unsubscribeURL = frontendBase + "/newsletter/unsubscribe/" + url.QueryEscape(strings.ToLower(strings.TrimSpace(to)))
|
||||
}
|
||||
if strings.Contains(strings.ToLower(name), "@") {
|
||||
name = ""
|
||||
|
||||
// Render via SendEmail to ensure base wrapper and branding
|
||||
ed := &EmailData{
|
||||
Subject: subj,
|
||||
To: []string{to},
|
||||
Template: "newsletter",
|
||||
Data: map[string]interface{}{
|
||||
"Subject": subj,
|
||||
"Content": trackedHTML,
|
||||
"OpenPixelURL": pixelURL,
|
||||
"ManageURL": manageURL,
|
||||
"UnsubscribeURL": unsubscribeURL,
|
||||
},
|
||||
}
|
||||
m.SetAddressHeader("From", addr, name)
|
||||
m.SetHeader("To", to)
|
||||
m.SetHeader("Subject", subj)
|
||||
m.SetDateHeader("Date", time.Now())
|
||||
m.SetHeader("X-Mailer", "Fotbal Club")
|
||||
if d.Headers != nil {
|
||||
for k, v := range d.Headers {
|
||||
if len(v) > 0 {
|
||||
m.SetHeader(k, v...)
|
||||
}
|
||||
}
|
||||
}
|
||||
m.SetBody("text/plain", "Pro zobrazení tohoto e-mailu použijte HTML klient.")
|
||||
m.AddAlternative("text/html", trackedHTML)
|
||||
// Retry send
|
||||
var lastErr error
|
||||
for i := 0; i < 3; i++ {
|
||||
logger.Debug("SMTP newsletter send attempt %d: to=%s subject=%s", i+1, to, subj)
|
||||
if err := dialer.DialAndSend(m); err == nil {
|
||||
lastErr = nil
|
||||
break
|
||||
} else {
|
||||
lastErr = err
|
||||
logger.Error("SMTP newsletter send failed (attempt %d) to=%s: %v", i+1, to, err)
|
||||
time.Sleep(time.Second * time.Duration(i+1))
|
||||
}
|
||||
}
|
||||
if lastErr != nil {
|
||||
errs = append(errs, fmt.Errorf("failed to send to %s: %w", to, lastErr))
|
||||
if err := s.SendEmail(ed); err != nil {
|
||||
errs = append(errs, fmt.Errorf("failed to send to %s: %w", to, err))
|
||||
if s.db != nil && logRec.ID != 0 {
|
||||
_ = s.db.Model(&models.EmailLog{}).Where("id = ?", logRec.ID).Updates(map[string]interface{}{
|
||||
"status": "failed",
|
||||
"send_error": lastErr.Error(),
|
||||
"send_error": err.Error(),
|
||||
}).Error
|
||||
}
|
||||
}
|
||||
if lastErr == nil && s.db != nil && logRec.ID != 0 {
|
||||
} else if s.db != nil && logRec.ID != 0 {
|
||||
_ = s.db.Model(&models.EmailLog{}).Where("id = ?", logRec.ID).Update("status", "sent").Error
|
||||
}
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
if len(errs) > 0 {
|
||||
|
||||
Reference in New Issue
Block a user