init: pristine aerc 0.20.0 source
This commit is contained in:
@@ -0,0 +1,313 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.sr.ht/~rjarry/aerc/lib/parse"
|
||||
"github.com/emersion/go-message/mail"
|
||||
)
|
||||
|
||||
// Flags is an abstraction around the different flags which can be present in
|
||||
// different email backends and represents a flag that we use in the UI.
|
||||
type Flags uint32
|
||||
|
||||
const (
|
||||
// SeenFlag marks a message as having been seen previously
|
||||
SeenFlag Flags = 1 << iota
|
||||
|
||||
// RecentFlag marks a message as being recent
|
||||
RecentFlag
|
||||
|
||||
// AnsweredFlag marks a message as having been replied to
|
||||
AnsweredFlag
|
||||
|
||||
// ForwardedFlag marks a message as having been forwarded
|
||||
ForwardedFlag
|
||||
|
||||
// DeletedFlag marks a message as having been deleted
|
||||
DeletedFlag
|
||||
|
||||
// FlaggedFlag marks a message with a user flag
|
||||
FlaggedFlag
|
||||
|
||||
// DraftFlag marks a message as a draft
|
||||
DraftFlag
|
||||
)
|
||||
|
||||
func (f Flags) Has(flags Flags) bool {
|
||||
return f&flags == flags
|
||||
}
|
||||
|
||||
type Role string
|
||||
|
||||
var Roles = map[string]Role{
|
||||
"all": AllRole,
|
||||
"archive": ArchiveRole,
|
||||
"drafts": DraftsRole,
|
||||
"inbox": InboxRole,
|
||||
"junk": JunkRole,
|
||||
"sent": SentRole,
|
||||
"trash": TrashRole,
|
||||
"query": QueryRole,
|
||||
}
|
||||
|
||||
const (
|
||||
AllRole Role = "all"
|
||||
ArchiveRole Role = "archive"
|
||||
DraftsRole Role = "drafts"
|
||||
InboxRole Role = "inbox"
|
||||
JunkRole Role = "junk"
|
||||
SentRole Role = "sent"
|
||||
TrashRole Role = "trash"
|
||||
// Custom aerc roles
|
||||
QueryRole Role = "query"
|
||||
// virtual node created by the directory tree
|
||||
VirtualRole Role = "virtual"
|
||||
)
|
||||
|
||||
type Directory struct {
|
||||
Name string
|
||||
// Exists messages in the Directory
|
||||
Exists int
|
||||
// Recent messages in the Directory
|
||||
Recent int
|
||||
// Unseen messages in the Directory
|
||||
Unseen int
|
||||
// IANA role
|
||||
Role Role
|
||||
}
|
||||
|
||||
type DirectoryInfo struct {
|
||||
Name string
|
||||
// The total number of messages in this mailbox.
|
||||
Exists int
|
||||
// The number of messages not seen since the last time the mailbox was opened.
|
||||
Recent int
|
||||
// The number of unread messages
|
||||
Unseen int
|
||||
}
|
||||
|
||||
// Capabilities provides the backend capabilities
|
||||
type Capabilities struct {
|
||||
Sort bool
|
||||
Thread bool
|
||||
Extensions []string
|
||||
}
|
||||
|
||||
func (c *Capabilities) Has(s string) bool {
|
||||
for _, ext := range c.Extensions {
|
||||
if ext == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type UID string
|
||||
|
||||
func UidToUint32(uid UID) uint32 {
|
||||
u, _ := strconv.ParseUint(string(uid), 10, 32)
|
||||
return uint32(u)
|
||||
}
|
||||
|
||||
func Uint32ToUid(u uint32) UID {
|
||||
return UID(fmt.Sprintf("%012d", u))
|
||||
}
|
||||
|
||||
func UidToUint32List(uids []UID) []uint32 {
|
||||
ulist := make([]uint32, 0, len(uids))
|
||||
for _, uid := range uids {
|
||||
ulist = append(ulist, UidToUint32(uid))
|
||||
}
|
||||
return ulist
|
||||
}
|
||||
|
||||
func Uint32ToUidList(ulist []uint32) []UID {
|
||||
uids := make([]UID, 0, len(ulist))
|
||||
for _, u := range ulist {
|
||||
uids = append(uids, Uint32ToUid(u))
|
||||
}
|
||||
return uids
|
||||
}
|
||||
|
||||
// A MessageInfo holds information about the structure of a message
|
||||
type MessageInfo struct {
|
||||
BodyStructure *BodyStructure
|
||||
Envelope *Envelope
|
||||
Flags Flags
|
||||
Labels []string
|
||||
Filenames []string
|
||||
InternalDate time.Time
|
||||
RFC822Headers *mail.Header
|
||||
Refs []string
|
||||
Size uint32
|
||||
Uid UID
|
||||
Error error
|
||||
}
|
||||
|
||||
func (mi *MessageInfo) MsgId() (msgid string, err error) {
|
||||
if mi == nil {
|
||||
return "", errors.New("msg is nil")
|
||||
}
|
||||
if mi.Envelope == nil {
|
||||
return "", errors.New("envelope is nil")
|
||||
}
|
||||
return mi.Envelope.MessageId, nil
|
||||
}
|
||||
|
||||
func (mi *MessageInfo) InReplyTo() (msgid string, err error) {
|
||||
if mi == nil {
|
||||
return "", errors.New("msg is nil")
|
||||
}
|
||||
if mi.Envelope != nil && mi.Envelope.InReplyTo != "" {
|
||||
return mi.Envelope.InReplyTo, nil
|
||||
}
|
||||
if mi.RFC822Headers == nil {
|
||||
return "", errors.New("header is nil")
|
||||
}
|
||||
list := parse.MsgIDList(mi.RFC822Headers, "In-Reply-To")
|
||||
if len(list) == 0 {
|
||||
return "", errors.New("no results")
|
||||
}
|
||||
return list[0], err
|
||||
}
|
||||
|
||||
func (mi *MessageInfo) References() ([]string, error) {
|
||||
if mi == nil {
|
||||
return []string{}, errors.New("msg is nil")
|
||||
}
|
||||
if mi.Refs != nil {
|
||||
return mi.Refs, nil
|
||||
}
|
||||
if mi.RFC822Headers == nil {
|
||||
return []string{}, errors.New("header is nil")
|
||||
}
|
||||
list := parse.MsgIDList(mi.RFC822Headers, "References")
|
||||
if len(list) == 0 {
|
||||
return []string{}, errors.New("no results")
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// A MessageBodyPart can be displayed in the message viewer
|
||||
type MessageBodyPart struct {
|
||||
Reader io.Reader
|
||||
Uid UID
|
||||
}
|
||||
|
||||
// A FullMessage is the entire message
|
||||
type FullMessage struct {
|
||||
Reader io.Reader
|
||||
Uid UID
|
||||
}
|
||||
|
||||
type BodyStructure struct {
|
||||
MIMEType string
|
||||
MIMESubType string
|
||||
Params map[string]string
|
||||
Description string
|
||||
Encoding string
|
||||
Parts []*BodyStructure
|
||||
Disposition string
|
||||
DispositionParams map[string]string
|
||||
}
|
||||
|
||||
// PartAtIndex returns the BodyStructure at the requested index
|
||||
func (bs *BodyStructure) PartAtIndex(index []int) (*BodyStructure, error) {
|
||||
if len(index) == 0 {
|
||||
return bs, nil
|
||||
}
|
||||
cur := index[0]
|
||||
rest := index[1:]
|
||||
// passed indexes are 1 based, we need to convert back to actual indexes
|
||||
curidx := cur - 1
|
||||
if curidx < 0 {
|
||||
return nil, fmt.Errorf("invalid index, expected 1 based input")
|
||||
}
|
||||
|
||||
// no children, base case
|
||||
if len(bs.Parts) == 0 {
|
||||
if len(rest) != 0 {
|
||||
return nil, fmt.Errorf("more index levels given than available")
|
||||
}
|
||||
if cur == 1 {
|
||||
return bs, nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("invalid index %v for non multipart", cur)
|
||||
}
|
||||
}
|
||||
|
||||
if cur > len(bs.Parts) {
|
||||
return nil, fmt.Errorf("invalid index %v, only have %v children",
|
||||
cur, len(bs.Parts))
|
||||
}
|
||||
|
||||
return bs.Parts[curidx].PartAtIndex(rest)
|
||||
}
|
||||
|
||||
func (bs *BodyStructure) FullMIMEType() string {
|
||||
mime := fmt.Sprintf("%s/%s", bs.MIMEType, bs.MIMESubType)
|
||||
return strings.ToLower(mime)
|
||||
}
|
||||
|
||||
func (bs *BodyStructure) FileName() string {
|
||||
if filename, ok := bs.DispositionParams["filename"]; ok {
|
||||
return filename
|
||||
} else if filename, ok := bs.Params["name"]; ok {
|
||||
// workaround golang not supporting RFC2231 besides ASCII and UTF8
|
||||
return filename
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Envelope struct {
|
||||
Date time.Time
|
||||
Subject string
|
||||
From []*mail.Address
|
||||
ReplyTo []*mail.Address
|
||||
Sender []*mail.Address
|
||||
To []*mail.Address
|
||||
Cc []*mail.Address
|
||||
Bcc []*mail.Address
|
||||
MessageId string
|
||||
InReplyTo string
|
||||
}
|
||||
|
||||
// OriginalMail is helper struct used for reply/forward
|
||||
type OriginalMail struct {
|
||||
Date time.Time
|
||||
From string
|
||||
Text string
|
||||
MIMEType string
|
||||
RFC822Headers *mail.Header
|
||||
Folder string
|
||||
}
|
||||
|
||||
type SignatureValidity int32
|
||||
|
||||
const (
|
||||
UnknownValidity SignatureValidity = iota
|
||||
Valid
|
||||
InvalidSignature
|
||||
UnknownEntity
|
||||
UnsupportedMicalg
|
||||
MicalgMismatch
|
||||
)
|
||||
|
||||
type MessageDetails struct {
|
||||
IsEncrypted bool
|
||||
IsSigned bool
|
||||
SignedBy string // Primary identity of signing key
|
||||
SignedByKeyId uint64
|
||||
SignatureValidity SignatureValidity
|
||||
SignatureError string
|
||||
DecryptedWith string // Primary Identity of decryption key
|
||||
DecryptedWithKeyId uint64 // Public key id of decryption key
|
||||
Body io.Reader
|
||||
Micalg string
|
||||
}
|
||||
Reference in New Issue
Block a user