2019-07-08 04:43:56 +02:00
|
|
|
package models
|
|
|
|
|
|
|
|
import (
|
2019-07-08 04:43:58 +02:00
|
|
|
"fmt"
|
2019-07-08 04:43:56 +02:00
|
|
|
"io"
|
2020-08-19 12:01:45 +02:00
|
|
|
gomail "net/mail"
|
2019-07-08 04:43:58 +02:00
|
|
|
"regexp"
|
|
|
|
"strings"
|
2019-07-08 04:43:56 +02:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/emersion/go-message/mail"
|
|
|
|
)
|
|
|
|
|
2019-07-08 04:43:58 +02:00
|
|
|
// Flag 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 Flag int
|
|
|
|
|
|
|
|
const (
|
|
|
|
// SeenFlag marks a message as having been seen previously
|
|
|
|
SeenFlag Flag = iota
|
|
|
|
|
|
|
|
// RecentFlag marks a message as being recent
|
|
|
|
RecentFlag
|
|
|
|
|
|
|
|
// AnsweredFlag marks a message as having been replied to
|
|
|
|
AnsweredFlag
|
|
|
|
|
|
|
|
// DeletedFlag marks a message as having been deleted
|
|
|
|
DeletedFlag
|
|
|
|
|
|
|
|
// FlaggedFlag marks a message with a user flag
|
|
|
|
FlaggedFlag
|
|
|
|
)
|
|
|
|
|
2019-07-08 04:43:56 +02:00
|
|
|
type Directory struct {
|
|
|
|
Name string
|
|
|
|
Attributes []string
|
|
|
|
}
|
|
|
|
|
|
|
|
type DirectoryInfo struct {
|
|
|
|
Name string
|
|
|
|
Flags []string
|
|
|
|
ReadOnly bool
|
|
|
|
|
|
|
|
// 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
|
2020-02-15 14:14:43 +01:00
|
|
|
|
|
|
|
// set to true if the value counts are accurate
|
|
|
|
AccurateCounts bool
|
2019-07-08 04:43:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// A MessageInfo holds information about the structure of a message
|
|
|
|
type MessageInfo struct {
|
2019-07-08 04:43:58 +02:00
|
|
|
BodyStructure *BodyStructure
|
|
|
|
Envelope *Envelope
|
|
|
|
Flags []Flag
|
2019-12-23 12:51:58 +01:00
|
|
|
Labels []string
|
2019-07-08 04:43:56 +02:00
|
|
|
InternalDate time.Time
|
|
|
|
RFC822Headers *mail.Header
|
|
|
|
Size uint32
|
|
|
|
Uid uint32
|
|
|
|
}
|
|
|
|
|
|
|
|
// A MessageBodyPart can be displayed in the message viewer
|
|
|
|
type MessageBodyPart struct {
|
|
|
|
Reader io.Reader
|
|
|
|
Uid uint32
|
|
|
|
}
|
|
|
|
|
|
|
|
// A FullMessage is the entire message
|
|
|
|
type FullMessage struct {
|
|
|
|
Reader io.Reader
|
|
|
|
Uid uint32
|
|
|
|
}
|
2019-07-08 04:43:58 +02:00
|
|
|
|
|
|
|
type BodyStructure struct {
|
|
|
|
MIMEType string
|
|
|
|
MIMESubType string
|
|
|
|
Params map[string]string
|
|
|
|
Description string
|
|
|
|
Encoding string
|
|
|
|
Parts []*BodyStructure
|
|
|
|
Disposition string
|
|
|
|
DispositionParams map[string]string
|
|
|
|
}
|
|
|
|
|
2020-01-04 21:13:50 +01:00
|
|
|
//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)
|
|
|
|
}
|
|
|
|
|
2019-07-08 04:43:58 +02:00
|
|
|
type Envelope struct {
|
|
|
|
Date time.Time
|
|
|
|
Subject string
|
|
|
|
From []*Address
|
|
|
|
ReplyTo []*Address
|
|
|
|
To []*Address
|
|
|
|
Cc []*Address
|
|
|
|
Bcc []*Address
|
|
|
|
MessageId string
|
|
|
|
}
|
|
|
|
|
2020-08-19 12:01:45 +02:00
|
|
|
type Address gomail.Address
|
2019-07-08 04:43:58 +02:00
|
|
|
|
|
|
|
var atom *regexp.Regexp = regexp.MustCompile("^[a-z0-9!#$%7'*+-/=?^_`{}|~ ]+$")
|
|
|
|
|
2020-08-19 12:01:45 +02:00
|
|
|
// String formats the address. If the address's name
|
|
|
|
// contains non-ASCII characters it will be quoted but not encoded.
|
|
|
|
// Meant for display purposes to the humans, not for sending over the wire.
|
|
|
|
func (a *Address) Format() string {
|
2019-07-08 04:43:58 +02:00
|
|
|
if a.Name != "" {
|
|
|
|
if atom.MatchString(a.Name) {
|
2020-08-19 12:01:45 +02:00
|
|
|
return fmt.Sprintf("%s <%s>", a.Name, a.Address)
|
2019-07-08 04:43:58 +02:00
|
|
|
} else {
|
2020-08-19 12:01:45 +02:00
|
|
|
return fmt.Sprintf("\"%s\" <%s>",
|
|
|
|
strings.ReplaceAll(a.Name, "\"", "'"), a.Address)
|
2019-07-08 04:43:58 +02:00
|
|
|
}
|
|
|
|
} else {
|
2020-08-19 12:01:45 +02:00
|
|
|
return fmt.Sprintf("<%s>", a.Address)
|
2019-07-08 04:43:58 +02:00
|
|
|
}
|
|
|
|
}
|
2020-01-08 21:44:14 +01:00
|
|
|
|
|
|
|
// OriginalMail is helper struct used for reply/forward
|
|
|
|
type OriginalMail struct {
|
2020-06-26 09:25:53 +02:00
|
|
|
Date time.Time
|
2020-01-08 21:44:16 +01:00
|
|
|
From string
|
|
|
|
Text string
|
|
|
|
MIMEType string
|
2020-01-08 21:44:14 +01:00
|
|
|
}
|