Smail/backend/controllers/email/contacts.go
2026-09-12 09:37:52 +08:00

159 lines
4.7 KiB
Go

package email
import (
"encoding/json"
"net/http"
"strings"
"time"
"git.pcux.cn/xuans/Smail/db"
"git.pcux.cn/xuans/Smail/dto/response"
"git.pcux.cn/xuans/Smail/models"
"git.pcux.cn/xuans/Smail/utils/context"
log "github.com/sirupsen/logrus"
"xorm.io/xorm"
)
type deleteContactRequest struct {
Email string `json:"email"`
}
type trustSenderRequest struct {
Email string `json:"email"`
Trusted bool `json:"trusted"`
}
// ContactsList 查询当前用户的历史写信收件人列表(多租户严格隔离)
func ContactsList(ctx *context.Context, w http.ResponseWriter, req *http.Request) {
var contacts []models.UserContact
err := db.Instance.Table(&models.UserContact{}).
Where("user_id = ?", ctx.UserID).
OrderBy("last_used_at DESC").
Limit(100).
Find(&contacts)
if err != nil {
log.WithContext(ctx).WithError(err).Error("query user contacts failed")
response.NewErrorResponse(response.ServerError, "获取联系人失败", "").FPrint(w)
return
}
response.NewSuccessResponse(contacts).FPrint(w)
}
// DeleteContact 删除当前用户的某项历史联系人记录
func DeleteContact(ctx *context.Context, w http.ResponseWriter, req *http.Request) {
var reqData deleteContactRequest
if err := json.NewDecoder(req.Body).Decode(&reqData); err != nil {
response.NewErrorResponse(response.ParamsError, "参数错误", "").FPrint(w)
return
}
email := strings.ToLower(strings.TrimSpace(reqData.Email))
if email == "" {
response.NewErrorResponse(response.ParamsError, "联系人邮箱不能为空", "").FPrint(w)
return
}
_, err := db.Instance.Table(&models.UserContact{}).
Where("user_id = ? AND LOWER(email) = ?", ctx.UserID, email).
Delete(&models.UserContact{})
if err != nil {
log.WithContext(ctx).WithError(err).Error("delete user contact failed")
response.NewErrorResponse(response.ServerError, "删除联系人失败", "").FPrint(w)
return
}
response.NewSuccessResponse("ok").FPrint(w)
}
// TrustSender 将发件人添加至信任白名单,或从中移除
func TrustSender(ctx *context.Context, w http.ResponseWriter, req *http.Request) {
var reqData trustSenderRequest
if err := json.NewDecoder(req.Body).Decode(&reqData); err != nil {
response.NewErrorResponse(response.ParamsError, "参数错误", "").FPrint(w)
return
}
email := strings.ToLower(strings.TrimSpace(reqData.Email))
if email == "" {
response.NewErrorResponse(response.ParamsError, "发件人邮箱不能为空", "").FPrint(w)
return
}
if reqData.Trusted {
var exists bool
has, err := db.Instance.Table(&models.UserTrustedSender{}).
Where("user_id = ? AND LOWER(email) = ?", ctx.UserID, email).
Exist(&models.UserTrustedSender{})
if err != nil {
log.WithContext(ctx).WithError(err).Error("check trusted sender failed")
response.NewErrorResponse(response.ServerError, "操作失败", "").FPrint(w)
return
}
exists = has
if !exists {
item := models.UserTrustedSender{
UserID: ctx.UserID,
Email: email,
CreatedAt: time.Now(),
}
if _, err := db.Instance.Insert(&item); err != nil {
log.WithContext(ctx).WithError(err).Error("insert trusted sender failed")
response.NewErrorResponse(response.ServerError, "添加信任发件人失败", "").FPrint(w)
return
}
}
} else {
if _, err := db.Instance.Table(&models.UserTrustedSender{}).
Where("user_id = ? AND LOWER(email) = ?", ctx.UserID, email).
Delete(&models.UserTrustedSender{}); err != nil {
log.WithContext(ctx).WithError(err).Error("remove trusted sender failed")
response.NewErrorResponse(response.ServerError, "取消信任发件人失败", "").FPrint(w)
return
}
}
response.NewSuccessResponse("ok").FPrint(w)
}
// RecordUserContacts 异步批量记录发件成功后的收件人地址
func RecordUserContacts(userID int, recipients []models.UserContact) {
if userID <= 0 || len(recipients) == 0 {
return
}
now := time.Now()
_ = db.Transaction(db.Instance, func(session *xorm.Session) error {
for _, r := range recipients {
email := strings.ToLower(strings.TrimSpace(r.Email))
if email == "" {
continue
}
var existing models.UserContact
has, err := session.Table(&models.UserContact{}).
Where("user_id = ? AND LOWER(email) = ?", userID, email).
Get(&existing)
if err != nil {
return err
}
if has {
existing.LastUsedAt = now
if r.Name != "" {
existing.Name = r.Name
}
if _, err := session.ID(existing.ID).Cols("name", "last_used_at").Update(&existing); err != nil {
return err
}
} else {
item := models.UserContact{
UserID: userID,
Email: email,
Name: r.Name,
LastUsedAt: now,
}
if _, err := session.Insert(&item); err != nil {
return err
}
}
}
return nil
})
}