Files
mail/imap.go
Z.To 7ab9f00c4f Fearure:
- 增加收件箱功能(有BUG)
- 增加已发送|草稿箱|发送历史 本地记录
2026-04-09 21:48:21 +08:00

182 lines
3.5 KiB
Go

package main
import (
"fmt"
"time"
imap "github.com/BrianLeishman/go-imap"
)
type ReceivedEmail struct {
UID uint32
From string
FromName string
Subject string
Date time.Time
Preview string
Account string
AccountID string
}
func getEmailProviderName(email string) string {
if len(email) == 0 {
return "Email"
}
atIdx := -1
for i := len(email) - 1; i >= 0; i-- {
if email[i] == '@' {
atIdx = i
break
}
}
if atIdx == -1 {
return "Email"
}
domain := email[atIdx+1:]
for i := len(domain) - 1; i >= 0; i-- {
if domain[i] == '.' {
return domain[:i]
}
}
return domain
}
func FetchUnreadEmails(account Account, days int) ([]ReceivedEmail, error) {
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()
err = m.SelectFolder("INBOX")
if err != nil {
return nil, fmt.Errorf("failed to select inbox: %w", err)
}
sinceDate := time.Now().AddDate(0, 0, -days)
uids, err := m.GetUIDs(imap.Search().Since(sinceDate).Unseen().Build())
if err != nil {
return nil, fmt.Errorf("failed to search emails: %w", err)
}
if len(uids) == 0 {
return nil, nil
}
overviews, err := m.GetOverviews(uids...)
if err != nil {
return nil, fmt.Errorf("failed to fetch emails: %w", err)
}
var emails []ReceivedEmail
accountName := getEmailProviderName(account.Email)
accountID := account.Email
if account.Name != "" {
accountName = account.Name
accountID = account.Name
}
for uid, email := range overviews {
from := ""
if len(email.From) > 0 {
for _, addr := range email.From {
from = addr
break
}
}
emails = append(emails, ReceivedEmail{
UID: uint32(uid),
From: from,
FromName: "",
Subject: email.Subject,
Date: email.Sent,
Preview: fmt.Sprintf("(%.1f KB)", float64(email.Size)/1024),
Account: accountName,
AccountID: accountID,
})
}
return emails, nil
}
func GetAccountByEmail(email string) (Account, error) {
accounts, err := getAccounts()
if err != nil {
return Account{}, err
}
for _, acc := range accounts {
if acc.Email == email || acc.Name == email {
return acc, nil
}
}
return Account{}, fmt.Errorf("account not found: %s", email)
}
func GetAccountByID(id string) (Account, error) {
accounts, err := getAccounts()
if err != nil {
return Account{}, err
}
for _, acc := range accounts {
if acc.Email == id || acc.Name == id {
return acc, nil
}
}
return Account{}, fmt.Errorf("account not found: %s", id)
}
func FetchAllUnreadEmails(days int) ([]ReceivedEmail, error) {
accounts, err := getAccounts()
if err != nil {
return nil, err
}
if len(accounts) == 0 {
return nil, fmt.Errorf("no accounts configured")
}
var allEmails []ReceivedEmail
for _, account := range accounts {
emails, err := FetchUnreadEmails(account, days)
if err != nil {
continue
}
allEmails = append(allEmails, emails...)
}
sortEmailsByDate(allEmails)
return allEmails, nil
}
func sortEmailsByDate(emails []ReceivedEmail) {
for i := 0; i < len(emails)-1; i++ {
for j := i + 1; j < len(emails); j++ {
if emails[j].Date.After(emails[i].Date) {
emails[i], emails[j] = emails[j], emails[i]
}
}
}
}