package mailer import ( "bytes" "fmt" "text/template" "time" "github.com/sendgrid/sendgrid-go" "github.com/sendgrid/sendgrid-go/helpers/mail" ) type SendGridMailer struct { fromEmail string apiKey string client *sendgrid.Client } func NewSendGrid(apiKey, fromEmail string) *SendGridMailer { client := sendgrid.NewSendClient(apiKey) return &SendGridMailer{ fromEmail: fromEmail, apiKey: apiKey, client: client, } } func (s *SendGridMailer) Send(templateFile, username, email string, data any, isDevEnv bool) (int, error) { from := mail.NewEmail(FromName, s.fromEmail) to := mail.NewEmail(username, email) tmpl, err := template.ParseFS(FS, "templates/"+templateFile) if err != nil { return -1, err } // Template Parsing and sending subject := new(bytes.Buffer) if err := tmpl.ExecuteTemplate(subject, "subject", data); err != nil { return -1, err } body := new(bytes.Buffer) if err := tmpl.ExecuteTemplate(body, "body", data); err != nil { return -1, err } message := mail.NewSingleEmail(from, subject.String(), to, "", body.String()) message.SetMailSettings(&mail.MailSettings{ SandboxMode: &mail.Setting{ Enable: &isDevEnv, }, }) var retryErr error for i := 0; i < maxRetries; i++ { resp, retryErr := s.client.Send(message) if retryErr != nil { //* Exponential backoff time.Sleep(time.Duration(i+1) * time.Second) continue } return resp.StatusCode, nil } return -1, fmt.Errorf("failed to send the email after %d attempts, error: %v", maxRetries, retryErr) }