ch14.3
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"gitea.local.lab/Lbenedar/greenlight/internal/data"
|
"gitea.local.lab/Lbenedar/greenlight/internal/data"
|
||||||
"gitea.local.lab/Lbenedar/greenlight/internal/jsonlog"
|
"gitea.local.lab/Lbenedar/greenlight/internal/jsonlog"
|
||||||
|
"gitea.local.lab/Lbenedar/greenlight/internal/mailer"
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ type application struct {
|
|||||||
config config
|
config config
|
||||||
logger *jsonlog.Logger
|
logger *jsonlog.Logger
|
||||||
models data.Models
|
models data.Models
|
||||||
|
mailer mailer.Mailer
|
||||||
}
|
}
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
@@ -34,6 +36,13 @@ type config struct {
|
|||||||
burst int
|
burst int
|
||||||
enabled bool
|
enabled bool
|
||||||
}
|
}
|
||||||
|
smtp struct {
|
||||||
|
host string
|
||||||
|
port int
|
||||||
|
username string
|
||||||
|
password string
|
||||||
|
sender string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func openDB(cfg config) (*sql.DB, error) {
|
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.IntVar(&cfg.limiter.burst, "limiter-burst", 4, "Rate limiter maximum burst")
|
||||||
flag.BoolVar(&cfg.limiter.enabled, "limiter-enabled", true, "Enable rate limiter")
|
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()
|
flag.Parse()
|
||||||
|
|
||||||
logger := jsonlog.New(os.Stdout, jsonlog.LevelInfo)
|
logger := jsonlog.New(os.Stdout, jsonlog.LevelInfo)
|
||||||
@@ -92,6 +107,7 @@ func main() {
|
|||||||
config: cfg,
|
config: cfg,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
models: data.NewModels(db),
|
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()
|
err = app.serve()
|
||||||
|
|||||||
@@ -52,6 +52,12 @@ func (app *application) registerUserHandler(w http.ResponseWriter, r *http.Reque
|
|||||||
return
|
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)
|
err = app.writeJSON(w, http.StatusCreated, envelope{"user": user}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
app.serverErrorResponse(w, r, err)
|
app.serverErrorResponse(w, r, err)
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -3,8 +3,10 @@ module gitea.local.lab/Lbenedar/greenlight
|
|||||||
go 1.25.0
|
go 1.25.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/go-mail/mail/v2 v2.3.0 // indirect
|
||||||
github.com/julienschmidt/httprouter v1.3.0 // indirect
|
github.com/julienschmidt/httprouter v1.3.0 // indirect
|
||||||
github.com/lib/pq v1.11.2 // indirect
|
github.com/lib/pq v1.11.2 // indirect
|
||||||
golang.org/x/crypto v0.49.0 // indirect
|
golang.org/x/crypto v0.49.0 // indirect
|
||||||
golang.org/x/time v0.15.0 // indirect
|
golang.org/x/time v0.15.0 // indirect
|
||||||
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -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 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
|
||||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||||
github.com/lib/pq v1.11.2 h1:x6gxUeu39V0BHZiugWe8LXZYZ+Utk7hSJGThs8sdzfs=
|
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/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 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
|
||||||
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
|
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
67
internal/mailer/mailer.go
Normal 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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user