This introduces the new value `auto` for NOTIFICATIONS_SMTP_AUTHENTICATION. Which will make the notifications service automatically pick an authentication mechanism that the server supports. This is also the new default behavior. This also removes most of the other default settings for the SMTP configuration. The default values were of no real use for this service. Closes: #7356
132 lines
3.6 KiB
Go
132 lines
3.6 KiB
Go
// Package channels provides different communication channels to notify users.
|
|
package channels
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
|
"github.com/owncloud/ocis/v2/services/notifications/pkg/config"
|
|
"github.com/pkg/errors"
|
|
mail "github.com/xhit/go-simple-mail/v2"
|
|
)
|
|
|
|
// Channel defines the methods of a communication channel.
|
|
type Channel interface {
|
|
// SendMessage sends a message to users.
|
|
SendMessage(ctx context.Context, message *Message) error
|
|
}
|
|
|
|
// Message represent the already rendered message including the user id opaqueID
|
|
type Message struct {
|
|
Sender string
|
|
Recipient []string
|
|
Subject string
|
|
TextBody string
|
|
HTMLBody string
|
|
AttachInline map[string][]byte
|
|
}
|
|
|
|
// NewMailChannel instantiates a new mail communication channel.
|
|
func NewMailChannel(cfg config.Config, logger log.Logger) (Channel, error) {
|
|
return Mail{
|
|
conf: cfg,
|
|
logger: logger,
|
|
}, nil
|
|
}
|
|
|
|
// Mail is the communication channel for email.
|
|
type Mail struct {
|
|
conf config.Config
|
|
logger log.Logger
|
|
}
|
|
|
|
func (m Mail) getMailClient() (*mail.SMTPClient, error) {
|
|
server := mail.NewSMTPClient()
|
|
server.Host = m.conf.Notifications.SMTP.Host
|
|
server.Port = m.conf.Notifications.SMTP.Port
|
|
server.Username = m.conf.Notifications.SMTP.Username
|
|
if server.Username == "" {
|
|
// compatibility fallback
|
|
server.Username = m.conf.Notifications.SMTP.Sender
|
|
}
|
|
server.Password = m.conf.Notifications.SMTP.Password
|
|
if server.TLSConfig == nil {
|
|
server.TLSConfig = &tls.Config{
|
|
MinVersion: tls.VersionTLS12,
|
|
}
|
|
}
|
|
server.TLSConfig.InsecureSkipVerify = m.conf.Notifications.SMTP.Insecure
|
|
|
|
switch strings.ToLower(m.conf.Notifications.SMTP.Authentication) {
|
|
case "login":
|
|
server.Authentication = mail.AuthLogin
|
|
case "plain":
|
|
server.Authentication = mail.AuthPlain
|
|
case "crammd5":
|
|
server.Authentication = mail.AuthCRAMMD5
|
|
case "none":
|
|
server.Authentication = mail.AuthNone
|
|
case "auto", "":
|
|
server.Authentication = mail.AuthAuto
|
|
default:
|
|
return nil, errors.New("unknown mail authentication method")
|
|
}
|
|
|
|
switch strings.ToLower(m.conf.Notifications.SMTP.Encryption) {
|
|
case "tls":
|
|
server.Encryption = mail.EncryptionTLS
|
|
server.TLSConfig.ServerName = m.conf.Notifications.SMTP.Host
|
|
case "starttls":
|
|
server.Encryption = mail.EncryptionSTARTTLS
|
|
server.TLSConfig.ServerName = m.conf.Notifications.SMTP.Host
|
|
case "ssl":
|
|
server.Encryption = mail.EncryptionSSL
|
|
case "ssltls":
|
|
server.Encryption = mail.EncryptionSSLTLS
|
|
case "none":
|
|
server.Encryption = mail.EncryptionNone
|
|
default:
|
|
return nil, errors.New("unknown mail encryption method")
|
|
}
|
|
|
|
smtpClient, err := server.Connect()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return smtpClient, nil
|
|
}
|
|
|
|
// SendMessage sends a message to all given users.
|
|
func (m Mail) SendMessage(ctx context.Context, message *Message) error {
|
|
if m.conf.Notifications.SMTP.Host == "" {
|
|
m.logger.Info().Str("mail", "SendMessage").Msg("failed to send a message. SMTP host is not set")
|
|
return nil
|
|
}
|
|
|
|
smtpClient, err := m.getMailClient()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
email := mail.NewMSG()
|
|
if message.Sender != "" {
|
|
email.SetFrom(fmt.Sprintf("%s via %s", message.Sender, m.conf.Notifications.SMTP.Sender)).AddTo(message.Recipient...)
|
|
} else {
|
|
email.SetFrom(m.conf.Notifications.SMTP.Sender).AddTo(message.Recipient...)
|
|
}
|
|
email.SetSubject(message.Subject)
|
|
email.SetBody(mail.TextPlain, message.TextBody)
|
|
if message.HTMLBody != "" {
|
|
email.AddAlternative(mail.TextHTML, message.HTMLBody)
|
|
for filename, data := range message.AttachInline {
|
|
email.Attach(&mail.File{Data: data, Name: filename, Inline: true})
|
|
}
|
|
}
|
|
|
|
return email.Send(smtpClient)
|
|
}
|