fix: connect EmailService to contact form handler

The contact form was logging submissions but never actually sending emails.
This commit:
- Adds EmailService field to CVHandler
- Initializes EmailService in main.go with SMTP config
- Calls SendContactForm in HandleContact handler
- Updates all test files to pass nil for emailService parameter
This commit is contained in:
juanatsap
2025-12-02 14:27:03 +00:00
parent 9842f183ea
commit f3842a3486
9 changed files with 66 additions and 30 deletions
+6 -6
View File
@@ -21,7 +21,7 @@ func BenchmarkHome(b *testing.B) {
b.Fatalf("Failed to create template manager: %v", err)
}
handler := NewCVHandler(tmplManager, "localhost:8080")
handler := NewCVHandler(tmplManager, "localhost:8080", nil)
b.ResetTimer()
for i := 0; i < b.N; i++ {
@@ -43,7 +43,7 @@ func BenchmarkCVContent(b *testing.B) {
b.Fatalf("Failed to create template manager: %v", err)
}
handler := NewCVHandler(tmplManager, "localhost:8080")
handler := NewCVHandler(tmplManager, "localhost:8080", nil)
b.ResetTimer()
for i := 0; i < b.N; i++ {
@@ -65,7 +65,7 @@ func BenchmarkToggleLength(b *testing.B) {
b.Fatalf("Failed to create template manager: %v", err)
}
handler := NewCVHandler(tmplManager, "localhost:8080")
handler := NewCVHandler(tmplManager, "localhost:8080", nil)
b.ResetTimer()
for i := 0; i < b.N; i++ {
@@ -101,7 +101,7 @@ func BenchmarkPrepareTemplateData(b *testing.B) {
b.Fatalf("Failed to create template manager: %v", err)
}
handler := NewCVHandler(tmplManager, "localhost:8080")
handler := NewCVHandler(tmplManager, "localhost:8080", nil)
b.ResetTimer()
for i := 0; i < b.N; i++ {
@@ -144,7 +144,7 @@ func BenchmarkParallelHome(b *testing.B) {
b.Fatalf("Failed to create template manager: %v", err)
}
handler := NewCVHandler(tmplManager, "localhost:8080")
handler := NewCVHandler(tmplManager, "localhost:8080", nil)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
@@ -168,7 +168,7 @@ func BenchmarkParallelToggleLength(b *testing.B) {
b.Fatalf("Failed to create template manager: %v", err)
}
handler := NewCVHandler(tmplManager, "localhost:8080")
handler := NewCVHandler(tmplManager, "localhost:8080", nil)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
+5 -1
View File
@@ -4,6 +4,7 @@ import (
"time"
"github.com/juanatsap/cv-site/internal/pdf"
"github.com/juanatsap/cv-site/internal/services"
"github.com/juanatsap/cv-site/internal/templates"
)
@@ -12,18 +13,21 @@ import (
// - cv_pages.go: Page rendering (Home, CVContent, DefaultCVShortcut)
// - cv_pdf.go: PDF export (ExportPDF)
// - cv_htmx.go: HTMX toggles (ToggleLength, ToggleIcons, SwitchLanguage, ToggleTheme)
// - cv_contact.go: Contact form submission (HandleContact)
// - cv_helpers.go: Helper functions (skills, dates, git, templates, cookies)
type CVHandler struct {
templates *templates.Manager
pdfGenerator *pdf.Generator
emailService *services.EmailService
serverAddr string
}
// NewCVHandler creates a new CV handler
func NewCVHandler(tmpl *templates.Manager, serverAddr string) *CVHandler {
func NewCVHandler(tmpl *templates.Manager, serverAddr string, emailService *services.EmailService) *CVHandler {
return &CVHandler{
templates: tmpl,
pdfGenerator: pdf.NewGenerator(30 * time.Second),
emailService: emailService,
serverAddr: serverAddr,
}
}
+2 -2
View File
@@ -29,7 +29,7 @@ func TestCmdKData(t *testing.T) {
t.Fatalf("Failed to create template manager: %v", err)
}
handler := NewCVHandler(tmplManager, "localhost:8080")
handler := NewCVHandler(tmplManager, "localhost:8080", nil)
tests := []struct {
name string
@@ -207,7 +207,7 @@ func TestCmdKDataCaching(t *testing.T) {
t.Fatalf("Failed to create template manager: %v", err)
}
handler := NewCVHandler(tmplManager, "localhost:8080")
handler := NewCVHandler(tmplManager, "localhost:8080", nil)
req := httptest.NewRequest(http.MethodGet, "/api/cmd-k", nil)
rec := httptest.NewRecorder()
+23 -3
View File
@@ -9,6 +9,7 @@ import (
"time"
uimodel "github.com/juanatsap/cv-site/internal/models/ui"
"github.com/juanatsap/cv-site/internal/services"
)
// ==============================================================================
@@ -81,14 +82,33 @@ func (h *CVHandler) HandleContact(w http.ResponseWriter, r *http.Request) {
return
}
// Log the contact form submission (in production, send email or save to database)
// Log the contact form submission
log.Printf("Contact form submission from %s (IP: %s)", formData.Email, getClientIP(r))
log.Printf(" Name: %s, Company: %s", formData.Name, formData.Company)
log.Printf(" Subject: %s", formData.Subject)
log.Printf(" Message length: %d characters", len(formData.Message))
// TODO: Implement actual email sending or database storage here
// For now, we just log and return success
// Send email via EmailService
if h.emailService != nil {
emailData := &services.ContactFormData{
Email: formData.Email,
Name: formData.Name,
Company: formData.Company,
Subject: formData.Subject,
Message: formData.Message,
IP: getClientIP(r),
Time: time.Now(),
}
if err := h.emailService.SendContactForm(emailData); err != nil {
log.Printf("ERROR sending contact email: %v", err)
h.renderContactError(w, r, "Failed to send message. Please try again later.")
return
}
log.Printf("Contact email sent successfully to configured recipient")
} else {
log.Printf("WARNING: Email service not configured, skipping email send")
}
// Render success response
h.renderContactSuccess(w, r, lang)
+5 -5
View File
@@ -21,7 +21,7 @@ func TestToggleLength(t *testing.T) {
t.Fatalf("Failed to create template manager: %v", err)
}
handler := NewCVHandler(tmplManager, "localhost:8080")
handler := NewCVHandler(tmplManager, "localhost:8080", nil)
tests := []struct {
name string
@@ -94,7 +94,7 @@ func TestToggleIcons(t *testing.T) {
t.Fatalf("Failed to create template manager: %v", err)
}
handler := NewCVHandler(tmplManager, "localhost:8080")
handler := NewCVHandler(tmplManager, "localhost:8080", nil)
tests := []struct {
name string
@@ -152,7 +152,7 @@ func TestSwitchLanguage(t *testing.T) {
t.Fatalf("Failed to create template manager: %v", err)
}
handler := NewCVHandler(tmplManager, "localhost:8080")
handler := NewCVHandler(tmplManager, "localhost:8080", nil)
tests := []struct {
name string
@@ -221,7 +221,7 @@ func TestToggleTheme(t *testing.T) {
t.Fatalf("Failed to create template manager: %v", err)
}
handler := NewCVHandler(tmplManager, "localhost:8080")
handler := NewCVHandler(tmplManager, "localhost:8080", nil)
tests := []struct {
name string
@@ -287,7 +287,7 @@ func TestHTMXHandlersRequirePost(t *testing.T) {
t.Fatalf("Failed to create template manager: %v", err)
}
handler := NewCVHandler(tmplManager, "localhost:8080")
handler := NewCVHandler(tmplManager, "localhost:8080", nil)
tests := []struct {
name string
+3 -3
View File
@@ -23,7 +23,7 @@ func TestHome(t *testing.T) {
}
// Create handler
handler := NewCVHandler(tmplManager, "localhost:8080")
handler := NewCVHandler(tmplManager, "localhost:8080", nil)
tests := []struct {
name string
@@ -95,7 +95,7 @@ func TestCVContent(t *testing.T) {
}
// Create handler
handler := NewCVHandler(tmplManager, "localhost:8080")
handler := NewCVHandler(tmplManager, "localhost:8080", nil)
tests := []struct {
name string
@@ -162,7 +162,7 @@ func TestDefaultCVShortcut(t *testing.T) {
}
// Create handler
handler := NewCVHandler(tmplManager, "localhost:8080")
handler := NewCVHandler(tmplManager, "localhost:8080", nil)
tests := []struct {
name string
+2 -2
View File
@@ -30,7 +30,7 @@ func TestPlainText(t *testing.T) {
t.Fatalf("Failed to create template manager: %v", err)
}
handler := NewCVHandler(tmplManager, "localhost:8080")
handler := NewCVHandler(tmplManager, "localhost:8080", nil)
tests := []struct {
name string
@@ -152,7 +152,7 @@ func TestPlainTextDownloadFilename(t *testing.T) {
t.Fatalf("Failed to create template manager: %v", err)
}
handler := NewCVHandler(tmplManager, "localhost:8080")
handler := NewCVHandler(tmplManager, "localhost:8080", nil)
tests := []struct {
name string
+7 -7
View File
@@ -29,7 +29,7 @@ func TestExportPDF_ParameterValidation(t *testing.T) {
t.Fatalf("Failed to create template manager: %v", err)
}
handler := NewCVHandler(tmpl, "localhost:1999")
handler := NewCVHandler(tmpl, "localhost:1999", nil)
tests := []struct {
name string
@@ -157,7 +157,7 @@ func TestExportPDF_FilenameGeneration(t *testing.T) {
t.Fatalf("Failed to create template manager: %v", err)
}
handler := NewCVHandler(tmpl, "localhost:1999")
handler := NewCVHandler(tmpl, "localhost:1999", nil)
tests := []struct {
name string
@@ -266,7 +266,7 @@ func TestExportPDF_DefaultParameters(t *testing.T) {
t.Fatalf("Failed to create template manager: %v", err)
}
handler := NewCVHandler(tmpl, "localhost:1999")
handler := NewCVHandler(tmpl, "localhost:1999", nil)
// Request with no parameters
req := httptest.NewRequest(http.MethodGet, "/export/pdf", nil)
@@ -298,7 +298,7 @@ func TestExportPDF_LongWithSkills(t *testing.T) {
t.Fatalf("Failed to create template manager: %v", err)
}
handler := NewCVHandler(tmpl, "localhost:1999")
handler := NewCVHandler(tmpl, "localhost:1999", nil)
tests := []struct {
name string
@@ -449,7 +449,7 @@ func TestExportPDF_SkillsSidebarFeatures(t *testing.T) {
t.Fatalf("Failed to create template manager: %v", err)
}
handler := NewCVHandler(tmpl, "localhost:1999")
handler := NewCVHandler(tmpl, "localhost:1999", nil)
validVersions := []string{"clean", "with_skills"}
@@ -484,7 +484,7 @@ func TestExportPDF_SkillsSidebarFeatures(t *testing.T) {
t.Fatalf("Failed to create template manager: %v", err)
}
handler := NewCVHandler(tmpl, "localhost:1999")
handler := NewCVHandler(tmpl, "localhost:1999", nil)
modalTests := []struct {
name string
@@ -604,7 +604,7 @@ func TestExportPDF_CompactFontsIntegration(t *testing.T) {
t.Fatalf("Failed to create template manager: %v", err)
}
handler := NewCVHandler(tmpl, "localhost:1999")
handler := NewCVHandler(tmpl, "localhost:1999", nil)
tests := []struct {
name string
+13 -1
View File
@@ -14,6 +14,7 @@ import (
"github.com/juanatsap/cv-site/internal/config"
"github.com/juanatsap/cv-site/internal/handlers"
"github.com/juanatsap/cv-site/internal/routes"
"github.com/juanatsap/cv-site/internal/services"
"github.com/juanatsap/cv-site/internal/templates"
)
@@ -41,8 +42,19 @@ func main() {
log.Fatalf("❌ Failed to initialize templates: %v", err)
}
// Initialize email service
emailService := services.NewEmailService(&services.EmailConfig{
SMTPHost: cfg.Email.SMTPHost,
SMTPPort: cfg.Email.SMTPPort,
SMTPUser: cfg.Email.SMTPUser,
SMTPPassword: cfg.Email.SMTPPassword,
FromEmail: cfg.Email.FromEmail,
ToEmail: cfg.Email.ContactEmail,
})
log.Printf("📧 Email service configured (SMTP: %s:%s)", cfg.Email.SMTPHost, cfg.Email.SMTPPort)
// Initialize handlers
cvHandler := handlers.NewCVHandler(templateMgr, cfg.Address())
cvHandler := handlers.NewCVHandler(templateMgr, cfg.Address(), emailService)
healthHandler := handlers.NewHealthHandler(version)
// Setup routes and middleware