diff --git a/changelog/unreleased/feature-mail-insecure.md b/changelog/unreleased/feature-mail-insecure.md new file mode 100644 index 0000000000..0f94bdf900 --- /dev/null +++ b/changelog/unreleased/feature-mail-insecure.md @@ -0,0 +1,6 @@ +Enhancement: Introduce insecure flag for smtp email notifications + +We've introduced the `NOTIFICATIONS_SMTP_INSECURE` configuration option, +that let's you skip certificate verification for smtp email servers. + +https://github.com/owncloud/ocis/pull/4279 diff --git a/deployments/continuous-deployment-config/ocis_traefik/latest.yml b/deployments/continuous-deployment-config/ocis_traefik/latest.yml index 4ca0260b44..6f836dc4ae 100644 --- a/deployments/continuous-deployment-config/ocis_traefik/latest.yml +++ b/deployments/continuous-deployment-config/ocis_traefik/latest.yml @@ -35,6 +35,7 @@ OCIS_DOCKER_TAG: latest OCIS_DOMAIN: ocis.ocis-traefik.latest.owncloud.works DEMO_USERS: "true" + INBUCKET_DOMAIN: mail.ocis-traefik.latest.owncloud.works COMPOSE_FILE: docker-compose.yml:monitoring_tracing/docker-compose-additions.yml - name: monitoring git_url: https://github.com/owncloud-devops/monitoring-tracing-client.git diff --git a/deployments/continuous-deployment-config/ocis_traefik/released.yml b/deployments/continuous-deployment-config/ocis_traefik/released.yml index 3b0d74660a..3aad41f506 100644 --- a/deployments/continuous-deployment-config/ocis_traefik/released.yml +++ b/deployments/continuous-deployment-config/ocis_traefik/released.yml @@ -35,6 +35,7 @@ OCIS_DOCKER_TAG: 2.0.0-beta.5 OCIS_DOMAIN: ocis.ocis-traefik.released.owncloud.works DEMO_USERS: "true" + INBUCKET_DOMAIN: mail.ocis-traefik.released.owncloud.works COMPOSE_FILE: docker-compose.yml:monitoring_tracing/docker-compose-additions.yml - name: monitoring git_url: https://github.com/owncloud-devops/monitoring-tracing-client.git diff --git a/deployments/examples/ocis_traefik/.env b/deployments/examples/ocis_traefik/.env index 478247e879..54dba3cf73 100644 --- a/deployments/examples/ocis_traefik/.env +++ b/deployments/examples/ocis_traefik/.env @@ -23,6 +23,10 @@ ADMIN_PASSWORD= # because their passwords are public. Defaults to "false". DEMO_USERS= +### Email / Inbucket settings ### +# Inbucket / Mail domain. Defaults to "mail.owncloud.test" +INBUCKET_DOMAIN= + # If you want to use debugging and tracing with this stack, # you need uncomment following line. Please see documentation at # https://owncloud.dev/ocis/deployment/monitoring-tracing/ diff --git a/deployments/examples/ocis_traefik/docker-compose.yml b/deployments/examples/ocis_traefik/docker-compose.yml index dfcff9ed1b..38e1405947 100644 --- a/deployments/examples/ocis_traefik/docker-compose.yml +++ b/deployments/examples/ocis_traefik/docker-compose.yml @@ -65,6 +65,11 @@ services: IDM_ADMIN_PASSWORD: "${ADMIN_PASSWORD:-admin}" # this overrides the admin password from the configuration file # demo users IDM_CREATE_DEMO_USERS: "${DEMO_USERS:-false}" + # email server (in this case inbucket acts as mail catcher) + NOTIFICATIONS_SMTP_HOST: inbucket + NOTIFICATIONS_SMTP_PORT: 2500 + NOTIFICATIONS_SMTP_SENDER: notifications@${OCIS_DOMAIN:-ocis.owncloud.test} + NOTIFICATIONS_SMTP_INSECURE: true # the mail catcher uses self signed certificates volumes: - ocis-config:/etc/ocis - ocis-data:/var/lib/ocis @@ -79,6 +84,29 @@ services: driver: "local" restart: always + inbucket: + image: inbucket/inbucket + networks: + ocis-net: + entrypoint: + - /bin/sh + command: ["-c", "apk add openssl; openssl req -subj '/CN=inbucket.test' -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout /tmp/server.key -out /tmp/server.crt; /start-inbucket.sh"] + environment: + INBUCKET_SMTP_TLSENABLED: "true" + INBUCKET_SMTP_TLSPRIVKEY: /tmp/server.key + INBUCKET_SMTP_TLSCERT: /tmp/server.crt + INBUCKET_STORAGE_MAILBOXMSGCAP: 1000 + labels: + - "traefik.enable=true" + - "traefik.http.routers.inbucket.entrypoints=https" + - "traefik.http.routers.inbucket.rule=Host(`${INBUCKET_DOMAIN:-mail.owncloud.test}`)" + - "traefik.http.routers.inbucket.tls.certresolver=http" + - "traefik.http.routers.inbucket.service=inbucket" + - "traefik.http.services.inbucket.loadbalancer.server.port=9000" + logging: + driver: "local" + restart: always + volumes: certs: ocis-config: diff --git a/docs/ocis/deployment/continuous_deployment.md b/docs/ocis/deployment/continuous_deployment.md index 0308619a57..99a5983e34 100644 --- a/docs/ocis/deployment/continuous_deployment.md +++ b/docs/ocis/deployment/continuous_deployment.md @@ -25,10 +25,12 @@ Credentials: ## Latest - oCIS: [ocis.ocis-traefik.latest.owncloud.works](https://ocis.ocis-traefik.latest.owncloud.works) +- Mail: [mail.ocis-traefik.latest.owncloud.works](https://mail.ocis-traefik.latest.owncloud.works) ## Released - oCIS: [ocis.ocis-traefik.released.owncloud.works](https://ocis.ocis-traefik.released.owncloud.works) +- Mail: [mail.ocis-traefik.released.owncloud.works](https://mail.ocis-traefik.released.owncloud.works) # oCIS with WOPI server diff --git a/go.mod b/go.mod index 4a2c434375..27843145b5 100644 --- a/go.mod +++ b/go.mod @@ -239,10 +239,12 @@ require ( github.com/spacewander/go-suffix-tree v0.0.0-20191010040751-0865e368c784 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/objx v0.4.0 // indirect + github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208 // indirect github.com/trustelem/zxcvbn v1.0.1 // indirect github.com/tus/tusd v1.8.0 // indirect github.com/wk8/go-ordered-map v0.2.0 // indirect github.com/xanzy/ssh-agent v0.3.1 // indirect + github.com/xhit/go-simple-mail/v2 v2.11.0 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect go.etcd.io/bbolt v1.3.6 // indirect go.etcd.io/etcd/api/v3 v3.5.2 // indirect diff --git a/go.sum b/go.sum index 42acf9b936..73c961943c 100644 --- a/go.sum +++ b/go.sum @@ -1222,6 +1222,8 @@ github.com/thejerf/suture/v4 v4.0.2/go.mod h1:g0e8vwskm9tI0jRjxrnA6lSr0q6OfPdWJV github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208 h1:PM5hJF7HVfNWmCjMdEfbuOBNXSVF2cMFGgQTPdKCbwM= +github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208/go.mod h1:BzWtXXrXzZUvMacR0oF/fbDDgUPO8L36tDMmRAf14ns= github.com/transip/gotransip/v6 v6.2.0/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g= github.com/trustelem/zxcvbn v1.0.1 h1:mp4JFtzdDYGj9WYSD3KQSkwwUumWNFzXaAjckaTYpsc= github.com/trustelem/zxcvbn v1.0.1/go.mod h1:zonUyKeh7sw6psPf/e3DtRqkRyZvAbOfjNz/aO7YQ5s= @@ -1259,6 +1261,8 @@ github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6 github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xhit/go-simple-mail/v2 v2.11.0 h1:o/056V50zfkO3Mm5tVdo9rG3ryg4ZmJ2XW5GMinHfVs= +github.com/xhit/go-simple-mail/v2 v2.11.0/go.mod h1:b7P5ygho6SYE+VIqpxA6QkYfv4teeyG4MKqB3utRu98= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8= diff --git a/services/notifications/pkg/channels/channels.go b/services/notifications/pkg/channels/channels.go index e058e2db29..896dc8afcf 100644 --- a/services/notifications/pkg/channels/channels.go +++ b/services/notifications/pkg/channels/channels.go @@ -3,7 +3,7 @@ package channels import ( "context" - "net/smtp" + "crypto/tls" gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" groups "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1" @@ -12,6 +12,7 @@ import ( "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. @@ -29,6 +30,7 @@ func NewMailChannel(cfg config.Config, logger log.Logger) (Channel, error) { logger.Error().Err(err).Msg("could not get gateway client") return nil, err } + return Mail{ gatewayClient: gc, conf: cfg, @@ -36,7 +38,7 @@ func NewMailChannel(cfg config.Config, logger log.Logger) (Channel, error) { }, nil } -// Mail is the communcation channel for email. +// Mail is the communication channel for email. type Mail struct { gatewayClient gateway.GatewayAPIClient conf config.Config @@ -45,18 +47,34 @@ type Mail struct { // SendMessage sends a message to all given users. func (m Mail) SendMessage(userIDs []string, msg string) error { + if m.conf.Notifications.SMTP.Host == "" { + return nil + } + to, err := m.getReceiverAddresses(userIDs) if err != nil { return err } - body := []byte(msg) - smtpConf := m.conf.Notifications.SMTP - auth := smtp.PlainAuth("", smtpConf.Sender, smtpConf.Password, smtpConf.Host) - if err := smtp.SendMail(smtpConf.Host+":"+smtpConf.Port, auth, smtpConf.Sender, to, body); err != nil { - return errors.Wrap(err, "could not send mail") + server := mail.NewSMTPClient() + server.Host = m.conf.Notifications.SMTP.Host + server.Port = m.conf.Notifications.SMTP.Port + server.Username = m.conf.Notifications.SMTP.Sender + server.Password = m.conf.Notifications.SMTP.Password + server.TLSConfig = &tls.Config{InsecureSkipVerify: m.conf.Notifications.SMTP.Insecure} + + smtpClient, err := server.Connect() + if err != nil { + return err } - return nil + + email := mail.NewMSG() + + email.SetFrom(m.conf.Notifications.SMTP.Sender).AddTo(to...) + + email.SetBody(mail.TextPlain, msg) + + return email.Send(smtpClient) } // SendMessageToGroup sends a message to all members of the given group. diff --git a/services/notifications/pkg/config/config.go b/services/notifications/pkg/config/config.go index 2fd274ce96..ba23d12c61 100644 --- a/services/notifications/pkg/config/config.go +++ b/services/notifications/pkg/config/config.go @@ -31,14 +31,15 @@ type Notifications struct { // SMTP combines the smtp configuration options. type SMTP struct { Host string `yaml:"smtp_host" env:"NOTIFICATIONS_SMTP_HOST" desc:"SMTP host to connect to."` - Port string `yaml:"smtp_port" env:"NOTIFICATIONS_SMTP_PORT" desc:"Port of the SMTP host to connect to."` + Port int `yaml:"smtp_port" env:"NOTIFICATIONS_SMTP_PORT" desc:"Port of the SMTP host to connect to."` Sender string `yaml:"smtp_sender" env:"NOTIFICATIONS_SMTP_SENDER" desc:"Sender of emails that will be sent."` Password string `yaml:"smtp_password" env:"NOTIFICATIONS_SMTP_PASSWORD" desc:"Password of the SMTP host to connect to."` + Insecure bool `yaml:"insecure" env:"NOTIFICATIONS_SMTP_INSECURE" desc:"Allow insecure connections to the SMTP server."` } // Events combines the configuration options for the event bus. type Events struct { - Endpoint string `yaml:"endpoint" env:"NOTIFICATIONS_EVENTS_ENDPOINT" desc:"The address of the event system. The event system is the message queuing service. It is used as message broker for the microservice architecture.` + Endpoint string `yaml:"endpoint" env:"NOTIFICATIONS_EVENTS_ENDPOINT" desc:"The address of the event system. The event system is the message queuing service. It is used as message broker for the microservice architecture."` Cluster string `yaml:"cluster" env:"NOTIFICATIONS_EVENTS_CLUSTER" desc:"The clusterID of the event system. The event system is the message queuing service. It is used as message broker for the microservice architecture. Mandatory when using NATS as event system."` ConsumerGroup string `yaml:"group" env:"NOTIFICATIONS_EVENTS_GROUP" desc:"Name of the event group / queue on the event system."` } diff --git a/services/notifications/pkg/config/defaults/defaultconfig.go b/services/notifications/pkg/config/defaults/defaultconfig.go index 36b68c7461..acd443345b 100644 --- a/services/notifications/pkg/config/defaults/defaultconfig.go +++ b/services/notifications/pkg/config/defaults/defaultconfig.go @@ -24,8 +24,8 @@ func DefaultConfig() *config.Config { }, Notifications: config.Notifications{ SMTP: config.SMTP{ - Host: "127.0.0.1", - Port: "1025", + Host: "", + Port: 1025, Sender: "noreply@example.com", }, Events: config.Events{