Documentation
¶
Overview ¶
Package mailbox is the plain mailbox side of lfr: addresses that receive and send like any mail account, with aliases, catch-alls, plus-addressing, forwarding, folders, flags and full-text search.
Index ¶
- Constants
- Variables
- func BlobRefs(ctx context.Context, db interface{ ... }, hash string) (int, error)
- func ValidFolder(f string) (string, bool)
- type Delivery
- type Mailbox
- type Message
- type Outbox
- type Query
- type ReplyRequest
- type SendRequest
- type Service
- func (s *Service) Add(ctx context.Context, email, name string) (*Mailbox, error)
- func (s *Service) AddAlias(ctx context.Context, alias, target string) error
- func (s *Service) ByID(ctx context.Context, id int64) (*Mailbox, error)
- func (s *Service) Counts(ctx context.Context, mailboxID int64) (map[string]int, error)
- func (s *Service) Delete(ctx context.Context, id int64, purge bool) error
- func (s *Service) Deliver(ctx context.Context, d Delivery) (int64, error)
- func (s *Service) Flag(ctx context.Context, id int64, flag string, on bool) error
- func (s *Service) ForwardItem(ctx context.Context, mb *Mailbox, raw []byte, p *msg.Parsed) (outbound.Item, error)
- func (s *Service) Get(ctx context.Context, email string) (*Mailbox, error)
- func (s *Service) List(ctx context.Context, domain string) ([]*Mailbox, error)
- func (s *Service) Messages(ctx context.Context, q Query) ([]Summary, error)
- func (s *Service) Move(ctx context.Context, id int64, folder string) (string, error)
- func (s *Service) Purge(ctx context.Context, folder string, age time.Duration) (int, error)
- func (s *Service) Raw(ctx context.Context, id int64) ([]byte, error)
- func (s *Service) Read(ctx context.Context, id int64, seen bool) (*Message, error)
- func (s *Service) Remove(ctx context.Context, email string) error
- func (s *Service) RemoveAlias(ctx context.Context, alias string) error
- func (s *Service) Rename(ctx context.Context, from, to string) (*Mailbox, error)
- func (s *Service) Reply(ctx context.Context, out Outbox, id int64, r ReplyRequest) (int64, error)
- func (s *Service) Resolve(ctx context.Context, rcpt string) (int64, bool, error)
- func (s *Service) Send(ctx context.Context, out Outbox, req SendRequest) (int64, error)
- func (s *Service) SetCatchall(ctx context.Context, domain, target string) error
- func (s *Service) SetTrained(ctx context.Context, id int64, label string) error
- func (s *Service) Update(ctx context.Context, email string, name, forward *string) (*Mailbox, error)
- type Summary
Constants ¶
const MaxMessage = 20 << 20
MaxMessage is the largest message lfr sends: Outlook's limit, below Gmail's 25 MB, counted after attachments are encoded.
Variables ¶
var ErrExists = errors.New("already exists")
ErrExists reports a duplicate address.
var Folders = []string{"inbox", "junk", "archive", "sent", "trash"}
Folders a message can be in.
Functions ¶
func BlobRefs ¶
func BlobRefs(ctx context.Context, db interface { QueryRowContext(context.Context, string, ...any) *sql.Row }, hash string) (int, error)
BlobRefs counts what still points at a stored blob: messages, sends not done yet, issue images. A blob is removed only when this says 0 without an error; a failed query must never read as "unused".
func ValidFolder ¶
ValidFolder reports whether f is a folder name, accepting "spam" for junk.
Types ¶
type Delivery ¶
type Delivery struct {
MailboxID int64
Folder string
Raw []byte
Parsed *msg.Parsed // parsed when nil
Spam float64
Verdict string
Features string
Seen bool
}
Delivery is one message to store.
type Mailbox ¶
type Mailbox struct {
ID int64 `json:"id"`
DomainID int64 `json:"-"`
Address string `json:"address"`
Name string `json:"name,omitempty"`
Forward string `json:"forward,omitempty"`
Aliases []string `json:"aliases,omitempty"`
Catchall bool `json:"catchall,omitempty"`
Unread int `json:"unread"`
Total int `json:"total"`
Created time.Time `json:"created"`
}
Mailbox is one address that receives mail.
type Message ¶
type Message struct {
Summary
ReplyTo string `json:"reply_to,omitempty"`
Text string `json:"text"`
HTML string `json:"html,omitempty"`
Files []msg.Attachment `json:"attachments_list,omitempty"`
Verdict json.RawMessage `json:"verdict,omitempty"` // authentication and spam details
// SenderCheck says in one line whether the From address is proven: a
// "Rechnung" from an unproven sender is the classic phishing mail.
SenderCheck string `json:"sender_check,omitempty"`
// Events summarizes calendar invitations: what, when, where.
Events []string `json:"events,omitempty"`
Trained string `json:"trained,omitempty"`
Blob string `json:"-"`
Features string `json:"-"`
InReplyTo string `json:"in_reply_to,omitempty"`
References []string `json:"references,omitempty"`
}
Message is a message as read.
type Outbox ¶
type Outbox interface {
EnqueueTx(ctx context.Context, tx outbound.Execer, items ...outbound.Item) (int, error)
Wake()
}
Outbox queues messages for delivery.
type Query ¶
type Query struct {
Mailbox string // address; empty for every mailbox
Folder string // empty: inbox
Unread bool
Thread string
Search string // full-text query
Limit int
Before int64 // only messages with a smaller ID, for paging
}
Query selects messages to list.
type ReplyRequest ¶
type ReplyRequest struct {
Text string `json:"text"`
HTML string `json:"html,omitempty"`
All bool `json:"all"`
Quote bool `json:"quote"`
Files []msg.File `json:"-"`
}
ReplyRequest answers a stored message.
type SendRequest ¶
type SendRequest struct {
From string `json:"from"` // a mailbox address (or one of its aliases)
To []string `json:"to"`
Cc []string `json:"cc,omitempty"`
Bcc []string `json:"bcc,omitempty"`
ReplyTo string `json:"reply_to,omitempty"`
Subject string `json:"subject"`
Text string `json:"text"`
HTML string `json:"html,omitempty"`
Files []msg.File `json:"-"`
InReplyTo string `json:"-"`
References []string `json:"-"`
}
SendRequest is a message to send from a mailbox.
type Service ¶
Service is the mailbox store.
func (*Service) AddAlias ¶
AddAlias makes alias deliver into the mailbox target; both share a domain.
func (*Service) Delete ¶
Delete moves a message to trash, or removes it for good when purge is set or it already is in trash.
func (*Service) ForwardItem ¶
func (s *Service) ForwardItem(ctx context.Context, mb *Mailbox, raw []byte, p *msg.Parsed) (outbound.Item, error)
ForwardItem prepares a delivered message for the mailbox's forwarding address. The copy is sent as the mailbox (so SPF, DKIM and DMARC pass for lfr's domain) with the original sender as Reply-To.
func (*Service) Purge ¶
Purge removes messages that sat in folder longer than age, returning how many.
func (*Service) RemoveAlias ¶
RemoveAlias deletes an alias.
func (*Service) Resolve ¶
Resolve finds the mailbox mail to rcpt belongs in: the exact address, an alias, the address without its +tag, then the domain's catch-all.
func (*Service) Send ¶
Send composes a message, files it in the sender's sent folder and queues it for every recipient. It returns the ID of the sent-folder copy.
func (*Service) SetCatchall ¶
SetCatchall routes unknown addresses of domain to target; empty target turns it off.
func (*Service) SetTrained ¶
SetTrained records how a message was used to train the spam filter.
type Summary ¶
type Summary struct {
ID int64 `json:"id"`
Mailbox string `json:"mailbox"`
Folder string `json:"folder"`
From string `json:"from"`
FromName string `json:"from_name,omitempty"`
To []string `json:"to,omitempty"`
Cc []string `json:"cc,omitempty"`
Subject string `json:"subject"`
Snippet string `json:"snippet"`
Date time.Time `json:"date"`
Received time.Time `json:"received"`
Seen bool `json:"seen"`
Flagged bool `json:"flagged"`
Answered bool `json:"answered"`
Attachments int `json:"attachments"`
Spam float64 `json:"spam"`
Thread string `json:"thread"`
Size int `json:"size"`
MessageID string `json:"message_id,omitempty"`
}
Summary is a message as listed.