feat: 收件箱功能新增按回车查看详情面板
- 添加邮件详情面板显示(主题、发件人、收件人、抄送、账户、时间、正文) - 优化邮件列表卡片样式,增加选中高亮效果 - 窗口宽度 >= 80 时启用双面板布局,左侧列表右侧详情 - 简化依赖包,从 charm.land 使用统一导入路径 - 删除未使用的 golangci/goreleaser 配置文件
This commit is contained in:
142
imap.go
142
imap.go
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
imap "github.com/BrianLeishman/go-imap"
|
||||
@@ -193,3 +194,144 @@ func sortEmailsByDate(emails []ReceivedEmail) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type EmailDetail struct {
|
||||
UID uint32
|
||||
From string
|
||||
FromName string
|
||||
To string
|
||||
Cc string
|
||||
Subject string
|
||||
Date time.Time
|
||||
TextBody string
|
||||
HTMLBody string
|
||||
Account string
|
||||
AccountID string
|
||||
}
|
||||
|
||||
func FetchEmailDetailByUID(accountID string, uid uint32) (*EmailDetail, error) {
|
||||
account, err := GetAccountByID(accountID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if account.IMAP.Host == "" {
|
||||
return nil, fmt.Errorf("IMAP host not configured for account: %s", account.Email)
|
||||
}
|
||||
|
||||
port := account.IMAP.Port
|
||||
if port == 0 {
|
||||
port = 993
|
||||
}
|
||||
|
||||
username := account.IMAP.Username
|
||||
if username == "" {
|
||||
username = account.Email
|
||||
}
|
||||
|
||||
m, err := imap.New(username, account.IMAP.Password, account.IMAP.Host, port)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to connect to IMAP server: %w", err)
|
||||
}
|
||||
defer m.Close()
|
||||
|
||||
if account.CheckID != nil && *account.CheckID {
|
||||
info := ProjectConfig.Info
|
||||
idCmd := fmt.Sprintf("ID (\"name\" \"%s\" \"version\" \"%s\" \"vendor\" \"%s\")",
|
||||
info.Name, info.Version, info.Vendor)
|
||||
_, err := m.Exec(idCmd, false, 0, func(line []byte) error {
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Printf("WARNING: failed to send IMAP ID: %v\n", err)
|
||||
}
|
||||
|
||||
m.Exec("NOOP", false, 0, nil)
|
||||
}
|
||||
|
||||
err = m.SelectFolder("INBOX")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to select inbox: %w", err)
|
||||
}
|
||||
|
||||
emails, err := m.GetEmails(int(uid))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch email: %w", err)
|
||||
}
|
||||
|
||||
if len(emails) == 0 {
|
||||
return nil, fmt.Errorf("email not found")
|
||||
}
|
||||
|
||||
var email imap.Email
|
||||
found := false
|
||||
for i := range emails {
|
||||
if emails[i] != nil {
|
||||
email = *emails[i]
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
return nil, fmt.Errorf("email not found or has been removed")
|
||||
}
|
||||
|
||||
accountName := getEmailProviderName(account.Email)
|
||||
accountIDName := account.Email
|
||||
if account.Name != "" {
|
||||
accountName = account.Name
|
||||
accountIDName = account.Name
|
||||
}
|
||||
|
||||
var fromName string
|
||||
var fromAddr string
|
||||
if email.From != nil {
|
||||
for name, addr := range email.From {
|
||||
fromName = name
|
||||
fromAddr = addr
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
var toList []string
|
||||
if email.To != nil {
|
||||
for name, addr := range email.To {
|
||||
if name != "" {
|
||||
toList = append(toList, fmt.Sprintf("%s <%s>", name, addr))
|
||||
} else {
|
||||
toList = append(toList, addr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var ccList []string
|
||||
if email.CC != nil {
|
||||
for name, addr := range email.CC {
|
||||
if name != "" {
|
||||
ccList = append(ccList, fmt.Sprintf("%s <%s>", name, addr))
|
||||
} else {
|
||||
ccList = append(ccList, addr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fromStr := fromAddr
|
||||
if fromName != "" {
|
||||
fromStr = fmt.Sprintf("%s <%s>", fromName, fromAddr)
|
||||
}
|
||||
|
||||
return &EmailDetail{
|
||||
UID: uint32(email.UID),
|
||||
From: fromStr,
|
||||
FromName: fromName,
|
||||
To: strings.Join(toList, ", "),
|
||||
Cc: strings.Join(ccList, ", "),
|
||||
Subject: email.Subject,
|
||||
Date: email.Sent,
|
||||
TextBody: email.Text,
|
||||
HTMLBody: email.HTML,
|
||||
Account: accountName,
|
||||
AccountID: accountIDName,
|
||||
}, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user