crowdsec/plugins/notifications/email/main.go
Manuel Sabban 589a30cd5f
[fix issue 1484] Allow to send email without auth again (#1485)
* We can now send email with plain auth
* better defaults for email plugin

Co-authored-by: sabban <15465465+sabban@users.noreply.github.com>
2022-04-27 12:07:54 +02:00

144 lines
3.8 KiB
Go

package main
import (
"context"
"fmt"
"os"
"github.com/crowdsecurity/crowdsec/pkg/protobufs"
"github.com/hashicorp/go-hclog"
plugin "github.com/hashicorp/go-plugin"
mail "github.com/xhit/go-simple-mail/v2"
"gopkg.in/yaml.v2"
)
var logger hclog.Logger = hclog.New(&hclog.LoggerOptions{
Name: "email-plugin",
Level: hclog.LevelFromString("INFO"),
Output: os.Stderr,
JSONFormat: true,
})
var AuthStringToType map[string]mail.AuthType = map[string]mail.AuthType{
"none": mail.AuthNone,
"crammd5": mail.AuthCRAMMD5,
"login": mail.AuthLogin,
"plain": mail.AuthPlain,
}
var EncryptionStringToType map[string]mail.Encryption = map[string]mail.Encryption{
"ssltls": mail.EncryptionSTARTTLS,
"none": mail.EncryptionNone,
}
type PluginConfig struct {
Name string `yaml:"name"`
LogLevel *string `yaml:"log_level"`
SMTPHost string `yaml:"smtp_host"`
SMTPPort int `yaml:"smtp_port"`
SMTPUsername string `yaml:"smtp_username"`
SMTPPassword string `yaml:"smtp_password"`
SenderEmail string `yaml:"sender_email"`
SenderName string `yaml:"sender_name"`
ReceiverEmails []string `yaml:"receiver_emails"`
EmailSubject string `yaml:"email_subject"`
EncryptionType string `yaml:"encryption_type"`
AuthType string `yaml:"auth_type"`
}
type EmailPlugin struct {
ConfigByName map[string]PluginConfig
}
func (n *EmailPlugin) Configure(ctx context.Context, config *protobufs.Config) (*protobufs.Empty, error) {
d := PluginConfig{
SMTPPort: 25,
SenderName: "Crowdsec",
EmailSubject: "Crowdsec notification",
EncryptionType: "ssltls",
AuthType: "login",
SenderEmail: "crowdsec@crowdsec.local",
}
if err := yaml.Unmarshal(config.Config, &d); err != nil {
return nil, err
}
if d.Name == "" {
return nil, fmt.Errorf("name is required")
}
if d.SMTPHost == "" {
return nil, fmt.Errorf("SMTP host is not set")
}
if d.ReceiverEmails == nil || len(d.ReceiverEmails) == 0 {
return nil, fmt.Errorf("Receiver emails are not set")
}
n.ConfigByName[d.Name] = d
return &protobufs.Empty{}, nil
}
func (n *EmailPlugin) Notify(ctx context.Context, notification *protobufs.Notification) (*protobufs.Empty, error) {
if _, ok := n.ConfigByName[notification.Name]; !ok {
return nil, fmt.Errorf("invalid plugin config name %s", notification.Name)
}
cfg := n.ConfigByName[notification.Name]
if cfg.LogLevel != nil && *cfg.LogLevel != "" {
logger.SetLevel(hclog.LevelFromString(*cfg.LogLevel))
}
logger = logger.Named(cfg.Name)
logger.Debug("got notification")
server := mail.NewSMTPClient()
server.Host = cfg.SMTPHost
server.Port = cfg.SMTPPort
server.Username = cfg.SMTPUsername
server.Password = cfg.SMTPPassword
server.Encryption = EncryptionStringToType[cfg.EncryptionType]
server.Authentication = AuthStringToType[cfg.AuthType]
logger.Debug("making smtp connection")
smtpClient, err := server.Connect()
if err != nil {
return &protobufs.Empty{}, err
}
logger.Debug("smtp connection done")
email := mail.NewMSG()
email.SetFrom(fmt.Sprintf("%s <%s>", cfg.SenderName, cfg.SenderEmail)).
AddTo(cfg.ReceiverEmails...).
SetSubject(cfg.EmailSubject)
email.SetBody(mail.TextHTML, notification.Text)
err = email.Send(smtpClient)
if err != nil {
return &protobufs.Empty{}, err
}
logger.Info(fmt.Sprintf("sent email to %v", cfg.ReceiverEmails))
return &protobufs.Empty{}, nil
}
func main() {
var handshake = plugin.HandshakeConfig{
ProtocolVersion: 1,
MagicCookieKey: "CROWDSEC_PLUGIN_KEY",
MagicCookieValue: os.Getenv("CROWDSEC_PLUGIN_KEY"),
}
plugin.Serve(&plugin.ServeConfig{
HandshakeConfig: handshake,
Plugins: map[string]plugin.Plugin{
"email": &protobufs.NotifierPlugin{
Impl: &EmailPlugin{ConfigByName: make(map[string]PluginConfig)},
},
},
GRPCServer: plugin.DefaultGRPCServer,
Logger: logger,
})
}