mirror of
				https://github.com/cloudreve/cloudreve.git
				synced 2025-11-01 00:57:15 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			114 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			114 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package email
 | ||
| 
 | ||
| import (
 | ||
| 	"github.com/HFO4/cloudreve/pkg/util"
 | ||
| 	"github.com/go-mail/mail"
 | ||
| 	"time"
 | ||
| )
 | ||
| 
 | ||
| // SMTP SMTP协议发送邮件
 | ||
| type SMTP struct {
 | ||
| 	Config SMTPConfig
 | ||
| 	ch     chan *mail.Message
 | ||
| 	chOpen bool
 | ||
| }
 | ||
| 
 | ||
| // SMTPConfig SMTP发送配置
 | ||
| type SMTPConfig struct {
 | ||
| 	Name       string // 发送者名
 | ||
| 	Address    string // 发送者地址
 | ||
| 	ReplyTo    string // 回复地址
 | ||
| 	Host       string // 服务器主机名
 | ||
| 	Port       int    // 服务器端口
 | ||
| 	User       string // 用户名
 | ||
| 	Password   string // 密码
 | ||
| 	Encryption string // 是否启用加密
 | ||
| 	Keepalive  int    // SMTP 连接保留时长
 | ||
| }
 | ||
| 
 | ||
| // NewSMTPClient 新建SMTP发送队列
 | ||
| func NewSMTPClient(config SMTPConfig) *SMTP {
 | ||
| 	client := &SMTP{
 | ||
| 		Config: config,
 | ||
| 		ch:     make(chan *mail.Message, 30),
 | ||
| 		chOpen: false,
 | ||
| 	}
 | ||
| 
 | ||
| 	client.Init()
 | ||
| 
 | ||
| 	return client
 | ||
| }
 | ||
| 
 | ||
| // Send 发送邮件
 | ||
| func (client *SMTP) Send(to, title, body string) error {
 | ||
| 	if !client.chOpen {
 | ||
| 		return ErrChanNotOpen
 | ||
| 	}
 | ||
| 	m := mail.NewMessage()
 | ||
| 	m.SetAddressHeader("From", client.Config.Address, client.Config.Name)
 | ||
| 	m.SetAddressHeader("Reply-To", client.Config.ReplyTo, client.Config.Name)
 | ||
| 	m.SetHeader("To", to)
 | ||
| 	m.SetHeader("Subject", title)
 | ||
| 	m.SetBody("text/html", body)
 | ||
| 	client.ch <- m
 | ||
| 	return nil
 | ||
| }
 | ||
| 
 | ||
| // Close 关闭发送队列
 | ||
| func (client *SMTP) Close() {
 | ||
| 	if client.ch != nil {
 | ||
| 		close(client.ch)
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| // Init 初始化发送队列
 | ||
| func (client *SMTP) Init() {
 | ||
| 	go func() {
 | ||
| 		defer func() {
 | ||
| 			if err := recover(); err != nil {
 | ||
| 				client.chOpen = false
 | ||
| 				util.Log().Error("邮件发送队列出现异常, %s ,10 秒后重置", err)
 | ||
| 				time.Sleep(time.Duration(10) * time.Second)
 | ||
| 				client.Init()
 | ||
| 			}
 | ||
| 		}()
 | ||
| 
 | ||
| 		d := mail.NewDialer(client.Config.Host, client.Config.Port, client.Config.User, client.Config.Password)
 | ||
| 		d.Timeout = time.Duration(client.Config.Keepalive+5) * time.Second
 | ||
| 		client.chOpen = true
 | ||
| 
 | ||
| 		var s mail.SendCloser
 | ||
| 		var err error
 | ||
| 		open := false
 | ||
| 		for {
 | ||
| 			select {
 | ||
| 			case m, ok := <-client.ch:
 | ||
| 				if !ok {
 | ||
| 					util.Log().Debug("邮件队列关闭")
 | ||
| 					client.chOpen = false
 | ||
| 					return
 | ||
| 				}
 | ||
| 				if !open {
 | ||
| 					if s, err = d.Dial(); err != nil {
 | ||
| 						panic(err)
 | ||
| 					}
 | ||
| 					open = true
 | ||
| 				}
 | ||
| 				if err := mail.Send(s, m); err != nil {
 | ||
| 					util.Log().Warning("邮件发送失败, %s", err)
 | ||
| 				} else {
 | ||
| 					util.Log().Debug("邮件已发送")
 | ||
| 				}
 | ||
| 			// 长时间没有新邮件,则关闭SMTP连接
 | ||
| 			case <-time.After(time.Duration(client.Config.Keepalive) * time.Second):
 | ||
| 				if open {
 | ||
| 					if err := s.Close(); err != nil {
 | ||
| 						util.Log().Warning("无法关闭 SMTP 连接 %s", err)
 | ||
| 					}
 | ||
| 					open = false
 | ||
| 				}
 | ||
| 			}
 | ||
| 		}
 | ||
| 	}()
 | ||
| }
 | 
