feat(worker): integrate GeoIP functionality into email notifications and enhance email template with region information

This commit is contained in:
keven1024
2026-05-23 21:25:58 +08:00
parent 0cb30b6293
commit 9a9418c564
11 changed files with 3161 additions and 2065 deletions

View File

@@ -6,6 +6,7 @@ require (
github.com/go-resty/resty/v2 v2.16.5
github.com/google/uuid v1.6.0
github.com/hibiken/asynq v0.26.0
github.com/mocktools/go-smtp-mock/v2 v2.5.4
github.com/openai/openai-go/v3 v3.30.0
github.com/samber/lo v1.53.0
github.com/spf13/cast v1.10.0
@@ -18,7 +19,6 @@ require (
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/mocktools/go-smtp-mock/v2 v2.5.4 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/redis/go-redis/v9 v9.18.0 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect

View File

@@ -40,6 +40,8 @@ github.com/samber/lo v1.53.0 h1:t975lj2py4kJPQ6haz1QMgtId2gtmfktACxIXArw3HM=
github.com/samber/lo v1.53.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=

View File

@@ -2,7 +2,9 @@ package services
import (
"fmt"
"net/url"
"pkg/i18n"
pkgmail "pkg/mail"
"pkg/models"
u "pkg/utils"
"strings"
@@ -44,8 +46,9 @@ func SendWebhook(webhook models.NotifyWebhook) error {
type EmailTemplateData struct {
Locale string
IP string
ShareType models.ShareType
Region string
FileName string
ShareType models.ShareType
}
func SendEmail(to string, emailTemplateData EmailTemplateData, options ...mail.Option) error {
@@ -63,16 +66,27 @@ func SendEmail(to string, emailTemplateData EmailTemplateData, options ...mail.O
if username == "" {
return fmt.Errorf("smtp.username is required")
}
port := lo.Ternary(cast.ToInt(smtp["port"]) != 0, cast.ToInt(smtp["port"]), mail.DefaultPortSSL)
templateData := map[string]any{
"IP": emailTemplateData.IP,
"SiteURL": u.GetEnv("site.url"),
"ShareType": i18n.T(emailTemplateData.Locale, lo.Ternary(emailTemplateData.ShareType == models.ShareTypeText, "share_type_text", "share_type_file")),
"FileName": emailTemplateData.FileName,
port := mail.DefaultPortSSL
if smtpPort := cast.ToInt(smtp["port"]); smtpPort != 0 {
port = smtpPort
}
p, err := url.Parse(u.GetEnv("site.url"))
subject := i18n.TWithData(emailTemplateData.Locale, "notify_email_subject", map[string]any{
"SiteURL": p.Host,
})
htmlBody, err := pkgmail.RenderMailTemplate("pull-notify", map[string]string{
"EMAIL-TITLE": subject,
"EMAIL-INTRO": i18n.T(emailTemplateData.Locale, "notify_email_intro"),
"EMAIL-FILEICON": lo.Ternary(emailTemplateData.ShareType == models.ShareTypeText, "spiral_notepad", "file_folder"),
"EMAIL-FILENAME": emailTemplateData.FileName,
"EMAIL-IP": emailTemplateData.IP,
"EMAIL-REGION": emailTemplateData.Region,
"EMAIL-LABEL-REGION": i18n.T(emailTemplateData.Locale, "notify_email_label_region"),
})
if err != nil {
return err
}
subject := i18n.TWithData(emailTemplateData.Locale, "notify_email_subject", templateData)
body := i18n.TWithData(emailTemplateData.Locale, "notify_email_body", templateData)
message := mail.NewMsg()
if err := message.From(username); err != nil {
return err
@@ -81,7 +95,7 @@ func SendEmail(to string, emailTemplateData EmailTemplateData, options ...mail.O
return err
}
message.Subject(subject)
message.SetBodyString(mail.TypeTextPlain, body)
message.SetBodyString(mail.TypeTextHTML, htmlBody)
options = append([]mail.Option{
mail.WithPort(port),

View File

@@ -7,6 +7,7 @@ import (
"fmt"
"os"
"path/filepath"
"pkg/geoip"
"pkg/models"
u "pkg/utils"
"worker/internal/services"
@@ -77,12 +78,18 @@ func ShareNotify(ctx context.Context, task *asynq.Task) error {
successCount++
}
region := "-"
if info := geoip.GetIpGeoInfo(payload.IP); info != nil {
region = info.Emoji + " " + info.Country.Country.Names.English
}
for _, email := range shareInfo.NotifyEmails {
if err := services.SendEmail(email, services.EmailTemplateData{
Locale: shareInfo.Locale,
ShareType: shareInfo.Type,
FileName: shareInfo.FileName,
FileName: lo.Ternary(shareInfo.Type == models.ShareTypeFile, shareInfo.FileName, lo.Substring(shareInfo.Data, 0, 7)+"..."),
IP: payload.IP,
Region: region,
ShareType: shareInfo.Type,
}); err != nil {
errs = append(errs, err)
continue

View File

@@ -2,6 +2,7 @@ package main
import (
"log"
"pkg/geoip"
"pkg/i18n"
"pkg/utils"
"worker/internal/tasks"
@@ -26,6 +27,9 @@ func main() {
if err := i18n.Init(); err != nil {
log.Fatalf("failed to init i18n: %v", err)
}
if err := geoip.Init(); err != nil {
log.Fatalf("failed to init geoip: %v", err)
}
srv := asynq.NewServer(
utils.RedisURI2AsynqOpt(utils.GetEnv("redis.url")),