Documentation ¶
Overview ¶
Package msgs provides the Brief system's mail message abstraction including the Docket together with mail message parsing.
Index ¶
- Constants
- Variables
- func ModTime(docket Docket, date time.Time) time.Time
- func ParseAddressList(text string) ([]*netmail.Address, error)
- func ParseDate(text string) (time.Time, error)
- func SetMailbox(setdocketer interface{ ... }, t time.Time, mid MessageId, mailbox string) error
- func SetMailboxRubbish(setdocketer interface{ ... }, t time.Time, mid MessageId) error
- type Docket
- type Docketed
- type Message
- type MessageId
- func (mid MessageId) Chevroned() *netmail.Address
- func (mid MessageId) Equal(other MessageId) bool
- func (mid MessageId) IsZero() bool
- func (mid MessageId) MarshalBinary() ([]byte, error)
- func (mid MessageId) MarshalText() ([]byte, error)
- func (mid MessageId) RandomAlternate() (MessageId, error)
- func (mid MessageId) Unchevroned() string
- func (mid *MessageId) UnmarshalBinary(text []byte) error
- func (mid *MessageId) UnmarshalText(text []byte) error
- type ParsedMessage
- type ParsedPart
- type TKV
- type Undocketed
Constants ¶
const DocketTimeLayout = time.RFC3339Nano
Variables ¶
Functions ¶
func ParseAddressList ¶
does no partial parse: err==nil iff []*netmail.Address!=nil
func ParseDate ¶
Expands (i.e. allows incompetent syntactical constructs found in the wild) on netmail.ParseDate (which claims to implement RFC 5322).
func SetMailbox ¶
Types ¶
type Docket ¶
type Docket []TKV
Docket represents brief's locally-added message metadata. Unlike e.g. a raw RFC 822 mail's "Date:" header field, all information inside the Docket can be trusted. Using sacks/fssack, the docket is stored *alongside the original message*. To accurately transmit the above described trust, "X-Brief" and "X-Brief-*" headers are sanitised (see WithDocket). A docket is appended to, meaning with increasing index, (generally) tkv.T increases.
func (Docket) Get ¶
Get gets the most recent k-keyed docket entry.
func (Docket) IsHot ¶
TODO "hot" is a bad name?
INBOX/ or OUTBOX/ residents are hot. Messages of indeterminate transfer-status are hot.
type Docketed ¶
type Docketed []byte
func WithDocket ¶
func WithDocket(docket Docket, undocketed Undocketed) Docketed
type Message ¶
type Message struct { // Id MUST correspond to the unique "Message-Id" field in Message. // Cf. Message.Contract Id MessageId // Docket holds is the Message's brief-specific associated metadata. This // is distinc from Message. Docket Docket // Message is this Message's byte-for-byte exact raw message, not including // the docket. This raw message may also contain un-sanitised, potentially // not trustworthy "X-Brief" and "X-Brief-*" headers. // Since a syntactically valid RFC 822 message contains a CRLF separating a // potentially empty header from a potentially empty body, a valid // Message's Message always has positive len. Message []byte }
Message represents a Sack's atomic unit of content. A Message's fields MUST NOT be retained by a Sack to ensure value semantics.
Often, *Message is used. Nonetheless, read-only value semantics should always be applied.
func (*Message) Contract ¶
Contract asserts internal type consistencies.
Most notably, Message.Id is asserted to be the unique Message-Id found in Message.Message.
func (*Message) Date ¶
When the message contains a unique, parsable "Date:" header, said field is parsed and returned. A message's "Date:" may be parsed to the zero time value. Else, the zero time value is returned. RFC 822 does not force messages to employ the "Date:" field, though the vast majority probably does.
func (*Message) MarshalBinary ¶
MarshalBinary builds a docketed message form. All information is preserved.
type MessageId ¶
type MessageId struct {
// contains filtered or unexported fields
}
A Message-Id's e-mail-address-like appearance should not tempt to think its display name had any meaning. A Message-Id does not have a display name. MessageId.raw is in net/mail's eyes (*"net/mail".Address).Address.
MessageId has fully non-retaining value semantics and thus does not implement a "Clone()" method.
func ParseMessageId ¶
ParseMessageId parses a Message-Id field's body.
func UniqueMessageId ¶
func UniqueMessageId(undocketed Undocketed) (MessageId, int64, int64, error)
UniqueMessageId extracts the unique (!) Message-Id.
func (MessageId) Equal ¶
TODO think about domain case lowering?
func (MessageId) MarshalBinary ¶
interface { encoding.BinaryMarshaler; encoding.BinaryUnmarshaler } are required by sacks/fssacks.Cache.
func (MessageId) MarshalText ¶
The chevrons are not an inherent part of the Message-Id but merely a common framing.
func (MessageId) Unchevroned ¶
TODO Is mid.raw guaranteed to be Stringer-suitable?
type ParsedMessage ¶
type ParsedMessage struct { MessageId MessageId // may be .Zero() Date time.Time // may be .Zero() Subject string XMailer string // includes other headers: "X-Mailer", "X-Mailman-Version", "X-Originating-Client", "X-Powered-By", etc. (TODO create a fieldnames category) From []*netmail.Address // RFC 5322 3.6.2. allows multiple "From:" Sender **netmail.Address // RFC 5322 3.6.2. forbids multiple "Sender:" ReplyTo []*netmail.Address // RFC 5322 3.6.2. allows multiple "Reply-To:" InReplyTo []MessageId // RFC 5322 3.6.4. allows multiple "In-Reply-To:" References []MessageId // RFC 5322 3.6.4. allows multiple "References:" DispositionNotificationTo []MessageId // TODO verify multiple values are permissible To []*netmail.Address Cc []*netmail.Address Bcc []*netmail.Address // syntactically invalid fields (i.e. unknown "charset") Undecodable []mailx.RawField // semantically invalid fields Unparseable []mailx.Field // ignored fields due to fieldnames.Category.Boring Boring []mailx.Field // extra, non-interpreted, non-boring fields Extra []mailx.Field // [2023-12-11, jfrech] TODO "Body" is not really a good name for the // parsed Body (for MIME multipart, the RFC 822 body is only an encoding). Body []*ParsedPart }
*ParsedMessage holds a semantically broken open RFC 822/newer standards/MIME internet e-mail message. It is designed to admit its inabilities for ambiguous or incorrectly formatted values.
(*ParsedMessage).UnmarshalText: When a unique field is present more than once, all are put into Unparseable and the corresponding ParsedMessage struct field is set to its zero value.
*netmail.Address is never nil. **netmail.Address is used to fake a Maybe monad and thus may be nil.
TODO use for "brief compose"
func ParseMessage
deprecated
func ParseMessage(rawmessage []byte) (*ParsedMessage, error)
Deprecated: TODO remove Convenience wrapper for (*ParsedMessage).UnmarshalText.
func (*ParsedMessage) UnmarshalText ¶
func (parsedmessage *ParsedMessage) UnmarshalText(rawmessage []byte) error
A RFC 822-style message. No concepts like "Brief dockets" exist here.
type ParsedPart ¶
type TKV ¶
NOTE: Contrary to RFC-822-style message headers, dockets have in-built versioning requiring the most recent entry to be interpreted as the sole value: where some mail headers (e.g. "From: x\r\nFrom: y\r\n") can be catenated (e.g. "From: x, y\r\n"), docket values MUST NOT be catenated.