diff --git a/.env.example b/.env.example index 4c29ad7..ed279d5 100644 --- a/.env.example +++ b/.env.example @@ -5,4 +5,11 @@ APP_LISTEN_PORT=3000 APP_BEHIND_PROXY=false DATABASE_DSN="host=localhost user=camarades password=camarades dbname=camarades port=5432 sslmode=disable TimeZone=Europe/Zurich" SESSIONS_LOCATION=./sessions.db -AUTHELIA_USERS_LOCATION=./users.yml \ No newline at end of file +AUTHELIA_USERS_LOCATION=./users.yml +AUTHELIA_RESET_URL=https://login.popvaud.ch/reset-password/step1 +MAIL_HOST=mail.infomaniak.com +MAIL_PORT=587 +MAIL_USERNAME=no-reply@popvaud.ch +MAIL_PASSWORD=very-secure-password +MAIL_FROM_NAME=POP Vaud +MAIL_FROM_ADDRESS=no-reply@popvaud.ch \ No newline at end of file diff --git a/go.mod b/go.mod index b093844..c9a9c40 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module git.readonly.ch/bouzoure/pop-camarades -go 1.25.0 +go 1.25.3 require ( github.com/alexedwards/argon2id v1.0.0 @@ -16,6 +16,7 @@ require ( github.com/google/uuid v1.6.0 github.com/pquerna/otp v1.5.0 github.com/sethvargo/go-password v0.3.1 + github.com/wneessen/go-mail v0.7.2 github.com/yuin/goldmark v1.8.2 go.yaml.in/yaml/v4 v4.0.0-rc.4 golang.org/x/crypto v0.50.0 diff --git a/go.sum b/go.sum index 88a415f..e6c8459 100644 --- a/go.sum +++ b/go.sum @@ -222,6 +222,8 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.70.0 h1:LAhMGcWk13QZWm85+eg8ZBNbrq5mnkWFGbHMUJHIdXA= github.com/valyala/fasthttp v1.70.0/go.mod h1:oDZEHHkJ/Buyklg6uURmYs19442zFSnCIfX3j1FY3pE= +github.com/wneessen/go-mail v0.7.2 h1:xxPnhZ6IZLSgxShebmZ6DPKh1b6OJcoHfzy7UjOkzS8= +github.com/wneessen/go-mail v0.7.2/go.mod h1:+TkW6QP3EVkgTEqHtVmnAE/1MRhmzb8Y9/W3pweuS+k= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= diff --git a/helpers/authelia/mail.go b/helpers/authelia/mail.go new file mode 100644 index 0000000..a1d33e7 --- /dev/null +++ b/helpers/authelia/mail.go @@ -0,0 +1,66 @@ +package authelia + +import ( + ht "html/template" + tt "text/template" + + "git.readonly.ch/bouzoure/pop-camarades/helpers" + "git.readonly.ch/bouzoure/pop-camarades/models" +) + +type InputWelcomeMail struct { + Person models.Person + ResetURL string +} + +func SendWelcomeMail(person models.Person) error { + config, err := helpers.GetConfig() + if err != nil { + return err + } + + mailer, err := helpers.GetMailer() + if err != nil { + return err + } + + msg, err := helpers.NewMessage() + if err != nil { + return err + } + + mailsFS, err := helpers.GetEmbeddedFS("mails") + if err != nil { + return err + } + + inputValues := InputWelcomeMail{ + Person: person, + ResetURL: config.Authelia.ResetURL, + } + + tplHTML, err := ht.ParseFS(mailsFS, "mails/welcome.html") + if err != nil { + return err + } + + tplTXT, err := tt.ParseFS(mailsFS, "mails/welcome.txt") + if err != nil { + return err + } + + msg.Subject("Ton compte POP Vaud") + msg.AddTo(person.Email) + + err = msg.SetBodyHTMLTemplate(tplHTML, inputValues) + if err != nil { + return err + } + + err = msg.AddAlternativeTextTemplate(tplTXT, inputValues) + if err != nil { + return err + } + + return mailer.DialAndSend(msg) +} diff --git a/helpers/authelia/users.go b/helpers/authelia/users.go index 8c35b28..437ee5e 100644 --- a/helpers/authelia/users.go +++ b/helpers/authelia/users.go @@ -101,7 +101,10 @@ func SyncUsers() error { account.UpdateNeeded = false if !account.AccountCreated.Valid { - // TODO: send email + err := SendWelcomeMail(account.Person) + if err != nil { + log.Error(err) + } account.AccountCreated.Scan(time.Now()) } diff --git a/helpers/config.go b/helpers/config.go index e6c0791..a1f98c6 100644 --- a/helpers/config.go +++ b/helpers/config.go @@ -22,6 +22,15 @@ type Config struct { } Authelia struct { UsersLocation string `env:"AUTHELIA_USERS_LOCATION"` + ResetURL string `env:"AUTHELIA_RESET_URL"` + } + Mail struct { + Host string `env:"MAIL_HOST"` + Port int `env:"MAIL_PORT"` + Username string `env:"MAIL_USERNAME"` + Password string `env:"MAIL_PASSWORD"` + FromName string `env:"MAIL_FROM_NAME"` + FromAddress string `env:"MAIL_FROM_ADDRESS"` } } diff --git a/helpers/mailer.go b/helpers/mailer.go new file mode 100644 index 0000000..977dbfb --- /dev/null +++ b/helpers/mailer.go @@ -0,0 +1,49 @@ +package helpers + +import ( + "github.com/wneessen/go-mail" +) + +var mailer *mail.Client +var mailerSet bool + +func GetMailer() (*mail.Client, error) { + if mailerSet { + return mailer, nil + } + + config, err := GetConfig() + if err != nil { + return mailer, err + } + + mailer, err = mail.NewClient( + config.Mail.Host, + mail.WithPort(config.Mail.Port), + mail.WithSMTPAuth(mail.SMTPAuthAutoDiscover), + mail.WithUsername(config.Mail.Username), + mail.WithPassword(config.Mail.Password), + ) + if err != nil { + return mailer, err + } + + mailerSet = true + return mailer, nil +} + +func NewMessage() (*mail.Msg, error) { + msg := mail.NewMsg() + + config, err := GetConfig() + if err != nil { + return msg, err + } + + msg.FromFormat( + config.Mail.FromName, + config.Mail.FromAddress, + ) + + return msg, nil +} diff --git a/mails/welcome.html b/mails/welcome.html new file mode 100644 index 0000000..e977516 --- /dev/null +++ b/mails/welcome.html @@ -0,0 +1,19 @@ + + +
+ + + + +