Skip to content

Commit 2b58dbf

Browse files
committed
feat(notify): email
1 parent bf75bb4 commit 2b58dbf

33 files changed

+599
-111
lines changed

app/notify/cmd/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func newApp(logger log.Logger, log *log.Helper, gs *grpc.Server, hs *http.Server
4646
log.Infof("start server %s", id)
4747

4848
go eventHandler.Handle()
49-
log.Infof("start message quque event handler")
49+
log.Infof("start message queue event handler")
5050

5151
return kratos.New(
5252
kratos.ID(id),

app/notify/cmd/wire_gen.go

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/notify/configs/config.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,11 @@ trace:
4242
endpoint: "127.0.0.1:4317" # OTel Collector 地址
4343
insecure: true
4444
sampler: 1 # 100% 采样率
45+
46+
email:
47+
enable: true
48+
smtp_host: smtp.qq.com
49+
smtp_port: 465
50+
username: example
51+
password: example
52+
from: example@example.com

app/notify/go.mod

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ require (
1616
github.com/panjf2000/ants/v2 v2.11.3
1717
github.com/prometheus/client_golang v1.23.2
1818
github.com/rabbitmq/amqp091-go v1.10.0
19-
github.com/redis/go-redis/v9 v9.17.2
2019
go.etcd.io/etcd/client/v3 v3.6.6
2120
go.opentelemetry.io/otel v1.38.0
2221
go.opentelemetry.io/otel/metric v1.38.0
2322
google.golang.org/protobuf v1.36.10
23+
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
2424
)
2525

2626
require (
@@ -64,6 +64,7 @@ require (
6464
github.com/prometheus/client_model v0.6.2 // indirect
6565
github.com/prometheus/common v0.66.1 // indirect
6666
github.com/prometheus/procfs v0.16.1 // indirect
67+
github.com/redis/go-redis/v9 v9.17.2 // indirect
6768
github.com/stoewer/go-strcase v1.3.0 // indirect
6869
github.com/zclconf/go-cty v1.14.4 // indirect
6970
github.com/zclconf/go-cty-yaml v1.1.0 // indirect
@@ -88,6 +89,7 @@ require (
8889
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect
8990
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect
9091
google.golang.org/grpc v1.77.0 // indirect
92+
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
9193
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
9294
gopkg.in/yaml.v3 v3.0.1 // indirect
9395
)

app/notify/go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,9 +237,13 @@ google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM=
237237
google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig=
238238
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
239239
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
240+
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
241+
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
240242
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
241243
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
242244
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
245+
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
246+
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
243247
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
244248
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
245249
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package base
2+
3+
import (
4+
"fmt"
5+
6+
"gopkg.in/gomail.v2"
7+
)
8+
9+
type EmailDomain struct {
10+
*BaseDomain
11+
}
12+
13+
func NewEmailDomain(base *BaseDomain) *EmailDomain {
14+
return &EmailDomain{
15+
BaseDomain: base,
16+
}
17+
}
18+
19+
// Send 发送邮件
20+
func (d *EmailDomain) Send(to []string, subject string, body string) error {
21+
m := gomail.NewMessage()
22+
m.SetHeader("From", d.Conf.Email.From)
23+
m.SetHeader("To", to...)
24+
m.SetHeader("Subject", subject)
25+
m.SetBody("text/html", body)
26+
27+
dialer := gomail.NewDialer(d.Conf.Email.SmtpHost, int(d.Conf.Email.SmtpPort), d.Conf.Email.Username, d.Conf.Email.Password)
28+
dialer.SSL = d.Conf.Email.SmtpPort == 465
29+
30+
err := dialer.DialAndSend(m)
31+
if err != nil {
32+
return fmt.Errorf("send email error: %v", err)
33+
}
34+
d.Log.Infof(" %s send email to %v success", d.Conf.Email.From, to)
35+
return nil
36+
}

app/notify/internal/biz/biz.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ var BizProviderSet = wire.NewSet(
1818
NewNotificationMetaDomain,
1919
NewNotificationRecordDomain,
2020
NewNotificationTemplateDomain,
21+
base.NewEmailDomain,
2122
)

app/notify/internal/biz/event_handler.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ func (h *EventHandler) Handle() {
137137
if err != nil {
138138
break
139139
}
140+
notification.Title = template.Title
140141
notification.Content = template.Content
141142
_, err = handler.Handle(h.ctx, notification)
142143
if err != nil {

app/notify/internal/biz/handler/handler.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ import (
1010

1111
var HandlerSet = wire.NewSet(
1212
NewFullHandler,
13-
NewFilter,
13+
NewRegisterVerifyCode,
1414
)
1515

1616
func ProvideHandlers(
17-
filter *Filter,
17+
registerVerifyCode *RegisterVerifyCode,
1818
fullHandler *FullHandler,
1919
) dict.Map[string, handlerchain.Handler[*commonModel.Notification]] {
2020
m := dict.New[string, handlerchain.Handler[*commonModel.Notification]](0)
21-
m.Set(filter.Name(), filter)
21+
m.Set(registerVerifyCode.Name(), registerVerifyCode)
2222
m.Set(fullHandler.Name(), fullHandler)
2323
return m
2424
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package handler
2+
3+
import (
4+
"bytes"
5+
"common/pkg/cutil/handlerchain"
6+
commonModel "common/pkg/model"
7+
"context"
8+
"html/template"
9+
"notify/internal/biz/base"
10+
)
11+
12+
type RegisterVerifyCode struct {
13+
*handlerchain.BaseHandler[*commonModel.Notification]
14+
emailDomain *base.EmailDomain
15+
}
16+
17+
func NewRegisterVerifyCode(emailDomain *base.EmailDomain) *RegisterVerifyCode {
18+
return &RegisterVerifyCode{
19+
BaseHandler: &handlerchain.BaseHandler[*commonModel.Notification]{Name: "register_verify_code"},
20+
emailDomain: emailDomain,
21+
}
22+
}
23+
24+
func (h *RegisterVerifyCode) Handle(ctx context.Context, data *commonModel.Notification) (*commonModel.Notification, error) {
25+
26+
// 按模板渲染
27+
data.Meta.RegisterVerifyCode.ExpireMinutes = int(data.Meta.RegisterVerifyCode.Expire.Minutes())
28+
tpl, err := template.New(data.UUID).Parse(data.Content)
29+
if err != nil {
30+
return nil, err
31+
}
32+
33+
buf := &bytes.Buffer{}
34+
if err := tpl.Execute(buf, data.Meta); err != nil {
35+
return nil, err
36+
}
37+
data.ContentRender = buf.String()
38+
39+
// 发送邮件
40+
err = h.emailDomain.Send([]string{data.Meta.RegisterVerifyCode.Email}, data.Title, data.ContentRender)
41+
if err != nil {
42+
return nil, err
43+
}
44+
45+
return h.BaseHandler.Next(ctx, data)
46+
}
47+
48+
func (h *RegisterVerifyCode) SetNext(next handlerchain.Handler[*commonModel.Notification]) {
49+
h.BaseHandler.SetNext(next)
50+
}
51+
52+
func (h *RegisterVerifyCode) Name() string {
53+
return h.BaseHandler.GetName()
54+
}

0 commit comments

Comments
 (0)