package clients import ( "bytes" "fmt" "github.com/gofiber/fiber/v2" "go.uber.org/zap" "html/template" "mime/multipart" "os" ) type Deps struct { SmtpApiUrl string SmtpHost string SmtpPort string SmtpSender string Username string Password string ApiKey string FiberClient *fiber.Client Logger *zap.Logger } type MailClient struct { deps Deps } func NewMailClient(deps Deps) *MailClient { if deps.FiberClient == nil { deps.FiberClient = fiber.AcquireClient() } return &MailClient{ deps: deps, } } type SenderDeps struct { Subject string Email string TmplPath string } func (m *MailClient) MailSender(data SenderDeps) error { tmplContent, err := os.ReadFile(data.TmplPath) if err != nil { m.deps.Logger.Error("Error reading template file", zap.Error(err)) return err } tmpl, err := template.New("email").Parse(string(tmplContent)) if err != nil { m.deps.Logger.Error("Error parsing HTML template", zap.Error(err)) return err } var buf bytes.Buffer if err := tmpl.Execute(&buf, nil); err != nil { m.deps.Logger.Error("Error executing template", zap.Error(err)) return err } htmlBody := buf.String() form := new(bytes.Buffer) writer := multipart.NewWriter(form) defer writer.Close() fields := map[string]string{ "from": m.deps.SmtpSender, "to": data.Email, "subject": data.Subject, "html": htmlBody, } for key, value := range fields { if err := writer.WriteField(key, value); err != nil { return err } } if err := writer.Close(); err != nil { return err } req := m.deps.FiberClient.Post(m.deps.SmtpApiUrl).Body(form.Bytes()).ContentType(writer.FormDataContentType()) if m.deps.ApiKey != "" { req.Set("Authorization", m.deps.ApiKey) } statusCode, body, errs := req.Bytes() if errs != nil { m.deps.Logger.Error("Error sending request", zap.Error(errs[0])) return errs[0] } if statusCode != fiber.StatusOK { err := fmt.Errorf("the SMTP service returned an error: %s Response body: %s", statusCode, body) m.deps.Logger.Error("Error sending email", zap.Error(err)) return err } return nil }