package email import ( "bytes" "encoding/base64" "encoding/json" "fmt" "io" "net/http" "os" "time" ) // resendEndpoint Resend 发信 API(走 HTTPS/443,规避国内出口 SMTP 被限速/信誉差导致的海外送达率问题)。 const resendEndpoint = "https://api.resend.com/emails" // Resend 通过 Resend HTTP API 发信,实现 ISys。 // 复用 Options.Password 承载 API Key(re_ 开头);Options.FromEmail 须为在 Resend 已验证域名下的发件地址。 type Resend struct { ApiKey string From string Name string } // resendAttachment Resend 附件:内容为 base64 编码。 type resendAttachment struct { Filename string `json:"filename"` Content string `json:"content"` } // resendPayload Resend /emails 请求体。 type resendPayload struct { From string `json:"from"` To []string `json:"to"` Subject string `json:"subject"` Html string `json:"html"` Attachments []resendAttachment `json:"attachments,omitempty"` } var resendClient = &http.Client{Timeout: 15 * time.Second} // fromAddr 拼成 "昵称 <邮箱>"(无昵称则仅邮箱)。 func (this *Resend) fromAddr() string { if this.Name != "" { return fmt.Sprintf("%s <%s>", this.Name, this.From) } return this.From } // send 提交一次发信请求,非 2xx 视为失败并带回响应体。 func (this *Resend) send(p *resendPayload) error { body, err := json.Marshal(p) if err != nil { return err } req, err := http.NewRequest(http.MethodPost, resendEndpoint, bytes.NewReader(body)) if err != nil { return err } req.Header.Set("Authorization", "Bearer "+this.ApiKey) req.Header.Set("Content-Type", "application/json") resp, err := resendClient.Do(req) if err != nil { return err } defer resp.Body.Close() rb, _ := io.ReadAll(resp.Body) if resp.StatusCode < 200 || resp.StatusCode >= 300 { return fmt.Errorf("resend send failed: status=%d body=%s", resp.StatusCode, string(rb)) } return nil } // SendMail 发送 HTML 邮件。 func (this *Resend) SendMail(title, content string, to ...string) error { return this.send(&resendPayload{ From: this.fromAddr(), To: to, Subject: title, Html: content, }) } // SendMailForFile 发送带单个附件的 HTML 邮件。 func (this *Resend) SendMailForFile(title string, content string, filepath string, filename string, to ...string) (err error) { data, err := os.ReadFile(filepath) if err != nil { return err } return this.send(&resendPayload{ From: this.fromAddr(), To: to, Subject: title, Html: content, Attachments: []resendAttachment{{ Filename: filename, Content: base64.StdEncoding.EncodeToString(data), }}, }) }