Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion internal/api/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import (
type SendRequest struct {
From string `json:"from"`
To []string `json:"to"`
CC []string `json:"cc,omitempty"`
BCC []string `json:"bcc,omitempty"`
Subject string `json:"subject"`
Body string `json:"body"`
HTML string `json:"html,omitempty"`
Expand Down Expand Up @@ -99,6 +101,18 @@ func (s *Server) handleSend(w http.ResponseWriter, r *http.Request) {
return
}
}
for _, cc := range req.CC {
if _, err := mail.ParseAddress(cc); err != nil {
s.sendError(w, http.StatusBadRequest, fmt.Sprintf("invalid cc address: %s", cc))
return
}
}
for _, bcc := range req.BCC {
if _, err := mail.ParseAddress(bcc); err != nil {
s.sendError(w, http.StatusBadRequest, fmt.Sprintf("invalid bcc address: %s", bcc))
return
}
}
if req.Subject == "" && req.Body == "" && req.HTML == "" {
s.sendError(w, http.StatusBadRequest, "subject, body or html is required")
return
Expand All @@ -118,11 +132,17 @@ func (s *Server) handleSend(w http.ResponseWriter, r *http.Request) {
// Build email data (RFC 5322)
data := s.buildEmailData(&req)

// Envelope recipients = To + CC + BCC
envelopeTo := make([]string, 0, len(req.To)+len(req.CC)+len(req.BCC))
envelopeTo = append(envelopeTo, req.To...)
envelopeTo = append(envelopeTo, req.CC...)
envelopeTo = append(envelopeTo, req.BCC...)

// Create message
msg := &queue.Message{
ID: uuid.New().String(),
From: req.From,
To: req.To,
To: envelopeTo,
Data: data,
Status: queue.StatusPending,
CreatedAt: time.Now(),
Expand Down Expand Up @@ -254,6 +274,9 @@ func (s *Server) buildEmailData(req *SendRequest) []byte {
// Headers
buf.WriteString(fmt.Sprintf("From: %s\r\n", req.From))
buf.WriteString(fmt.Sprintf("To: %s\r\n", strings.Join(req.To, ", ")))
if len(req.CC) > 0 {
buf.WriteString(fmt.Sprintf("Cc: %s\r\n", strings.Join(req.CC, ", ")))
}
buf.WriteString(fmt.Sprintf("Subject: %s\r\n", req.Subject))
buf.WriteString(fmt.Sprintf("Date: %s\r\n", time.Now().Format(time.RFC1123Z)))
buf.WriteString(fmt.Sprintf("Message-ID: <%s@%s>\r\n", uuid.New().String(), email.ExtractDomainOrDefault(req.From, "localhost")))
Expand Down
15 changes: 12 additions & 3 deletions internal/api/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -413,13 +413,19 @@ func (s *TemplateServer) handleSendTemplate(w http.ResponseWriter, r *http.Reque
}

// Build email data
data := s.buildEmailData(req.From, req.To, result.Subject, result.Text, result.HTML, req.Headers)
data := s.buildEmailData(req.From, req.To, req.CC, result.Subject, result.Text, result.HTML, req.Headers)

// Envelope recipients = To + CC + BCC
envelopeTo := make([]string, 0, len(req.To)+len(req.CC)+len(req.BCC))
envelopeTo = append(envelopeTo, req.To...)
envelopeTo = append(envelopeTo, req.CC...)
envelopeTo = append(envelopeTo, req.BCC...)

// Create message
msg := &queue.Message{
ID: uuid.New().String(),
From: req.From,
To: req.To,
To: envelopeTo,
Data: data,
Status: queue.StatusPending,
CreatedAt: time.Now(),
Expand All @@ -440,12 +446,15 @@ func (s *TemplateServer) handleSendTemplate(w http.ResponseWriter, r *http.Reque
}

// buildEmailData constructs RFC 5322 email data
func (s *TemplateServer) buildEmailData(from string, to []string, subject, text, html string, headers map[string]string) []byte {
func (s *TemplateServer) buildEmailData(from string, to []string, cc []string, subject, text, html string, headers map[string]string) []byte {
var buf bytes.Buffer

// Headers
buf.WriteString(fmt.Sprintf("From: %s\r\n", from))
buf.WriteString(fmt.Sprintf("To: %s\r\n", strings.Join(to, ", ")))
if len(cc) > 0 {
buf.WriteString(fmt.Sprintf("Cc: %s\r\n", strings.Join(cc, ", ")))
}
buf.WriteString(fmt.Sprintf("Subject: %s\r\n", subject))
buf.WriteString(fmt.Sprintf("Date: %s\r\n", time.Now().Format(time.RFC1123Z)))
buf.WriteString(fmt.Sprintf("Message-ID: <%s@%s>\r\n", uuid.New().String(), email.ExtractDomainOrDefault(from, "localhost")))
Expand Down
Loading