Skip to content

Commit

Permalink
feat(email): send email with gmail
Browse files Browse the repository at this point in the history
  • Loading branch information
eizyc committed Jun 29, 2024
1 parent 504fdff commit 43ca5de
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ sqlc:
sqlc generate

test:
go test -v -cover ./...
go test -v -cover -short ./...

server:
go run main.go
Expand Down
5 changes: 4 additions & 1 deletion app.env
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,7 @@ GRPC_SERVER_ADDRESS=0.0.0.0:9090
TOKEN_SYMMETRIC_KEY=12345678901234567890123456789012
ACCESS_TOKEN_DURATION=15m
REFRESH_TOKEN_DURATION=24h
REDIS_ADDRESS=0.0.0.0:6379
REDIS_ADDRESS=0.0.0.0:6379
EMAIL_SENDER_NAME=Simple Bank
EMAIL_SENDER_ADDRESS=[email protected]
EMAIL_SENDER_PASSWORD=prgctnuzmwqlkcrn
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/aead/chacha20poly1305 v0.0.0-20170617001512-233f39982aeb
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0
github.com/jackc/pgx/v5 v5.6.0
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible
github.com/redis/go-redis/v9 v9.0.3
github.com/stretchr/testify v1.9.0
google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY=
github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw=
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible h1:jdpOPRN1zP63Td1hDQbZW73xKmzDvZHzVdNYxhnTMDA=
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
Expand Down
65 changes: 65 additions & 0 deletions mail/sender.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package mail

import (
"fmt"
"net/smtp"

"github.com/jordan-wright/email"
)

const (
smtpAuthAddress = "smtp.gmail.com"
smtpServerAddress = "smtp.gmail.com:587"
)

type EmailSender interface {
SendEmail(
subject string,
content string,
to []string,
cc []string,
bcc []string,
attachFiles []string,
) error
}

type GmailSender struct {
name string
fromEmailAddress string
fromEmailPassword string
}

func NewGmailSender(name string, fromEmailAddress string, fromEmailPassword string) EmailSender {
return &GmailSender{
name: name,
fromEmailAddress: fromEmailAddress,
fromEmailPassword: fromEmailPassword,
}
}

func (sender *GmailSender) SendEmail(
subject string,
content string,
to []string,
cc []string,
bcc []string,
attachFiles []string,
) error {
e := email.NewEmail()
e.From = fmt.Sprintf("%s <%s>", sender.name, sender.fromEmailAddress)
e.Subject = subject
e.HTML = []byte(content)
e.To = to
e.Cc = cc
e.Bcc = bcc

for _, f := range attachFiles {
_, err := e.AttachFile(f)
if err != nil {
return fmt.Errorf("failed to attach file %s: %w", f, err)
}
}

smtpAuth := smtp.PlainAuth("", sender.fromEmailAddress, sender.fromEmailPassword, smtpAuthAddress)
return e.Send(smtpServerAddress, smtpAuth)
}
30 changes: 30 additions & 0 deletions mail/sender_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package mail

import (
"testing"

"github.com/eizyc/simplebank/util"
"github.com/stretchr/testify/require"
)

func TestSendEmailWithGmail(t *testing.T) {
if testing.Short() {
t.Skip()
}

config, err := util.LoadConfig("..")
require.NoError(t, err)

sender := NewGmailSender(config.EmailSenderName, config.EmailSenderAddress, config.EmailSenderPassword)

subject := "A test email"
content := `
<h1>Hello world</h1>
<p>This is a test message from <a href="https://eizyc.github.io/">Eizyc</a></p>
`
to := []string{"[email protected]"}
attachFiles := []string{"../README.md"}

err = sender.SendEmail(subject, content, to, nil, nil, attachFiles)
require.NoError(t, err)
}
3 changes: 3 additions & 0 deletions util/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ type Config struct {
AccessTokenDuration time.Duration `mapstructure:"ACCESS_TOKEN_DURATION"`
RefreshTokenDuration time.Duration `mapstructure:"REFRESH_TOKEN_DURATION"`
RedisAddress string `mapstructure:"REDIS_ADDRESS"`
EmailSenderName string `mapstructure:"EMAIL_SENDER_NAME"`
EmailSenderAddress string `mapstructure:"EMAIL_SENDER_ADDRESS"`
EmailSenderPassword string `mapstructure:"EMAIL_SENDER_PASSWORD"`
}

// LoadConfig reads configuration from file or environment variables.
Expand Down

0 comments on commit 43ca5de

Please sign in to comment.