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 }