Files
zeekayandHanzo Dev aa87442fdd Record upstream authorship centrally in NOTICE instead of in every file header
Source files keep their SPDX-License-Identifier and Hanzo copyright line; the
Gitea, Gogs and LFS Test Server copyrights they used to repeat now live once in
NOTICE, alongside LICENSE. The header lint accepts any copyright line above the
SPDX line, so it no longer demands an upstream one.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 17:50:35 -07:00

129 lines
4.4 KiB
Go

// Copyright 2026 Hanzo AI, Inc. All rights reserved.
// SPDX-License-Identifier: MIT
package mailer
import (
"bytes"
"fmt"
user_model "github.com/hanzoai/git/models/user"
"github.com/hanzoai/git/modules/log"
"github.com/hanzoai/git/modules/setting"
"github.com/hanzoai/git/modules/templates"
"github.com/hanzoai/git/modules/timeutil"
"github.com/hanzoai/git/modules/translation"
sender_service "github.com/hanzoai/git/services/mailer/sender"
)
const (
mailAuthActivate templates.TplName = "user/auth/activate"
mailAuthActivateEmail templates.TplName = "user/auth/activate_email"
mailAuthResetPassword templates.TplName = "user/auth/reset_passwd"
mailAuthRegisterNotify templates.TplName = "user/auth/register_notify"
)
// sendUserMail sends a mail to the user
func sendUserMail(language string, u *user_model.User, tpl templates.TplName, code, subject, info string) {
locale := translation.NewLocale(language)
data := map[string]any{
"locale": locale,
"DisplayName": u.DisplayName(),
"ActiveCodeLives": timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, locale),
"ResetPwdCodeLives": timeutil.MinutesToFriendly(setting.Service.ResetPwdCodeLives, locale),
"Code": code,
"Language": locale.Language(),
}
var content bytes.Buffer
if err := LoadedTemplates().BodyTemplates.ExecuteTemplate(&content, string(tpl), data); err != nil {
log.Error("Template: %v", err)
return
}
msg := sender_service.NewMessage(u.EmailTo(), subject, content.String())
msg.Info = fmt.Sprintf("UID: %d, %s", u.ID, info)
SendAsync(msg)
}
// SendActivateAccountMail sends an activation mail to the user (new user registration)
func SendActivateAccountMail(locale translation.Locale, u *user_model.User) {
if setting.MailService == nil {
// No mail service configured
return
}
opts := &user_model.TimeLimitCodeOptions{Purpose: user_model.TimeLimitCodeActivateAccount}
sendUserMail(locale.Language(), u, mailAuthActivate, user_model.GenerateUserTimeLimitCode(opts, u), locale.TrString("mail.activate_account"), "activate account")
}
// SendResetPasswordMail sends a password reset mail to the user
func SendResetPasswordMail(u *user_model.User) {
if setting.MailService == nil {
// No mail service configured
return
}
locale := translation.NewLocale(u.Language)
opts := &user_model.TimeLimitCodeOptions{Purpose: user_model.TimeLimitCodeResetPassword}
sendUserMail(u.Language, u, mailAuthResetPassword, user_model.GenerateUserTimeLimitCode(opts, u), locale.TrString("mail.reset_password"), "recover account")
}
// SendActivateEmailMail sends confirmation email to confirm new email address
func SendActivateEmailMail(u *user_model.User, email string) {
if setting.MailService == nil {
// No mail service configured
return
}
locale := translation.NewLocale(u.Language)
opts := &user_model.TimeLimitCodeOptions{Purpose: user_model.TimeLimitCodeActivateEmail, NewEmail: email}
data := map[string]any{
"locale": locale,
"DisplayName": u.DisplayName(),
"ActiveCodeLives": timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, locale),
"Code": user_model.GenerateUserTimeLimitCode(opts, u),
"Email": email,
"Language": locale.Language(),
}
var content bytes.Buffer
if err := LoadedTemplates().BodyTemplates.ExecuteTemplate(&content, string(mailAuthActivateEmail), data); err != nil {
log.Error("Template: %v", err)
return
}
msg := sender_service.NewMessage(email, locale.TrString("mail.activate_email"), content.String())
msg.Info = fmt.Sprintf("UID: %d, activate email", u.ID)
SendAsync(msg)
}
// SendRegisterNotifyMail triggers a notify e-mail by admin created a account.
func SendRegisterNotifyMail(u *user_model.User) {
if setting.MailService == nil || !u.IsActive {
// No mail service configured OR user is inactive
return
}
locale := translation.NewLocale(u.Language)
data := map[string]any{
"locale": locale,
"DisplayName": u.DisplayName(),
"Username": u.Name,
"Language": locale.Language(),
}
var content bytes.Buffer
if err := LoadedTemplates().BodyTemplates.ExecuteTemplate(&content, string(mailAuthRegisterNotify), data); err != nil {
log.Error("Template: %v", err)
return
}
msg := sender_service.NewMessage(u.EmailTo(), locale.TrString("mail.register_notify", setting.AppName), content.String())
msg.Info = fmt.Sprintf("UID: %d, registration notify", u.ID)
SendAsync(msg)
}