HIGH fixes: - Access Token now used as PGP Passphrase: replaced session.AccessToken with session.MailPassphrase for all PGP operations - Session stored encrypted in keyring and file (was plain JSON) - Added checkAuthenticated() helper with IsAuthenticated() guard MEDIUM fixes: - Added MailPassphrase field to Session, collected during login - Added email validation in LoginInteractive - Added keyring cleanup on Logout - Implemented RefreshToken with actual API call LOW fixes: - Added mutex to PGPKeyRing for thread safety - Added ZeroPrivateKeyData() for memory cleanup - Use net/mail.ParseAddress for proper recipient parsing - Renamed internal/mail import to internalmail to avoid conflict
143 lines
3.6 KiB
Go
143 lines
3.6 KiB
Go
package mail
|
|
|
|
import "time"
|
|
|
|
type Folder int
|
|
|
|
const (
|
|
FolderInbox Folder = 0
|
|
FolderSent Folder = 3
|
|
FolderDraft Folder = 2
|
|
FolderTrash Folder = 4
|
|
FolderSpam Folder = 5
|
|
)
|
|
|
|
const (
|
|
MessageTypeRegular = "0"
|
|
MessageTypeDraft = "2"
|
|
)
|
|
|
|
func (f Folder) Name() string {
|
|
names := map[Folder]string{
|
|
FolderInbox: "Inbox",
|
|
FolderSent: "Sent",
|
|
FolderDraft: "Drafts",
|
|
FolderTrash: "Trash",
|
|
FolderSpam: "Spam",
|
|
}
|
|
if name, ok := names[f]; ok {
|
|
return name
|
|
}
|
|
return "Unknown"
|
|
}
|
|
|
|
type Message struct {
|
|
MessageID string `json:"MessageID"`
|
|
ConversationID string `json:"ConversationID"`
|
|
CreatedAt time.Time `json:"-"`
|
|
Created int64 `json:"Created"`
|
|
UpdatedAt time.Time `json:"-"`
|
|
Updated int64 `json:"Updated"`
|
|
Type int `json:"Type"`
|
|
Starred bool `json:"Starred"`
|
|
Read bool `json:"Read"`
|
|
Category int `json:"Category"`
|
|
Sender Recipient `json:"Sender"`
|
|
Recipients []Recipient `json:"Recipients"`
|
|
Subject string `json:"Subject"`
|
|
Body string `json:"Body"`
|
|
BodyEnc string `json:"BodyEnc,omitempty"`
|
|
Attachments []Attachment `json:"Attachments,omitempty"`
|
|
MimeMessageID string `json:"MimeMessageID,omitempty"`
|
|
InReplyTo string `json:"InReplyTo,omitempty"`
|
|
}
|
|
|
|
func (m *Message) Folder() Folder {
|
|
if m.Type == int(FolderDraft) {
|
|
return FolderDraft
|
|
}
|
|
if m.Type == int(FolderSent) {
|
|
return FolderSent
|
|
}
|
|
return FolderInbox
|
|
}
|
|
|
|
type Recipient struct {
|
|
Name string `json:"Name"`
|
|
Address string `json:"Address"`
|
|
Label int `json:"Label"`
|
|
AddressID string `json:"AddressID,omitempty"`
|
|
KeyID string `json:"KeyID,omitempty"`
|
|
Fingerprint string `json:"Fingerprint,omitempty"`
|
|
}
|
|
|
|
func (r Recipient) DisplayName() string {
|
|
if r.Name != "" {
|
|
return r.Name + " <" + r.Address + ">"
|
|
}
|
|
return r.Address
|
|
}
|
|
|
|
type Attachment struct {
|
|
AttachmentID string `json:"AttachmentID"`
|
|
Name string `json:"Name"`
|
|
ContentType string `json:"ContentType"`
|
|
Size int `json:"Size"`
|
|
DataEnc string `json:"DataEnc,omitempty"`
|
|
Keys []AttachmentKey `json:"Keys,omitempty"`
|
|
}
|
|
|
|
type AttachmentKey struct {
|
|
DataEnc string `json:"DataEnc"`
|
|
}
|
|
|
|
type Draft struct {
|
|
MessageID string `json:"MessageID"`
|
|
To []Recipient `json:"To"`
|
|
CC []Recipient `json:"CC,omitempty"`
|
|
BCC []Recipient `json:"BCC,omitempty"`
|
|
Subject string `json:"Subject"`
|
|
Body string `json:"Body"`
|
|
BodyEnc string `json:"BodyEnc,omitempty"`
|
|
Attachments []Attachment `json:"Attachments,omitempty"`
|
|
}
|
|
|
|
type ListMessagesRequest struct {
|
|
Folder Folder `json:"-"`
|
|
Page int `json:"Page"`
|
|
PageSize int `json:"PageSize"`
|
|
Passphrase string `json:"Passphrase"`
|
|
Starred *bool `json:"Starred,omitempty"`
|
|
Read *bool `json:"Read,omitempty"`
|
|
Since int64 `json:"Since,omitempty"`
|
|
}
|
|
|
|
type ListMessagesResponse struct {
|
|
Total int `json:"Total"`
|
|
Messages []Message `json:"Messages"`
|
|
}
|
|
|
|
type SendRequest struct {
|
|
To []Recipient `json:"To"`
|
|
CC []Recipient `json:"CC,omitempty"`
|
|
BCC []Recipient `json:"BCC,omitempty"`
|
|
Subject string `json:"Subject"`
|
|
Body string `json:"Body"`
|
|
HTML bool `json:"HTML,omitempty"`
|
|
ReplyTo []Recipient `json:"ReplyTo,omitempty"`
|
|
Attachments []Attachment `json:"Attachments,omitempty"`
|
|
Passphrase string `json:"Passphrase"`
|
|
}
|
|
|
|
type SearchRequest struct {
|
|
Query string `json:"Query"`
|
|
Page int `json:"Page"`
|
|
PageSize int `json:"PageSize"`
|
|
Passphrase string `json:"Passphrase"`
|
|
}
|
|
|
|
type SearchResponse struct {
|
|
Total int `json:"Total"`
|
|
Messages []Message `json:"Messages"`
|
|
}
|