diff --git a/app/services/mailer/mail.go b/app/services/mailer/mail.go new file mode 100644 index 000000000..f0b8b8170 --- /dev/null +++ b/app/services/mailer/mail.go @@ -0,0 +1,34 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mailer + +import gomail "gopkg.in/mail.v2" + +type MailRequest struct { + CCRecipients []string `json:"cc_recipients"` + ToRecipients []string `json:"to_recipients"` + Subject string `json:"subject"` + Body string `json:"body"` + ContentType string `json:"content_type"` +} + +func (dto *MailRequest) ToGoMail() *gomail.Message { + mail := gomail.NewMessage() + mail.SetHeader("To", dto.ToRecipients...) + mail.SetHeader("Cc", dto.CCRecipients...) + mail.SetHeader("Subject", dto.Subject) + mail.SetBody(dto.ContentType, dto.Body) + return mail +} diff --git a/app/services/mailer/mail_client.go b/app/services/mailer/mail_client.go new file mode 100644 index 000000000..025e4850f --- /dev/null +++ b/app/services/mailer/mail_client.go @@ -0,0 +1,49 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mailer + +import ( + "crypto/tls" + + gomail "gopkg.in/mail.v2" +) + +type Service struct { + dialer *gomail.Dialer + fromMail string +} + +func NewMailClient( + host string, + port int, + username string, + fromMail string, + password string, + insecureSkipVerify bool, +) *Service { + d := gomail.NewDialer(host, port, username, password) + d.TLSConfig = &tls.Config{InsecureSkipVerify: insecureSkipVerify} // #nosec G402 (insecure TLS configuration) + + return &Service{ + dialer: d, + fromMail: fromMail, + } +} + +func (c *Service) SendMail(mailRequest *MailRequest) error { + mail := mailRequest.ToGoMail() + mail.SetHeader("From", c.fromMail) + return c.dialer.DialAndSend(mail) +} diff --git a/app/services/mailer/wire.go b/app/services/mailer/wire.go new file mode 100644 index 000000000..bd7049266 --- /dev/null +++ b/app/services/mailer/wire.go @@ -0,0 +1,37 @@ +// Copyright 2023 Harness, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mailer + +import ( + "github.com/harness/gitness/types" + + "github.com/google/wire" +) + +var WireSet = wire.NewSet( + ProvideMailService, +) + +func ProvideMailService(config *types.Config) *Service { + mailSvc := NewMailClient( + config.SMTP.Host, + config.SMTP.Port, + config.SMTP.Username, + config.SMTP.FromMail, + config.SMTP.Password, + config.SMTP.InsecureSkipVerify, // #nosec G402 (insecure skipVerify configuration) + ) + return mailSvc +} diff --git a/events/reader.go b/events/reader.go index e95124544..5f3d2d317 100644 --- a/events/reader.go +++ b/events/reader.go @@ -38,7 +38,7 @@ type ReaderFactory[R Reader] struct { } // Launch launches a new reader for the provided group and client name. -// The setup method should be used to register the differents events the reader will act on. +// The setup method should be used to register the different events the reader will act on. // To stop the reader and cleanup its resources the returned ReaderCanceler can be used. // The reader also cancels automatically when the provided context is canceled. // NOTE: Do not setup the reader outside of the setup method! diff --git a/go.mod b/go.mod index cfba24ada..5fe947734 100644 --- a/go.mod +++ b/go.mod @@ -110,6 +110,8 @@ require ( google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect + gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect + gopkg.in/mail.v2 v2.3.1 // indirect ) require ( diff --git a/go.sum b/go.sum index 69739218a..1dded81b7 100644 --- a/go.sum +++ b/go.sum @@ -1014,6 +1014,8 @@ google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= +gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1026,6 +1028,8 @@ gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:a gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4= gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk= +gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= diff --git a/types/config.go b/types/config.go index d9f8503a2..fafe75505 100644 --- a/types/config.go +++ b/types/config.go @@ -285,4 +285,13 @@ type Config struct { CodeOwners struct { FilePath string `envconfig:"GITNESS_CODEOWNERS_FILEPATH" default:".harness/CODEOWNERS"` } + + SMTP struct { + Host string `envconfig:"GITNESS_SMTP_HOST"` + Port int `envconfig:"GITNESS_SMTP_PORT"` + Username string `envconfig:"GITNESS_SMTP_USERNAME"` + Password string `envconfig:"GITNESS_SMTP_PASSWORD"` + FromMail string `envconfig:"GITNESS_SMTP_FROM_MAIL"` + InsecureSkipVerify bool `envconfig:"GITNESS_SMTP_INSECURE_SKIP_VERIFY"` + } }