Skip to content

Commit 3a9cf02

Browse files
committed
feat(mail): integration when running job
this change adresses #15, in order to run the mail notifications as a job, the workload will need to have access to all attachements that are expected in the mails. The idea with this change, is that theese attachements will be available before dispatching a job (during the validation phase) and can be added as kubernetes resources (configmaps or secrets) from which the job can consume them. This change includes: - Adding volumes and mounts for a secret (with the expected name xml-data-<dataset_folder>.xml) - Adding environment variables that allows the user to configure the secret name to consume from (should be xml-data-<dataset_folder>.xml) - Replacing gopkg.in/gomail.v2 with github.com/wnessen/go-mail since gomail.v2 have a single maintainer that is no longer maintaining the repositry How to test: ```bash ./bpctl mail --dry-run ```
1 parent 0d565c2 commit 3a9cf02

6 files changed

Lines changed: 57 additions & 41 deletions

File tree

go.mod

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ require (
77
github.com/lib/pq v1.10.9
88
github.com/spf13/cobra v1.10.1
99
github.com/spf13/viper v1.21.0
10-
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
10+
github.com/wneessen/go-mail v0.7.2
1111
)
1212

1313
require (
@@ -24,6 +24,5 @@ require (
2424
github.com/subosito/gotenv v1.6.0 // indirect
2525
go.yaml.in/yaml/v3 v3.0.4 // indirect
2626
golang.org/x/sys v0.34.0 // indirect
27-
golang.org/x/text v0.28.0 // indirect
28-
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
27+
golang.org/x/text v0.29.0 // indirect
2928
)

go.sum

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,16 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu
4545
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
4646
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
4747
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
48+
github.com/wneessen/go-mail v0.7.2 h1:xxPnhZ6IZLSgxShebmZ6DPKh1b6OJcoHfzy7UjOkzS8=
49+
github.com/wneessen/go-mail v0.7.2/go.mod h1:+TkW6QP3EVkgTEqHtVmnAE/1MRhmzb8Y9/W3pweuS+k=
4850
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
4951
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
5052
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
5153
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
52-
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
53-
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
54-
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
55-
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
54+
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
55+
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
5656
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
5757
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
5858
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
59-
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
60-
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
6159
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
6260
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

helpers/helpers.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ type TemplateData struct {
3030
SslCaCert string
3131
ClientApiHost string
3232
ClientAccessToken string
33+
MailXmlSecretName string
3334
MailUploaderName string
3435
MailUploaderOrganizationName string
3536
MailUploader string
@@ -93,6 +94,7 @@ func createTemplateData(cfg *config.Config) (TemplateData, error) {
9394
SslCaCert: "/.secrets/tls/ca.crt",
9495
ClientApiHost: cfg.ClientApiHost,
9596
ClientAccessToken: cfg.ClientAccessToken,
97+
MailXmlSecretName: cfg.MailXmlSecretName,
9698
MailUploaderName: cfg.MailUploaderName,
9799
MailUploaderOrganizationName: cfg.MailUploaderOrganizationName,
98100
MailUploader: cfg.MailUploader,

helpers/templates/job.template.yaml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,17 @@ spec:
101101
volumeMounts:
102102
- name: data-volume
103103
mountPath: /data
104-
- mountPath: /.secrets/tls/
105-
name: tls
104+
- name: xml-data
105+
mountPath: /data/xml-data/
106+
- name: tls
107+
mountPath: /.secrets/tls/
106108
volumes:
107109
- name: data-volume
108110
emptyDir: {}
111+
- name: xml-data
112+
secret:
113+
defaultMode: 288
114+
secretName: {{ .MailXmlSecretName }}
109115
- name: tls
110116
secret:
111117
defaultMode: 288

internal/config/config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ type Config struct {
2828
DbSslMode string `mapstructure:"DB_SSL_MODE"`
2929
DbClientCert string `mapstructure:"DB_CLIENT_CERT"`
3030
DbClientKey string `mapstructure:"DB_CLIENT_KEY"`
31+
MailXmlSecretName string `mapstructure:"MAIL_XML_SECRET_NAME"`
3132
MailAddress string `mapstructure:"MAIL_ADDRESS"`
3233
MailPassword string `mapstructure:"MAIL_PASSWORD"`
3334
MailSmtpHost string `mapstructure:"MAIL_SMTP_HOST"`
@@ -86,6 +87,7 @@ func bindKeys(v *viper.Viper) {
8687
v.BindEnv("DB_SSL_MODE")
8788
v.BindEnv("DB_CLIENT_CERT")
8889
v.BindEnv("DB_CLIENT_KEY")
90+
v.BindEnv("MAIL_XML_SECRET_NAME")
8991
v.BindEnv("MAIL_ADDRESS")
9092
v.BindEnv("MAIL_PASSWORD")
9193
v.BindEnv("MAIL_SMTP_HOST")

internal/mail/mail.go

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
"github.com/NBISweden/sda-bpctl/cmd"
1212
"github.com/NBISweden/sda-bpctl/internal/config"
1313
"github.com/spf13/cobra"
14-
"gopkg.in/gomail.v2"
14+
gomail "github.com/wneessen/go-mail"
1515
)
1616

1717
//go:embed templates/*.html
@@ -110,35 +110,6 @@ func New(c *config.Config) *Mail {
110110
return m
111111
}
112112

113-
func (mail *Mail) send(subject string, message string, reciever string, attachements []string, ccs []string) error {
114-
m := gomail.NewMessage()
115-
m.SetHeader("From", mail.from)
116-
m.SetHeader("To", reciever)
117-
m.SetHeader("Subject", subject)
118-
119-
if len(ccs) > 0 {
120-
addresses := make([]string, 0, len(ccs))
121-
for _, email := range ccs {
122-
addresses = append(addresses, m.FormatAddress(email, ""))
123-
}
124-
m.SetHeader("Cc", addresses...)
125-
}
126-
127-
m.SetBody("text/html", message)
128-
129-
// Enforce that the wanted attachements are files that exists
130-
if err := attachementsExists(attachements); err != nil {
131-
return err
132-
}
133-
for _, file := range attachements {
134-
m.Attach(file)
135-
}
136-
137-
d := gomail.NewDialer(mail.smtpHost, mail.smtpPort, mail.email, mail.password)
138-
slog.Info("[mail] notification sent about dataset completion", "reciever", reciever)
139-
return d.DialAndSend(m)
140-
}
141-
142113
func (mail *Mail) Notify(notifier string, dryRun bool) error {
143114
htmlBody, err := renderTemplate(mail.lookup[notifier].template, mail.data)
144115
if err != nil {
@@ -173,6 +144,44 @@ func renderTemplate(filename string, data TemplateData) (string, error) {
173144
return buf.String(), nil
174145
}
175146

147+
func (mail *Mail) send(subject string, message string, reciever string, attachements []string, ccs []string) error {
148+
m := gomail.NewMsg()
149+
150+
if err := m.From(mail.from); err != nil {
151+
return err
152+
}
153+
154+
if err := m.To(reciever); err != nil {
155+
return err
156+
}
157+
158+
m.Subject(subject)
159+
160+
if len(ccs) > 0 {
161+
if err := m.Cc(ccs...); err != nil {
162+
return err
163+
}
164+
}
165+
166+
m.SetBodyString("text/html", message)
167+
168+
// Enforce that the wanted attachements are files that exists
169+
if err := attachementsExists(attachements); err != nil {
170+
return err
171+
}
172+
173+
for _, file := range attachements {
174+
m.AttachFile(file)
175+
}
176+
177+
client, err := gomail.NewClient(mail.smtpHost, gomail.WithPort(mail.smtpPort), gomail.WithSMTPAuth(gomail.SMTPAuthPlain), gomail.WithUsername(mail.email), gomail.WithPassword(mail.password))
178+
if err != nil {
179+
return err
180+
}
181+
slog.Info("[mail] notification sent about dataset completion", "reciever", reciever)
182+
return client.DialAndSend(m)
183+
}
184+
176185
func attachementsExists(attachements []string) error {
177186
for _, attachement := range attachements {
178187
info, err := os.Stat(attachement)

0 commit comments

Comments
 (0)