package snailmail import ( "bytes" "encoding/json" "fmt" "io" "log" "net/http" ) type cloudflareSender struct{} type cfEmailRequest struct { To string `json:"to"` From string `json:"from"` Subject string `json:"subject"` HTML string `json:"html,omitempty"` Text string `json:"text,omitempty"` } type cfEmailResponse struct { Success bool `json:"success"` Errors []struct { Code int `json:"code"` Message string `json:"message"` } `json:"errors"` } func (c *cloudflareSender) Send(message Email, mailtype int) error { if len(message.Recipients) == 0 { return fmt.Errorf("cloudflare email: no recipients") } req := cfEmailRequest{ To: message.Recipients[0], From: settings.Cloudflare.FromAddress, Subject: message.Subject, } if mailtype == TYPE_HTML { req.HTML = message.Body.String() } else { req.Text = message.Body.String() } body, err := json.Marshal(req) if err != nil { return fmt.Errorf("cloudflare email: failed to marshal request: %w", err) } url := fmt.Sprintf("https://api.cloudflare.com/client/v4/accounts/%s/email/sending/send", settings.Cloudflare.AccountID) httpReq, err := http.NewRequest("POST", url, bytes.NewReader(body)) if err != nil { return fmt.Errorf("cloudflare email: failed to create request: %w", err) } httpReq.Header.Set("Authorization", "Bearer "+settings.Cloudflare.APIToken) httpReq.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(httpReq) if err != nil { log.Println("cloudflare email: request failed:", err) return fmt.Errorf("cloudflare email: request failed: %w", err) } defer resp.Body.Close() respBody, err := io.ReadAll(resp.Body) if err != nil { return fmt.Errorf("cloudflare email: failed to read response: %w", err) } var cfResp cfEmailResponse if err := json.Unmarshal(respBody, &cfResp); err != nil { return fmt.Errorf("cloudflare email: failed to parse response: %w", err) } if !cfResp.Success { errMsg := "unknown error" if len(cfResp.Errors) > 0 { errMsg = cfResp.Errors[0].Message } log.Printf("cloudflare email: send failed: %s (HTTP %d)", errMsg, resp.StatusCode) return fmt.Errorf("cloudflare email: %s", errMsg) } return nil }