worker/clients/mailclient/client.go
2025-02-27 16:04:47 +03:00

134 lines
3.0 KiB
Go

package mailclient
import (
"bytes"
_ "embed"
"fmt"
"github.com/gofiber/fiber/v2"
"html/template"
"mime/multipart"
"gitea.pena/SQuiz/common/model"
"strings"
)
type ClientDeps struct {
Host string
Port string
Sender string
ApiKey string
SmtpApiUrl string
FiberClient *fiber.Client
}
type Client struct {
deps ClientDeps
}
type EmailTemplateData struct {
QuizConfig model.ResultInfo
QuizID uint64
AnswerContent model.ResultContent
AllAnswers []model.ResultAnswer
QuestionsMap map[uint64]string
AnswerTime string
}
func NewClient(deps ClientDeps) *Client {
if deps.FiberClient == nil {
deps.FiberClient = fiber.AcquireClient()
}
return &Client{
deps: deps,
}
}
func (c *Client) SendMailWithAttachment(recipient, subject string, emailTemplate string, data EmailTemplateData, attachments []Attachment) error {
sanitizedData := sanitizeHTMLData(data)
text, err := generateTextFromTemplate(sanitizedData, emailTemplate)
if err != nil {
return err
}
msg := &Message{
From: c.deps.Sender,
To: []string{recipient},
Subject: subject,
Body: text,
Attachments: attachments,
}
return c.Send(msg)
}
func (c *Client) Send(msg *Message) error {
form := new(bytes.Buffer)
writer := multipart.NewWriter(form)
defer writer.Close()
fields := map[string]string{
"from": msg.From,
"to": strings.Join(msg.To, ","),
"subject": msg.Subject,
"html": msg.Body,
}
for key, value := range fields {
if err := writer.WriteField(key, value); err != nil {
return err
}
}
// пока не используется так как Attachments из воркеров = nil, нужен ли будет потом
for _, attachment := range msg.Attachments {
part, err := writer.CreateFormFile("attachments", attachment.Name)
if err != nil {
return err
}
_, err = part.Write(attachment.Data)
if err != nil {
return err
}
}
if err := writer.Close(); err != nil {
return err
}
agent := c.deps.FiberClient.Post(c.deps.SmtpApiUrl).Body(form.Bytes()).ContentType(writer.FormDataContentType())
if c.deps.ApiKey != "" {
agent.Set("Authorization", c.deps.ApiKey)
}
statusCode, body, errs := agent.Bytes()
if errs != nil {
return errs[0]
}
if statusCode != fiber.StatusOK {
return fmt.Errorf("SMTP service returned error: %d, Response body: %s", statusCode, body)
}
return nil
}
func generateTextFromTemplate(data EmailTemplateData, tpl string) (string, error) {
t, err := template.New("email").Funcs(tmplFuncs).Parse(tpl)
if err != nil {
return "", fmt.Errorf("error parsing template: %w", err)
}
var text bytes.Buffer
if err := t.Execute(&text, EmailTemplateData{
QuizConfig: data.QuizConfig,
AnswerContent: data.AnswerContent,
AllAnswers: data.AllAnswers,
QuestionsMap: data.QuestionsMap,
AnswerTime: data.AnswerTime,
QuizID: data.QuizID,
}); err != nil {
return "", fmt.Errorf("error executing template: %w", err)
}
return text.String(), nil
}