backend/pkg/notification/repository/smtp_mailer.go

67 lines
1.5 KiB
Go

package repository
import (
"backend/pkg/notification/config"
"backend/pkg/notification/domain"
"backend/pkg/notification/domain/repository"
"context"
"fmt"
"backend/pkg/library/errs"
"backend/pkg/library/errs/code"
"github.com/zeromicro/go-zero/core/logx"
"gopkg.in/gomail.v2"
)
type SMTPMailUseCaseParam struct {
Conf config.SMTPConfig
}
type SMTPMailRepository struct {
Client *gomail.Dialer
}
func MustSMTPUseCase(param SMTPMailUseCaseParam) repository.MailRepository {
return &SMTPMailRepository{
Client: gomail.NewDialer(
param.Conf.Host,
param.Conf.Port,
param.Conf.Username,
param.Conf.Password,
),
}
}
func (repo *SMTPMailRepository) SendMail(ctx context.Context, req repository.MailReq) error {
// 檢查 context 是否已取消
if ctx.Err() != nil {
return ctx.Err()
}
// 構建郵件
m := gomail.NewMessage()
m.SetHeader("From", req.From)
m.SetHeader("To", req.To...)
m.SetHeader("Subject", req.Subject)
m.SetBody("text/html", req.Body)
// 直接發送,不使用 goroutine pool
// 讓 delivery usecase 統一管理重試和超時
if err := repo.Client.DialAndSend(m); err != nil {
return errs.ThirdPartyErrorL(
code.CloudEPNotification,
domain.FailedToSendEmailErrorCode,
logx.WithContext(ctx),
[]logx.LogField{
{Key: "func", Value: "SMTPMailRepository.SendMail"},
{Key: "req", Value: req},
{Key: "err", Value: err.Error()},
},
fmt.Sprintf("failed to send mail by smtp: %v", err)).Wrap(err)
}
logx.WithContext(ctx).Infof("Email sent successfully via SMTP to %v", req.To)
return nil
}