package email import ( "bytes" "encoding/json" "errors" "net/http" "time" "github.com/spf13/viper" ) type Client struct { apiKey string http *http.Client } // Resend service client func NewResendClient() (*Client, error) { key := viper.GetString("email.resend_api_key") if key == "" { return nil, errors.New("RESEND_API_KEY not set") } return &Client{ apiKey: key, http: &http.Client{ Timeout: 10 * time.Second, }, }, nil } type sendEmailRequest struct { From string `json:"from"` To []string `json:"to"` Subject string `json:"subject"` HTML string `json:"html,omitempty"` Text string `json:"text,omitempty"` } type sendEmailResponse struct { ID string `json:"id"` } // Send email by resend API func (c *Client) Send(to, subject, html string) (string, error) { reqBody := sendEmailRequest{ From: viper.GetString("email.from"), To: []string{to}, Subject: subject, HTML: html, } body, err := json.Marshal(reqBody) if err != nil { return "", err } req, err := http.NewRequest( http.MethodPost, "https://api.resend.com/emails", bytes.NewReader(body), ) if err != nil { return "", err } req.Header.Set("Authorization", "Bearer "+c.apiKey) req.Header.Set("Content-Type", "application/json") resp, err := c.http.Do(req) if err != nil { return "", err } defer resp.Body.Close() if resp.StatusCode >= 300 { return "", errors.New("resend send failed") } var res sendEmailResponse if err := json.NewDecoder(resp.Body).Decode(&res); err != nil { return "", err } return res.ID, nil }