This commit is contained in:
lbenedar
2026-03-19 18:19:37 +03:00
parent 86ce8e9eec
commit 8504d0e5ba
5 changed files with 95 additions and 0 deletions

View File

@@ -9,6 +9,7 @@ import (
"gitea.local.lab/Lbenedar/greenlight/internal/data"
"gitea.local.lab/Lbenedar/greenlight/internal/jsonlog"
"gitea.local.lab/Lbenedar/greenlight/internal/mailer"
_ "github.com/lib/pq"
)
@@ -18,6 +19,7 @@ type application struct {
config config
logger *jsonlog.Logger
models data.Models
mailer mailer.Mailer
}
type config struct {
@@ -34,6 +36,13 @@ type config struct {
burst int
enabled bool
}
smtp struct {
host string
port int
username string
password string
sender string
}
}
func openDB(cfg config) (*sql.DB, error) {
@@ -76,6 +85,12 @@ func main() {
flag.IntVar(&cfg.limiter.burst, "limiter-burst", 4, "Rate limiter maximum burst")
flag.BoolVar(&cfg.limiter.enabled, "limiter-enabled", true, "Enable rate limiter")
flag.StringVar(&cfg.smtp.host, "smtp-host", "smtp.mailtrap.io", "SMTP host")
flag.IntVar(&cfg.smtp.port, "smtp-port", 25, "SMTP port")
flag.StringVar(&cfg.smtp.username, "smtp-username", "0abf276416b183", "SMTP username")
flag.StringVar(&cfg.smtp.password, "smtp-password", "d8672aa2264bb5", "SMTP password")
flag.StringVar(&cfg.smtp.sender, "smtp-sender", "Greenlight <no-reply@greenlight.net", "SMTP sender")
flag.Parse()
logger := jsonlog.New(os.Stdout, jsonlog.LevelInfo)
@@ -92,6 +107,7 @@ func main() {
config: cfg,
logger: logger,
models: data.NewModels(db),
mailer: mailer.New(cfg.smtp.host, cfg.smtp.port, cfg.smtp.username, cfg.smtp.password, cfg.smtp.sender),
}
err = app.serve()

View File

@@ -52,6 +52,12 @@ func (app *application) registerUserHandler(w http.ResponseWriter, r *http.Reque
return
}
// err = app.mailer.Send(user.Email, "user_welcome.tmpl", user)
// if err != nil {
// app.serverErrorResponse(w, r, err)
// return
// }
err = app.writeJSON(w, http.StatusCreated, envelope{"user": user}, nil)
if err != nil {
app.serverErrorResponse(w, r, err)

2
go.mod
View File

@@ -3,8 +3,10 @@ module gitea.local.lab/Lbenedar/greenlight
go 1.25.0
require (
github.com/go-mail/mail/v2 v2.3.0 // indirect
github.com/julienschmidt/httprouter v1.3.0 // indirect
github.com/lib/pq v1.11.2 // indirect
golang.org/x/crypto v0.49.0 // indirect
golang.org/x/time v0.15.0 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
)

4
go.sum
View File

@@ -1,3 +1,5 @@
github.com/go-mail/mail/v2 v2.3.0 h1:wha99yf2v3cpUzD1V9ujP404Jbw2uEvs+rBJybkdYcw=
github.com/go-mail/mail/v2 v2.3.0/go.mod h1:oE2UK8qebZAjjV1ZYUpY7FPnbi/kIU53l1dmqPRb4go=
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/lib/pq v1.11.2 h1:x6gxUeu39V0BHZiugWe8LXZYZ+Utk7hSJGThs8sdzfs=
@@ -6,3 +8,5 @@ golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
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=

67
internal/mailer/mailer.go Normal file
View File

@@ -0,0 +1,67 @@
package mailer
import (
"bytes"
"embed"
"html/template"
"time"
"github.com/go-mail/mail/v2"
)
//go:embed "templates"
var templateFS embed.FS
type Mailer struct {
dialer *mail.Dialer
sender string
}
func New(host string, port int, username, password, sender string) Mailer {
dialer := mail.NewDialer(host, port, username, password)
dialer.Timeout = 5 * time.Second
return Mailer{
dialer: dialer,
sender: sender,
}
}
func (m Mailer) Send(recepient, templateFile string, data any) error {
tmpl, err := template.New("email").ParseFS(templateFS, "templates/"+templateFile)
if err != nil {
return err
}
subject := new(bytes.Buffer)
err = tmpl.ExecuteTemplate(subject, "subject", data)
if err != nil {
return err
}
plainBody := new(bytes.Buffer)
err = tmpl.ExecuteTemplate(plainBody, "plainBody", data)
if err != nil {
return err
}
htmlBody := new(bytes.Buffer)
err = tmpl.ExecuteTemplate(htmlBody, "htmlBody", data)
if err != nil {
return err
}
msg := mail.NewMessage()
msg.SetHeader("To", recepient)
msg.SetHeader("From", m.sender)
msg.SetHeader("Subject", subject.String())
msg.SetBody("text/plain", plainBody.String())
msg.AddAlternative("text/html", htmlBody.String())
err = m.dialer.DialAndSend(msg)
if err != nil {
return err
}
return nil
}