深化smtp文件的支持
This commit is contained in:
+112
-11
@@ -3,11 +3,18 @@ package mailgun
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"code.yun.ink/pkg/mailx/interfaces"
|
||||
"github.com/mailgun/mailgun-go/v4"
|
||||
)
|
||||
|
||||
const (
|
||||
MaxRetries = 3
|
||||
MaxRecipients = 1000 // Mailgun limit
|
||||
)
|
||||
|
||||
type MailGun struct {
|
||||
interfaces.DefaultEmail
|
||||
// params *interfaces.EmialConfigDataMailgun
|
||||
@@ -23,36 +30,130 @@ func NewMailGun() *MailGun {
|
||||
}
|
||||
|
||||
func (l *MailGun) SetOption(ctx context.Context, opt ...interfaces.Option) (interfaces.EmailInterface, error) {
|
||||
|
||||
for _, o := range opt {
|
||||
o(&l.Options)
|
||||
}
|
||||
|
||||
if l.Options.Mailgun == nil {
|
||||
return nil, errors.New("not mailgun")
|
||||
return nil, fmt.Errorf("Mailgun configuration is required")
|
||||
}
|
||||
|
||||
l.Options.Logger.Infof(ctx, "Mailgun:%+v", l.Options.Mailgun)
|
||||
// 验证配置
|
||||
if err := l.validateConfig(); err != nil {
|
||||
return nil, fmt.Errorf("invalid Mailgun config: %w", err)
|
||||
}
|
||||
|
||||
mg := mailgun.NewMailgun(l.Options.Mailgun.Domain, l.Options.Mailgun.ApiKey)
|
||||
// 安全日志输出
|
||||
l.Options.Logger.Infof(ctx, "Mailgun configured - Domain:%s Sender:%s",
|
||||
l.Options.Mailgun.Domain, l.Options.Mailgun.Sender)
|
||||
|
||||
l.mg = mg
|
||||
l.mg = mailgun.NewMailgun(l.Options.Mailgun.Domain, l.Options.Mailgun.ApiKey)
|
||||
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func (l *MailGun) Send(ctx context.Context, params interfaces.Message) error {
|
||||
if l.Options.Mailgun == nil {
|
||||
return errors.New("not init")
|
||||
if l.mg == nil {
|
||||
return fmt.Errorf("Mailgun client not initialized")
|
||||
}
|
||||
|
||||
message := l.mg.NewMessage(l.Options.Mailgun.Sender, params.Subject, params.Body, params.To...)
|
||||
// 验证消息
|
||||
if err := l.validateMessage(params); err != nil {
|
||||
return fmt.Errorf("invalid message: %w", err)
|
||||
}
|
||||
|
||||
// 重试机制
|
||||
var lastErr error
|
||||
for i := 0; i < MaxRetries; i++ {
|
||||
if i > 0 {
|
||||
l.Options.Logger.Infof(ctx, "Retrying Mailgun email send, attempt %d/%d", i+1, MaxRetries)
|
||||
time.Sleep(time.Duration(i) * time.Second)
|
||||
}
|
||||
|
||||
lastErr = l.sendEmail(ctx, params)
|
||||
if lastErr == nil {
|
||||
l.Options.Logger.Infof(ctx, "Mailgun email sent successfully to %v", params.To)
|
||||
return nil
|
||||
}
|
||||
|
||||
l.Options.Logger.Errorf(ctx, "Mailgun send attempt %d failed: %v", i+1, lastErr)
|
||||
}
|
||||
|
||||
return fmt.Errorf("failed to send Mailgun email after %d attempts: %w", MaxRetries, lastErr)
|
||||
}
|
||||
|
||||
// 验证配置
|
||||
func (l *MailGun) validateConfig() error {
|
||||
if l.Options.Mailgun.Domain == "" {
|
||||
return errors.New("Domain is required")
|
||||
}
|
||||
if l.Options.Mailgun.ApiKey == "" {
|
||||
return errors.New("ApiKey is required")
|
||||
}
|
||||
if l.Options.Mailgun.Sender == "" {
|
||||
return errors.New("Sender is required")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 验证消息
|
||||
func (l *MailGun) validateMessage(params interfaces.Message) error {
|
||||
if len(params.To) == 0 {
|
||||
return errors.New("at least one recipient is required")
|
||||
}
|
||||
if len(params.To) > MaxRecipients {
|
||||
return fmt.Errorf("too many recipients: %d (max: %d)", len(params.To), MaxRecipients)
|
||||
}
|
||||
if params.Subject == "" {
|
||||
return errors.New("subject is required")
|
||||
}
|
||||
if params.Body == "" {
|
||||
return errors.New("body is required")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 发送邮件核心逻辑
|
||||
func (l *MailGun) sendEmail(ctx context.Context, params interfaces.Message) error {
|
||||
// 创建邮件消息
|
||||
message := l.mg.NewMessage(l.Options.Mailgun.Sender, params.Subject, "", params.To...)
|
||||
|
||||
// 设置HTML内容
|
||||
message.SetHtml(params.Body)
|
||||
|
||||
// 设置Cc收件人
|
||||
for _, cc := range params.Cc {
|
||||
message.AddCC(cc)
|
||||
}
|
||||
|
||||
// 设置Bcc收件人
|
||||
for _, bcc := range params.Bcc {
|
||||
message.AddBCC(bcc)
|
||||
}
|
||||
|
||||
// 设置回复地址
|
||||
if params.ReplyTo != "" {
|
||||
message.SetReplyTo(params.ReplyTo)
|
||||
}
|
||||
|
||||
// 设置发件人名称
|
||||
if params.Form != "" {
|
||||
//
|
||||
}
|
||||
|
||||
// 添加附件
|
||||
for _, attachment := range params.Attachment {
|
||||
message.AddAttachment(attachment.Content)
|
||||
}
|
||||
|
||||
// 发送邮件
|
||||
resp, id, err := l.mg.Send(ctx, message)
|
||||
if err != nil {
|
||||
l.Options.Logger.Errorf(ctx, "Could not send email: %v, resp message: %s, id: %s", err, resp, id)
|
||||
return err
|
||||
return fmt.Errorf("Mailgun API call failed: %w", err)
|
||||
}
|
||||
|
||||
return err
|
||||
// 记录响应信息
|
||||
l.Options.Logger.Infof(ctx, "Mailgun email sent - ID:%s Response:%s", id, resp)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user