setup resend client for email service
This commit is contained in:
parent
4448c4a841
commit
82ac33ec66
5 changed files with 56 additions and 9 deletions
1
go.mod
1
go.mod
|
|
@ -52,6 +52,7 @@ require (
|
||||||
github.com/pierrec/lz4/v4 v4.1.22 // indirect
|
github.com/pierrec/lz4/v4 v4.1.22 // indirect
|
||||||
github.com/prometheus/procfs v0.15.1 // indirect
|
github.com/prometheus/procfs v0.15.1 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
|
github.com/resend/resend-go/v2 v2.28.0 // indirect
|
||||||
github.com/segmentio/asm v1.2.0 // indirect
|
github.com/segmentio/asm v1.2.0 // indirect
|
||||||
github.com/sethvargo/go-retry v0.3.0 // indirect
|
github.com/sethvargo/go-retry v0.3.0 // indirect
|
||||||
github.com/shopspring/decimal v1.4.0 // indirect
|
github.com/shopspring/decimal v1.4.0 // indirect
|
||||||
|
|
|
||||||
2
go.sum
2
go.sum
|
|
@ -191,6 +191,8 @@ github.com/rekby/fixenv v0.6.1 h1:jUFiSPpajT4WY2cYuc++7Y1zWrnCxnovGCIX72PZniM=
|
||||||
github.com/rekby/fixenv v0.6.1/go.mod h1:/b5LRc06BYJtslRtHKxsPWFT/ySpHV+rWvzTg+XWk4c=
|
github.com/rekby/fixenv v0.6.1/go.mod h1:/b5LRc06BYJtslRtHKxsPWFT/ySpHV+rWvzTg+XWk4c=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
|
github.com/resend/resend-go/v2 v2.28.0 h1:ttM1/VZR4fApBv3xI1TneSKi1pbfFsVrq7fXFlHKtj4=
|
||||||
|
github.com/resend/resend-go/v2 v2.28.0/go.mod h1:3YCb8c8+pLiqhtRFXTyFwlLvfjQtluxOr9HEh2BwCkQ=
|
||||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type App struct {
|
type App struct {
|
||||||
Cfg *config.Config
|
Cfg *config.Config
|
||||||
DB *sqlx.DB
|
DB *sqlx.DB
|
||||||
UserService *service.UserService
|
UserService *service.UserService
|
||||||
AuthService *service.AuthService
|
AuthService *service.AuthService
|
||||||
|
EmailService *service.EmailService
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(cfg *config.Config) (*App, error) {
|
func New(cfg *config.Config) (*App, error) {
|
||||||
|
|
@ -28,16 +29,20 @@ func New(cfg *config.Config) (*App, error) {
|
||||||
return nil, fmt.Errorf("failed to run migrations: %w", err)
|
return nil, fmt.Errorf("failed to run migrations: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emailClient := service.NewResendClient(cfg.ResendKey)
|
||||||
|
|
||||||
userRepository := repository.NewUserRepository(database)
|
userRepository := repository.NewUserRepository(database)
|
||||||
|
|
||||||
userService := service.NewUserService(userRepository)
|
userService := service.NewUserService(userRepository)
|
||||||
authService := service.NewAuthService(userRepository)
|
authService := service.NewAuthService(userRepository)
|
||||||
|
emailService := service.NewEmailService(emailClient, cfg.EmailFrom, cfg.AppURL, cfg.AppName, cfg.AppEnv == "development")
|
||||||
|
|
||||||
return &App{
|
return &App{
|
||||||
Cfg: cfg,
|
Cfg: cfg,
|
||||||
DB: database,
|
DB: database,
|
||||||
UserService: userService,
|
UserService: userService,
|
||||||
AuthService: authService,
|
AuthService: authService,
|
||||||
|
EmailService: emailService,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,9 @@ type Config struct {
|
||||||
|
|
||||||
JWTSecret string
|
JWTSecret string
|
||||||
JWTExpiry time.Duration
|
JWTExpiry time.Duration
|
||||||
|
|
||||||
|
EmailFrom string
|
||||||
|
ResendKey string
|
||||||
}
|
}
|
||||||
|
|
||||||
func Load() *Config {
|
func Load() *Config {
|
||||||
|
|
@ -40,6 +43,9 @@ func Load() *Config {
|
||||||
|
|
||||||
JWTSecret: envRequired("JWT_SECRET"),
|
JWTSecret: envRequired("JWT_SECRET"),
|
||||||
JWTExpiry: envDuration("JWT_EXPIRY", 168*time.Hour), // 7 days default
|
JWTExpiry: envDuration("JWT_EXPIRY", 168*time.Hour), // 7 days default
|
||||||
|
|
||||||
|
EmailFrom: envString("EMAIL_FROM", ""),
|
||||||
|
ResendKey: envString("RESEND_KEY", ""),
|
||||||
}
|
}
|
||||||
|
|
||||||
return cfg
|
return cfg
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
package service
|
package service
|
||||||
|
|
||||||
import "context"
|
import (
|
||||||
|
"context"
|
||||||
|
"log/slog"
|
||||||
|
|
||||||
|
"github.com/resend/resend-go/v2"
|
||||||
|
)
|
||||||
|
|
||||||
type EmailParams struct {
|
type EmailParams struct {
|
||||||
From string
|
From string
|
||||||
|
|
@ -13,6 +18,34 @@ type EmailClient interface {
|
||||||
SendWithContext(ctx context.Context, params EmailParams) (string, error)
|
SendWithContext(ctx context.Context, params EmailParams) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ResendClient struct {
|
||||||
|
client *resend.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewResendClient(apiKey string) *ResendClient {
|
||||||
|
var client *resend.Client
|
||||||
|
if apiKey != "" {
|
||||||
|
client = resend.NewClient(apiKey)
|
||||||
|
} else {
|
||||||
|
slog.Warn("cannot initialize Resend client with empty api key")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &ResendClient{client: client}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ResendClient) SendWithContext(ctx context.Context, params EmailParams) (string, error) {
|
||||||
|
res, err := c.client.Emails.SendWithContext(ctx, &resend.SendEmailRequest{
|
||||||
|
From: params.From,
|
||||||
|
To: params.To,
|
||||||
|
Subject: params.Subject,
|
||||||
|
Text: params.Text,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return res.Id, nil
|
||||||
|
}
|
||||||
|
|
||||||
type EmailService struct {
|
type EmailService struct {
|
||||||
client EmailClient
|
client EmailClient
|
||||||
fromEmail string
|
fromEmail string
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue