You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
synctv/internal/email/smtp.go

170 lines
3.5 KiB
Go

package email
import (
"errors"
"strings"
"sync"
"github.com/synctv-org/synctv/internal/model"
"github.com/synctv-org/synctv/internal/settings"
"github.com/synctv-org/synctv/utils/smtp"
)
var (
smtpPool *smtp.Pool
configChanged bool
lock sync.Mutex
)
var (
smtpHost = settings.NewStringSetting(
"smtp_host",
"",
model.SettingGroupEmail,
settings.WithAfterSetString(func(ss settings.StringSetting, s string) {
lock.Lock()
defer lock.Unlock()
configChanged = true
}),
)
// Generally speaking, TLS uses port 587 and SSL uses port 465.
smtpPort = settings.NewInt64Setting(
"smtp_port",
587,
model.SettingGroupEmail,
settings.WithValidatorInt64(func(i int64) error {
if i <= 0 {
return errors.New("smtp port must be greater than 0")
}
if i > 65535 {
return errors.New("smtp port must be less than 65535")
}
return nil
}),
settings.WithAfterSetInt64(func(ss settings.Int64Setting, i int64) {
lock.Lock()
defer lock.Unlock()
configChanged = true
}),
)
smtpProtocol = settings.NewStringSetting(
"smtp_protocol",
"TLS",
model.SettingGroupEmail,
settings.WithValidatorString(func(s string) error {
s = strings.ToLower(s)
switch s {
case "tcp", "tls", "ssl", "":
return nil
default:
return errors.New("smtp protocol must be tcp, tls or ssl")
}
}),
settings.WithAfterSetString(func(ss settings.StringSetting, s string) {
lock.Lock()
defer lock.Unlock()
configChanged = true
}),
)
smtpUsername = settings.NewStringSetting(
"smtp_username",
"",
model.SettingGroupEmail,
settings.WithAfterSetString(func(ss settings.StringSetting, s string) {
lock.Lock()
defer lock.Unlock()
configChanged = true
}),
)
smtpPassword = settings.NewStringSetting(
"smtp_password",
"",
model.SettingGroupEmail,
settings.WithAfterSetString(func(ss settings.StringSetting, s string) {
lock.Lock()
defer lock.Unlock()
configChanged = true
}),
)
smtpFrom = settings.NewStringSetting(
"smtp_from",
"",
model.SettingGroupEmail,
settings.WithAfterSetString(func(ss settings.StringSetting, s string) {
lock.Lock()
defer lock.Unlock()
if smtpPool != nil {
smtpPool.SetFrom(s)
}
}),
)
smtpPoolSize = settings.NewInt64Setting(
"smtp_pool_size",
10,
model.SettingGroupEmail,
settings.WithValidatorInt64(func(i int64) error {
if i <= 0 {
return errors.New("smtp pool size must be greater than 0")
}
if i > 100 {
return errors.New("smtp pool size must be less than 100")
}
return nil
}),
settings.WithAfterSetInt64(func(ss settings.Int64Setting, i int64) {
lock.Lock()
defer lock.Unlock()
configChanged = true
}),
)
)
func newSmtpConfig() *smtp.Config {
return &smtp.Config{
Host: smtpHost.Get(),
Port: uint32(smtpPort.Get()),
Protocol: smtpProtocol.Get(),
Username: smtpUsername.Get(),
Password: smtpPassword.Get(),
From: smtpFrom.Get(),
}
}
func newSmtpPool() (*smtp.Pool, error) {
return smtp.NewSMTPPool(newSmtpConfig(), int(smtpPoolSize.Get()))
}
func getSmtpPool() (*smtp.Pool, error) {
lock.Lock()
defer lock.Unlock()
if configChanged {
configChanged = false
if smtpPool != nil {
smtpPool.Close()
smtpPool = nil
}
}
if smtpPool == nil {
pool, err := newSmtpPool()
if err != nil {
return nil, err
}
smtpPool = pool
}
return smtpPool, nil
}
func closeSmtpPool() {
lock.Lock()
defer lock.Unlock()
if smtpPool != nil {
smtpPool.Close()
smtpPool = nil
}
}