145 lines
3.3 KiB
Go
145 lines
3.3 KiB
Go
package mailclient
|
|
|
|
import (
|
|
"bytes"
|
|
_ "embed"
|
|
"fmt"
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/themakers/hlog"
|
|
"mime/multipart"
|
|
"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/model"
|
|
"strings"
|
|
"text/template"
|
|
)
|
|
|
|
type ClientDeps struct {
|
|
Host string
|
|
Port string
|
|
Sender string
|
|
Auth *PlainAuth
|
|
ApiKey string
|
|
FiberClient *fiber.Client
|
|
Logger hlog.Logger
|
|
}
|
|
|
|
type Client struct {
|
|
deps ClientDeps
|
|
}
|
|
|
|
type PlainAuth struct {
|
|
Identity string
|
|
Username string
|
|
Password string
|
|
}
|
|
|
|
type EmailTemplateData struct {
|
|
QuizConfig model.ResultInfo
|
|
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 {
|
|
text, err := generateTextFromTemplate(data, emailTemplate)
|
|
if err != nil {
|
|
c.deps.Logger.Module("Error generate text from template")
|
|
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 {
|
|
url := "https://api.smtp.bz/v1/smtp/send"
|
|
|
|
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 {
|
|
c.deps.Logger.Module("Error creating form fields")
|
|
return err
|
|
}
|
|
}
|
|
|
|
for _, attachment := range msg.Attachments {
|
|
part, err := writer.CreateFormFile("attachments", attachment.Name)
|
|
if err != nil {
|
|
c.deps.Logger.Module("Error creating form file for attachment")
|
|
return err
|
|
}
|
|
_, err = part.Write(attachment.Data)
|
|
if err != nil {
|
|
c.deps.Logger.Module("Error writing attachment content")
|
|
return err
|
|
}
|
|
}
|
|
|
|
if err := writer.Close(); err != nil {
|
|
c.deps.Logger.Module("Error closing writer for multipart form")
|
|
return err
|
|
}
|
|
|
|
agent := c.deps.FiberClient.Post(url).Body(form.Bytes()).ContentType(writer.FormDataContentType())
|
|
if c.deps.ApiKey != "" {
|
|
agent.Set("Authorization", c.deps.ApiKey)
|
|
}
|
|
|
|
statusCode, body, errs := agent.Bytes()
|
|
if errs != nil {
|
|
c.deps.Logger.Module("Error sending request")
|
|
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").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,
|
|
}); err != nil {
|
|
return "", fmt.Errorf("error executing template: %w", err)
|
|
}
|
|
|
|
return text.String(), nil
|
|
}
|