119 lines
2.8 KiB
Go
119 lines
2.8 KiB
Go
package imap
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/emersion/go-imap/v2"
|
|
)
|
|
|
|
var folderDisplayNames = map[string]string{
|
|
"inbox": "Inbox",
|
|
"sent": "Sent",
|
|
"drafts": "Drafts",
|
|
"trash": "Trash",
|
|
"archive": "Archive",
|
|
"spam": "Spam",
|
|
}
|
|
|
|
var folderNameHeuristics = map[string]string{
|
|
"inbox": "inbox",
|
|
"sent": "sent",
|
|
"sent items": "sent",
|
|
"sent messages": "sent",
|
|
"[gmail]/sent mail": "sent",
|
|
"inbox.sent": "sent",
|
|
"drafts": "drafts",
|
|
"[gmail]/drafts": "drafts",
|
|
"trash": "trash",
|
|
"deleted": "trash",
|
|
"[gmail]/trash": "trash",
|
|
"archive": "archive",
|
|
"all mail": "archive",
|
|
"[gmail]/all mail": "archive",
|
|
"junk": "spam",
|
|
"spam": "spam",
|
|
"[gmail]/spam": "spam",
|
|
}
|
|
|
|
// DetectFolderType classifies an IMAP mailbox for sync using SPECIAL-USE
|
|
// attributes when present, otherwise name heuristics. NoSelect mailboxes
|
|
// return "" so callers can skip sync.
|
|
func DetectFolderType(mailbox string, attrs []imap.MailboxAttr) string {
|
|
for _, attr := range attrs {
|
|
if attr == imap.MailboxAttrNoSelect {
|
|
return ""
|
|
}
|
|
}
|
|
|
|
if folderType := folderTypeFromAttrs(attrs); folderType != "" {
|
|
return folderType
|
|
}
|
|
|
|
return folderTypeFromName(mailbox)
|
|
}
|
|
|
|
// DisplayName returns a user-facing folder label from the detected type,
|
|
// or the last path segment of mailbox when type is custom or unknown.
|
|
func DisplayName(mailbox, folderType string) string {
|
|
folderType = strings.ToLower(strings.TrimSpace(folderType))
|
|
if name, ok := folderDisplayNames[folderType]; ok {
|
|
return name
|
|
}
|
|
return mailboxLeaf(mailbox)
|
|
}
|
|
|
|
func folderTypeFromAttrs(attrs []imap.MailboxAttr) string {
|
|
for _, attr := range attrs {
|
|
switch attr {
|
|
case imap.MailboxAttrSent:
|
|
return "sent"
|
|
case imap.MailboxAttrDrafts:
|
|
return "drafts"
|
|
case imap.MailboxAttrTrash:
|
|
return "trash"
|
|
case imap.MailboxAttrArchive:
|
|
return "archive"
|
|
case imap.MailboxAttrJunk:
|
|
return "spam"
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func folderTypeFromName(mailbox string) string {
|
|
full := strings.ToLower(strings.TrimSpace(mailbox))
|
|
if folderType, ok := folderNameHeuristics[full]; ok {
|
|
return folderType
|
|
}
|
|
|
|
leaf := strings.ToLower(mailboxLeaf(mailbox))
|
|
if folderType, ok := folderNameHeuristics[leaf]; ok {
|
|
return folderType
|
|
}
|
|
|
|
return "custom"
|
|
}
|
|
|
|
func mailboxLeaf(mailbox string) string {
|
|
mailbox = strings.TrimSpace(mailbox)
|
|
if mailbox == "" {
|
|
return ""
|
|
}
|
|
|
|
leaf := mailbox
|
|
for _, sep := range []string{"/", "."} {
|
|
if idx := strings.LastIndex(leaf, sep); idx >= 0 && idx < len(leaf)-len(sep) {
|
|
leaf = leaf[idx+len(sep):]
|
|
}
|
|
}
|
|
return leaf
|
|
}
|
|
|
|
// FolderDerivedLabels returns Ultimail labels inferred from IMAP mailbox path/name.
|
|
func FolderDerivedLabels(mailbox string) []string {
|
|
if strings.ToLower(mailboxLeaf(mailbox)) == "important" {
|
|
return []string{"important"}
|
|
}
|
|
return nil
|
|
}
|