Feat: cron / Fix: users status check
This commit is contained in:
38
pkg/email/init.go
Normal file
38
pkg/email/init.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package email
|
||||
|
||||
import model "github.com/HFO4/cloudreve/models"
|
||||
|
||||
// Client 默认的邮件发送客户端
|
||||
var Client Driver
|
||||
|
||||
// Init 初始化
|
||||
func Init() {
|
||||
if Client != nil {
|
||||
Client.Close()
|
||||
}
|
||||
|
||||
// 读取SMTP设置
|
||||
options := model.GetSettingByNames(
|
||||
"fromName",
|
||||
"fromAdress",
|
||||
"smtpHost",
|
||||
"replyTo",
|
||||
"smtpUser",
|
||||
"smtpPass",
|
||||
)
|
||||
port := model.GetIntSetting("smtpPort", 25)
|
||||
keepAlive := model.GetIntSetting("mail_keepalive", 30)
|
||||
|
||||
client := NewSMTPClient(SMTPConfig{
|
||||
Name: options["fromName"],
|
||||
Address: options["fromAdress"],
|
||||
ReplyTo: options["replyTo"],
|
||||
Host: options["smtpHost"],
|
||||
Port: port,
|
||||
User: options["smtpUser"],
|
||||
Password: options["smtpPass"],
|
||||
Keepalive: keepAlive,
|
||||
})
|
||||
|
||||
Client = client
|
||||
}
|
||||
27
pkg/email/mail.go
Normal file
27
pkg/email/mail.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package email
|
||||
|
||||
import "errors"
|
||||
|
||||
// Driver 邮件发送驱动
|
||||
type Driver interface {
|
||||
// Close 关闭驱动
|
||||
Close()
|
||||
// Send 发送邮件
|
||||
Send(to, title, body string) error
|
||||
}
|
||||
|
||||
var (
|
||||
// ErrChanNotOpen 邮件队列未开启
|
||||
ErrChanNotOpen = errors.New("邮件队列未开启")
|
||||
// ErrNoActiveDriver 无可用邮件发送服务
|
||||
ErrNoActiveDriver = errors.New("无可用邮件发送服务")
|
||||
)
|
||||
|
||||
// Send 发送邮件
|
||||
func Send(to, title, body string) error {
|
||||
if Client == nil {
|
||||
return ErrNoActiveDriver
|
||||
}
|
||||
|
||||
return Client.Send(to, title, body)
|
||||
}
|
||||
111
pkg/email/smtp.go
Normal file
111
pkg/email/smtp.go
Normal file
@@ -0,0 +1,111 @@
|
||||
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.SetHeader("From", client.Config.Address)
|
||||
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 ,30 秒后重新连接", err)
|
||||
time.Sleep(time.Duration(30) * 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 {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
21
pkg/email/template.go
Normal file
21
pkg/email/template.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package email
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
model "github.com/HFO4/cloudreve/models"
|
||||
"github.com/HFO4/cloudreve/pkg/util"
|
||||
)
|
||||
|
||||
// NewOveruseNotification 新建超额提醒邮件
|
||||
func NewOveruseNotification(userName, reason string) (string, string) {
|
||||
options := model.GetSettingByNames("siteName", "siteURL", "siteTitle", "over_used_template")
|
||||
replace := map[string]string{
|
||||
"{siteTitle}": options["siteName"],
|
||||
"{userName}": userName,
|
||||
"{notifyReason}": reason,
|
||||
"{siteUrl}": options["siteURL"],
|
||||
"{siteSecTitle}": options["siteTitle"],
|
||||
}
|
||||
return fmt.Sprintf("【%s】空间容量超额提醒", options["siteName"]),
|
||||
util.Replace(replace, options["over_used_template"])
|
||||
}
|
||||
Reference in New Issue
Block a user