Files
pop/internal/mail/types.go
Paperclip 0684e726bb FRE-681: Fix security review findings (3 HIGH, 3 MEDIUM, 2 LOW)
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
2026-04-28 12:40:09 -04:00

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"`
}