Files
opencloud/services/notifications/pkg/channels/channels.go
Roman Perekhod 27322c5bbf The email HTML templates added #6146 (#6147)
* The email HTML templates added #6146

* use a single palne text email template. use fs.FS

* Update services/notifications/README.md

Co-authored-by: Martin <github@diemattels.at>

* Update services/notifications/README.md

Co-authored-by: Martin <github@diemattels.at>

* fix md

---------

Co-authored-by: Roman Perekhod <rperekhod@owncloud.com>
Co-authored-by: Martin <github@diemattels.at>
2023-05-03 10:47:46 +02:00

130 lines
3.5 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
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)
}