diff --git a/backend/internal/services/notification_service.go b/backend/internal/services/notification_service.go
index 0f8aba5e..9032f0ed 100644
--- a/backend/internal/services/notification_service.go
+++ b/backend/internal/services/notification_service.go
@@ -5,6 +5,7 @@ import (
"context"
"encoding/json"
"fmt"
+ "html"
"net"
"net/http"
neturl "net/url"
@@ -283,24 +284,24 @@ func (s *NotificationService) dispatchEmail(ctx context.Context, p models.Notifi
safeTitle := sanitizeForEmail(title)
safeMessage := sanitizeForEmail(message)
subject := fmt.Sprintf("[Charon Alert] %s", safeTitle)
- // Build a plain-text body; MailService will convert this to safe HTML and
- // perform additional sanitization before sending.
var bodyBuilder strings.Builder
if safeTitle != "" {
- bodyBuilder.WriteString(safeTitle)
+ bodyBuilder.WriteString("")
+ bodyBuilder.WriteString(html.EscapeString(safeTitle))
+ bodyBuilder.WriteString("")
}
if safeMessage != "" {
if bodyBuilder.Len() > 0 {
- bodyBuilder.WriteString("\n\n")
+ bodyBuilder.WriteString("
")
}
- bodyBuilder.WriteString(safeMessage)
+ bodyBuilder.WriteString(html.EscapeString(safeMessage))
}
- plainBody := bodyBuilder.String()
+ htmlBody := bodyBuilder.String()
timeoutCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()
- if err := s.mailService.SendEmail(timeoutCtx, recipients, subject, plainBody); err != nil {
+ if err := s.mailService.SendEmail(timeoutCtx, recipients, subject, htmlBody); err != nil {
logger.Log().WithError(err).WithField("provider", util.SanitizeForLog(p.Name)).Error("Failed to send email notification")
}
}