summaryrefslogtreecommitdiffci
path: root/internal/mailer
diff refs
from: back
to: back
| flip
diff options
context:
space:
mode:
Diffstat (limited to 'internal/mailer')
-rw-r--r--internal/mailer/mailer.go73
1 files changed, 49 insertions, 24 deletions
diff --git a/internal/mailer/mailer.go b/internal/mailer/mailer.go
index eb86d56..33db4f7 100644
--- a/internal/mailer/mailer.go
+++ b/internal/mailer/mailer.go
@@ -14,9 +14,9 @@ import (
"sync"
"time"
- "github.com/SayaAndy/saya-today-web/internal/b2"
+ "github.com/SayaAndy/saya-today-web/internal/blog"
"github.com/SayaAndy/saya-today-web/internal/templatemanager"
- "github.com/SayaAndy/saya-today-web/locale"
+ "github.com/SayaAndy/saya-today-web/l10n"
"github.com/dgraph-io/ristretto/v2"
"github.com/gofiber/fiber/v2"
"github.com/wneessen/go-mail"
@@ -43,8 +43,6 @@ type Mailer struct {
hashMap map[string][]byte
hashMapMutex sync.RWMutex
-
- l map[string]*locale.LocaleConfig
}
type SubscriptionType int
@@ -55,7 +53,7 @@ const (
Specific
)
-func NewMailer(db *sql.DB, clientHost string, mailHost string, publicName string, mailAddress string, username string, password string, salt []byte, localization map[string]*locale.LocaleConfig) (*Mailer, error) {
+func NewMailer(db *sql.DB, clientHost string, mailHost string, publicName string, mailAddress string, username string, password string, salt []byte) (*Mailer, error) {
verificationCodes, err := ristretto.NewCache(&ristretto.Config[uint64, string]{
NumCounters: 10000,
MaxCost: 1 << 20, // 1 MB
@@ -111,7 +109,7 @@ func NewMailer(db *sql.DB, clientHost string, mailHost string, publicName string
End time.Time
CodeExpiry time.Time
}, 0),
- l: localization}, nil
+ }, nil
}
func (m *Mailer) GetHash(id string) []byte {
@@ -151,15 +149,19 @@ func (m *Mailer) MailIsTaken(email string) (bool, error) {
if err != nil {
return false, fmt.Errorf("failed to initialize transaction with db: %s", err)
}
+
+ slog.Debug("began db transaction", slog.String("method", "MailIsTaken"))
defer func(tx *sql.Tx) {
if err = tx.Commit(); err != nil {
tx.Rollback()
}
+ slog.Debug("ended db transaction", slog.String("method", "MailIsTaken"))
}(tx)
var rows *sql.Rows
if rows, err = tx.Query(`SELECT email FROM user_email_table WHERE email=? LIMIT 1;`, email); err != nil {
tx.Rollback()
+
return false, fmt.Errorf("failed to query user-email settings in db: %s", err)
}
defer rows.Close()
@@ -173,10 +175,13 @@ func (m *Mailer) GetInfo(userIdHash []byte) (email string, lang string, err erro
if err != nil {
return "", "", fmt.Errorf("failed to initialize transaction with db: %s", err)
}
+
+ slog.Debug("began db transaction", slog.String("method", "GetInfo"))
defer func(tx *sql.Tx) {
if err = tx.Commit(); err != nil {
tx.Rollback()
}
+ slog.Debug("ended db transaction", slog.String("method", "GetInfo"))
}(tx)
var rows *sql.Rows
@@ -254,10 +259,9 @@ func (m *Mailer) SendVerificationCode(userId string, address string, lang string
verificationInfo := fmt.Sprintf("%s.%s", base64.RawStdEncoding.EncodeToString([]byte(userId)), base64.RawStdEncoding.EncodeToString([]byte(address)))
m.verificationCodes.Set(verificationCode, verificationInfo, int64(len(verificationInfo)+8))
- message.Subject(m.l[lang].Mail.VerifyEmail.Subject)
+ message.Subject(l10n.T.GetPath(lang, "Mail", "VerifyEmail", "Subject").(string))
msg, err := m.tm.Render("verify-email", fiber.Map{
- "L": m.l[lang],
"Lang": lang,
"VerificationCode": fmt.Sprintf("%X", verificationCode),
"ClientHost": m.clientHost,
@@ -310,18 +314,22 @@ func (m *Mailer) Verify(verificationCodeEncoded string, lang string) error {
return fmt.Errorf("failed to initialize transaction with db: %s", err)
}
+ slog.Debug("began db transaction", slog.String("method", "Verify"))
if _, err = tx.Exec(`INSERT INTO user_email_table(user_id, email, lang) VALUES(?, ?, ?)
ON CONFLICT(user_id) DO UPDATE SET
email=excluded.email,
lang=excluded.lang;`, m.GetHash(string(userId)), address, lang); err != nil {
tx.Rollback()
+ slog.Debug("ended db transaction", slog.String("method", "Verify"))
return fmt.Errorf("failed to configure user-email settings in db: %s", err)
}
if err = tx.Commit(); err != nil {
tx.Rollback()
+ slog.Debug("ended db transaction", slog.String("method", "Verify"))
return fmt.Errorf("failed to commit transaction to db: %s", err)
}
+ slog.Debug("ended db transaction", slog.String("method", "Verify"))
m.verificationCodes.Del(verificationCode)
delete(m.lostMailMap, verificationSegments[0])
@@ -333,10 +341,13 @@ func (m *Mailer) GetSubscriptions(userId string) (subscriptionType SubscriptionT
if err != nil {
return None, nil, fmt.Errorf("failed to initialize transaction with db: %s", err)
}
+
+ slog.Debug("began db transaction", slog.String("method", "GetSubscriptions"))
defer func(tx *sql.Tx) {
if err = tx.Commit(); err != nil {
tx.Rollback()
}
+ slog.Debug("ended db transaction", slog.String("method", "GetSubscriptions"))
}(tx)
hash := m.GetHash(userId)
@@ -373,6 +384,8 @@ func (m *Mailer) Subscribe(userIdHash []byte, subscriptionType SubscriptionType,
return fmt.Errorf("failed to initialize transaction with db: %s", err)
}
+ slog.Debug("began db transaction", slog.String("method", "Subscribe"))
+
slices.Sort(tags)
tagsOutput := ""
switch subscriptionType {
@@ -388,26 +401,31 @@ func (m *Mailer) Subscribe(userIdHash []byte, subscriptionType SubscriptionType,
ON CONFLICT(user_id) DO UPDATE SET
tags=excluded.tags;`, userIdHash, tagsOutput); err != nil {
tx.Rollback()
+ slog.Debug("ended db transaction", slog.String("method", "Subscribe"))
return fmt.Errorf("failed to configure user-to-tags table in db for the user: %s", err)
}
if err = tx.Commit(); err != nil {
tx.Rollback()
+ slog.Debug("ended db transaction", slog.String("method", "Subscribe"))
return fmt.Errorf("failed to commit transaction to db: %s", err)
}
+ slog.Debug("ended db transaction", slog.String("method", "Subscribe"))
return nil
}
-func (m *Mailer) NewPost(post *b2.BlogPage) error {
+func (m *Mailer) NewPost(post *blog.Page) error {
tx, err := m.db.Begin()
if err != nil {
return fmt.Errorf("failed to initialize transaction with db: %s", err)
}
+ slog.Debug("began db transaction", slog.String("method", "NewPost"))
var rows *sql.Rows
if rows, err = tx.Query(`SELECT user_id, tags FROM subscription_user_to_tags_table;`); err != nil {
tx.Rollback()
+ slog.Debug("ended db transaction", slog.String("method", "NewPost"))
return fmt.Errorf("failed to query user-to-tags table in db: %s", err)
}
@@ -431,21 +449,11 @@ rowLoop:
continue
}
- email, lang, err := m.GetInfo(userId)
- if err != nil {
- slog.Warn("failed to get info about the user", slog.String("error", err.Error()), slog.Int("index", i), slog.String("user_id", base64.RawStdEncoding.EncodeToString(userId)))
- continue
- }
-
- if lang != post.Lang {
- continue
- }
-
if tagsString == "_all" {
usersToSend = append(usersToSend, struct {
userId []byte
email string
- }{userId, email})
+ }{userId, ""})
continue
}
@@ -455,7 +463,7 @@ rowLoop:
usersToSend = append(usersToSend, struct {
userId []byte
email string
- }{userId, email})
+ }{userId, ""})
continue rowLoop
}
}
@@ -463,18 +471,35 @@ rowLoop:
tx.Commit()
rows.Close()
+ slog.Debug("ended db transaction", slog.String("method", "NewPost"))
+
+ for i := range usersToSend {
+ email, lang, err := m.GetInfo(usersToSend[i].userId)
+ if err != nil {
+ slog.Warn("failed to get info about the user", slog.String("error", err.Error()), slog.Int("index", i), slog.String("user_id", base64.RawStdEncoding.EncodeToString(userId)))
+ continue
+ }
+
+ if lang != post.Lang {
+ continue
+ }
+
+ usersToSend[i].email = email
+ }
messages := make([]*mail.Msg, 0, len(usersToSend))
for _, user := range usersToSend {
+ if user.email == "" {
+ continue
+ }
unsubscribeCodeBytes := make([]byte, 8)
rand.Read(unsubscribeCodeBytes)
unsubscribeCode := binary.LittleEndian.Uint64(unsubscribeCodeBytes)
- unsubscribeFooter := strings.Replace(m.l[post.Lang].Mail.UnsubscribeFooter, "{}", fmt.Sprintf(`<a style="color: #273de1 !important;" href="https://%s/%s/user/unsubscribe?code=%X">`, m.clientHost, post.Lang, unsubscribeCode), 1)
+ unsubscribeFooter := strings.Replace(l10n.T.GetPath(post.Lang, "Mail", "UnsubscribeFooter").(string), "{}", fmt.Sprintf(`<a style="color: #273de1 !important;" href="https://%s/%s/user/unsubscribe?code=%X">`, m.clientHost, post.Lang, unsubscribeCode), 1)
unsubscribeFooter = strings.Replace(unsubscribeFooter, "{/}", "</a>", 1)
msgBody, err := m.tm.Render("new-post", fiber.Map{
- "L": m.l[post.Lang],
"Lang": post.Lang,
"Post": post,
"ClientHost": m.clientHost,
@@ -500,7 +525,7 @@ rowLoop:
message.SetMessageID()
message.SetDate()
message.SetBulk()
- message.Subject(m.l[post.Lang].Mail.NewPost.Subject)
+ message.Subject(l10n.T.GetPath(post.Lang, "Mail", "NewPost", "Subject").(string))
message.SetBodyString(mail.TypeTextHTML, string(msgBody))
m.unsubscribeCodes.Set(unsubscribeCode, user.userId, 40)