Documentation
¶
Overview ¶
Package mailparser is a fast and robust e-mail parsing library.
Index ¶
- Variables
- func AddHTMLToken(result *strings.Builder, token []byte, addSpace bool)
- func Base64Decode(bytes []byte) ([]byte, bool)
- func Base64DecodeStream(stream iter.Seq[byte], streamLen int, stopChar byte) ([]byte, bool)
- func DecodeHex(src []byte) (bool, []byte)
- func HTMLToText(input string) string
- func ParseAddressDetailPart(addr string) (string, bool)
- func ParseAddressDomain(addr string) (string, bool)
- func ParseAddressLocalPart(addr string) (string, bool)
- func ParseAddressUserPart(addr string) (string, bool)
- func PreviewHTML(html string, maxLen int) string
- func PreviewText(text string, maxLen int) string
- func QuotedPrintableDecode(bytes []byte) ([]byte, bool)
- func QuotedPrintableDecodeChar(hex1, hex2 byte) (byte, bool)
- func TextToHTML(input string) string
- func ThreadName(text string) string
- func TrimTrailingFwd(text string) string
- func TruncateHTML(html string, maxLen int) string
- func TruncateText(text string, maxLen int) string
- type Addr
- type Address
- func (a *Address) All() iter.Seq[*Addr]
- func (a *Address) AsGroup() ([]Group, bool)
- func (a *Address) AsList() ([]Addr, bool)
- func (a *Address) Contains(addr string) bool
- func (a *Address) First() *Addr
- func (a *Address) IsGroup() bool
- func (a *Address) Last() *Addr
- func (a Address) MarshalJSON() ([]byte, error)
- func (a *Address) ToGroups() []Group
- func (a *Address) ToList() []Addr
- func (a *Address) UnmarshalJSON(data []byte) error
- type Attribute
- type ContentType
- func (c *ContentType) Attribute(name string) (string, bool)
- func (c *ContentType) HasAttribute(name string) bool
- func (c *ContentType) IsAttachment() bool
- func (c *ContentType) IsInline() bool
- func (c ContentType) MarshalJSON() ([]byte, error)
- func (c *ContentType) RemoveAttribute(name string) (string, bool)
- func (c *ContentType) UnmarshalJSON(data []byte) error
- type DateTime
- func (d DateTime) Compare(other DateTime) int
- func (d DateTime) DayOfWeek() uint8
- func (d DateTime) IsValid() bool
- func (d DateTime) JulianDay() int64
- func (d DateTime) MarshalJSON() ([]byte, error)
- func (d DateTime) String() string
- func (d DateTime) ToRFC822() string
- func (d DateTime) ToRFC3339() string
- func (d DateTime) ToTimestamp() int64
- func (d DateTime) ToTimestampLocal() int64
- func (d DateTime) ToTimezone(tz int64) DateTime
- func (d *DateTime) UnmarshalJSON(data []byte) error
- type DecodeFnc
- type DecodeWordFnc
- type DecoderFnc
- type Encoding
- type Greeting
- type Group
- type HdrParseFunc
- type Header
- type HeaderForm
- type HeaderID
- type HeaderName
- func (h HeaderName) Equal(o HeaderName) bool
- func (h HeaderName) ID() HeaderID
- func (h HeaderName) IsMimeHeader() bool
- func (h HeaderName) IsOther() bool
- func (h HeaderName) Len() int
- func (h HeaderName) MapKey() HeaderName
- func (h HeaderName) MarshalJSON() ([]byte, error)
- func (h HeaderName) Other() string
- func (h HeaderName) StaticString() string
- func (h HeaderName) String() string
- func (h *HeaderName) UnmarshalJSON(data []byte) error
- type HeaderSlice
- type HeaderValue
- func (v *HeaderValue) AsAddress() *Address
- func (v *HeaderValue) AsContentType() *ContentType
- func (v *HeaderValue) AsDateTime() *DateTime
- func (v *HeaderValue) AsReceived() *Received
- func (v *HeaderValue) AsText() (string, bool)
- func (v *HeaderValue) AsTextList() ([]string, bool)
- func (v *HeaderValue) IsEmpty() bool
- func (v *HeaderValue) Kind() HeaderValueKind
- func (v *HeaderValue) Len() int
- func (v HeaderValue) MarshalJSON() ([]byte, error)
- func (v *HeaderValue) ToText() (string, bool)
- func (v *HeaderValue) UnmarshalJSON(data []byte) error
- func (v *HeaderValue) UnwrapAddress() Address
- func (v *HeaderValue) UnwrapContentType() ContentType
- func (v *HeaderValue) UnwrapDateTime() DateTime
- func (v *HeaderValue) UnwrapReceived() Received
- func (v *HeaderValue) UnwrapText() string
- func (v *HeaderValue) UnwrapTextList() []string
- type HeaderValueKind
- type Host
- type Message
- func (m *Message) AllAttachments() iter.Seq[*MessagePart]
- func (m *Message) AllBcc() iter.Seq[*Address]
- func (m *Message) AllCc() iter.Seq[*Address]
- func (m *Message) AllTo() iter.Seq[*Address]
- func (m *Message) Attachment(pos int) *MessagePart
- func (m *Message) AttachmentCount() int
- func (m *Message) AttachmentName() (string, bool)
- func (m *Message) Bcc() *Address
- func (m *Message) BodyHTML(pos int) (string, bool)
- func (m *Message) BodyPreview(previewLen int) (string, bool)
- func (m *Message) BodyText(pos int) (string, bool)
- func (m *Message) Cc() *Address
- func (m *Message) Comments() *HeaderValue
- func (m *Message) ContentDescription() (string, bool)
- func (m *Message) ContentDisposition() *ContentType
- func (m *Message) ContentID() (string, bool)
- func (m *Message) ContentLanguage() *HeaderValue
- func (m *Message) ContentLocation() (string, bool)
- func (m *Message) ContentTransferEncoding() (string, bool)
- func (m *Message) ContentType() *ContentType
- func (m *Message) Date() *DateTime
- func (m *Message) From() *Address
- func (m *Message) HTMLBodies() iter.Seq[*MessagePart]
- func (m *Message) HTMLBodyCount() int
- func (m *Message) HTMLPart(pos int) *MessagePart
- func (m *Message) Header(name HeaderName) *HeaderValue
- func (m *Message) HeaderAs(name HeaderName, form HeaderForm) []HeaderValue
- func (m *Message) HeaderRaw(name HeaderName) (string, bool)
- func (m *Message) HeaderValues(name HeaderName) iter.Seq[*HeaderValue]
- func (m *Message) Headers() []Header
- func (m *Message) HeadersRaw() iter.Seq2[string, string]
- func (m *Message) InReplyTo() *HeaderValue
- func (m *Message) IsContentType(ctype, subtype string) bool
- func (m *Message) IsEmpty() bool
- func (m *Message) Keywords() *HeaderValue
- func (m *Message) ListArchive() *HeaderValue
- func (m *Message) ListHelp() *HeaderValue
- func (m *Message) ListID() *HeaderValue
- func (m *Message) ListOwner() *HeaderValue
- func (m *Message) ListPost() *HeaderValue
- func (m *Message) ListSubscribe() *HeaderValue
- func (m *Message) ListUnsubscribe() *HeaderValue
- func (m Message) MarshalJSON() ([]byte, error)
- func (m *Message) MessageID() (string, bool)
- func (m *Message) MimeVersion() *HeaderValue
- func (m *Message) Part(pos int) *MessagePart
- func (m *Message) Received() *Received
- func (m *Message) ReceivedAll() iter.Seq[*Received]
- func (m *Message) References() *HeaderValue
- func (m *Message) RemoveHeader(name HeaderName) (HeaderValue, bool)
- func (m *Message) ReplyTo() *Address
- func (m *Message) ResentBcc() *Address
- func (m *Message) ResentCc() *Address
- func (m *Message) ResentDate() *HeaderValue
- func (m *Message) ResentFrom() *Address
- func (m *Message) ResentMessageID() *HeaderValue
- func (m *Message) ResentSender() *Address
- func (m *Message) ResentTo() *Address
- func (m *Message) ReturnAddress() (string, bool)
- func (m *Message) ReturnPath() *HeaderValue
- func (m *Message) RootPart() *MessagePart
- func (m *Message) RootRawMessage() []byte
- func (m *Message) Sender() *Address
- func (m *Message) Subject() (string, bool)
- func (m *Message) TextBodies() iter.Seq[*MessagePart]
- func (m *Message) TextBodyCount() int
- func (m *Message) TextPart(pos int) *MessagePart
- func (m *Message) ThreadName() (string, bool)
- func (m *Message) To() *Address
- func (m *Message) UnmarshalJSON(data []byte) error
- type MessageParser
- func (p *MessageParser) DefaultHeaderIgnore() *MessageParser
- func (p *MessageParser) DefaultHeaderRaw() *MessageParser
- func (p *MessageParser) DefaultHeaderText() *MessageParser
- func (p *MessageParser) HeaderAddress(header HeaderName) *MessageParser
- func (p *MessageParser) HeaderCommaSeparated(header HeaderName) *MessageParser
- func (p *MessageParser) HeaderContentType(header HeaderName) *MessageParser
- func (p *MessageParser) HeaderDate(header HeaderName) *MessageParser
- func (p *MessageParser) HeaderID(header HeaderName) *MessageParser
- func (p *MessageParser) HeaderRaw(header HeaderName) *MessageParser
- func (p *MessageParser) HeaderReceived(header HeaderName) *MessageParser
- func (p *MessageParser) HeaderText(header HeaderName) *MessageParser
- func (p *MessageParser) IgnoreHeader(header HeaderName) *MessageParser
- func (p *MessageParser) Parse(rawMessage []byte) *Message
- func (p *MessageParser) ParseHeaders(rawMessage []byte) *Message
- func (p *MessageParser) WithAddressHeaders() *MessageParser
- func (p *MessageParser) WithDateHeaders() *MessageParser
- func (p *MessageParser) WithMessageIDs() *MessageParser
- func (p *MessageParser) WithMimeHeaders() *MessageParser
- func (p *MessageParser) WithMinimalHeaders() *MessageParser
- func (p *MessageParser) WithoutHeader(header HeaderName) *MessageParser
- type MessagePart
- func (p *MessagePart) AttachmentName() (string, bool)
- func (p *MessagePart) ContentDescription() (string, bool)
- func (p *MessagePart) ContentDisposition() *ContentType
- func (p *MessagePart) ContentID() (string, bool)
- func (p *MessagePart) ContentLanguage() *HeaderValue
- func (p *MessagePart) ContentLocation() (string, bool)
- func (p *MessagePart) ContentTransferEncoding() (string, bool)
- func (p *MessagePart) ContentType() *ContentType
- func (p *MessagePart) Contents() []byte
- func (p *MessagePart) IsBinary() bool
- func (p *MessagePart) IsContentType(ctype, subtype string) bool
- func (p *MessagePart) IsEmpty() bool
- func (p *MessagePart) IsMessage() bool
- func (p *MessagePart) IsMultipart() bool
- func (p *MessagePart) IsText() bool
- func (p *MessagePart) IsTextHTML() bool
- func (p *MessagePart) Len() int
- func (p MessagePart) MarshalJSON() ([]byte, error)
- func (p *MessagePart) Message() *Message
- func (p *MessagePart) RawBodyOffset() int
- func (p *MessagePart) RawEndOffset() int
- func (p *MessagePart) RawHeaderOffset() int
- func (p *MessagePart) RawLen() int
- func (p *MessagePart) String() string
- func (p *MessagePart) SubParts() ([]int, bool)
- func (p *MessagePart) TextContents() (string, bool)
- func (p *MessagePart) UnmarshalJSON(data []byte) error
- type MessageStream
- func (s *MessageStream) Bytes(start, end int) []byte
- func (s *MessageStream) Checkpoint()
- func (s *MessageStream) DecodeBase64MIME(boundary []byte) (int, []byte)
- func (s *MessageStream) DecodeBase64Word() ([]byte, bool)
- func (s *MessageStream) DecodeQuotedPrintableMIME(boundary []byte) (int, []byte)
- func (s *MessageStream) DecodeQuotedPrintableWord() ([]byte, bool)
- func (s *MessageStream) DecodeRFC2047() (string, bool)
- func (s *MessageStream) IsEOF() bool
- func (s *MessageStream) IsMultipartEnd() bool
- func (s *MessageStream) Len() int
- func (s *MessageStream) MIMEPart(boundary []byte) (int, []byte)
- func (s *MessageStream) Next() (byte, bool)
- func (s *MessageStream) NextIsSpace() bool
- func (s *MessageStream) Offset() int
- func (s *MessageStream) ParseAddress() HeaderValue
- func (s *MessageStream) ParseAndIgnore()
- func (s *MessageStream) ParseCommaSeparated() HeaderValue
- func (s *MessageStream) ParseContentType() HeaderValue
- func (s *MessageStream) ParseDate() HeaderValue
- func (s *MessageStream) ParseHeaders(conf *MessageParser, headers *[]Header) bool
- func (s *MessageStream) ParseID() HeaderValue
- func (s *MessageStream) ParseRaw() HeaderValue
- func (s *MessageStream) ParseReceived() HeaderValue
- func (s *MessageStream) ParseUnstructured() HeaderValue
- func (s *MessageStream) Peek() (byte, bool)
- func (s *MessageStream) PeekBytes(n int) []byte
- func (s *MessageStream) PeekChar(ch byte) bool
- func (s *MessageStream) PeekNextIsSpace() bool
- func (s *MessageStream) ReadHeaderName() (HeaderName, bool)
- func (s *MessageStream) Remaining() int
- func (s *MessageStream) Reset()
- func (s *MessageStream) Restore()
- func (s *MessageStream) SeekEnd()
- func (s *MessageStream) SeekNextPart(boundary []byte) bool
- func (s *MessageStream) SeekNextPartOffset(boundary []byte) (offset int, ok bool)
- func (s *MessageStream) SeekPartEnd(boundary []byte) (int, bool)
- func (s *MessageStream) SkipBytes(n int)
- func (s *MessageStream) SkipCRLF()
- func (s *MessageStream) TryNextIsSpace() bool
- func (s *MessageStream) TrySkip(bytes []byte) bool
- func (s *MessageStream) TrySkipChar(ch byte) bool
- type MimeHeaders
- type PartKind
- type PartType
- func (p *PartType) Binary() []byte
- func (p *PartType) Kind() PartKind
- func (p *PartType) Len() int
- func (p PartType) MarshalJSON() ([]byte, error)
- func (p *PartType) Message() *Message
- func (p *PartType) SubParts() []int
- func (p *PartType) Text() string
- func (p *PartType) UnmarshalJSON(data []byte) error
- type Protocol
- type Received
- type TLSVersion
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( HeaderSubject = HeaderName{/* contains filtered or unexported fields */} HeaderFrom = HeaderName{/* contains filtered or unexported fields */} HeaderTo = HeaderName{/* contains filtered or unexported fields */} HeaderCc = HeaderName{/* contains filtered or unexported fields */} HeaderDate = HeaderName{/* contains filtered or unexported fields */} HeaderBcc = HeaderName{/* contains filtered or unexported fields */} HeaderReplyTo = HeaderName{/* contains filtered or unexported fields */} HeaderSender = HeaderName{/* contains filtered or unexported fields */} HeaderComments = HeaderName{/* contains filtered or unexported fields */} HeaderInReplyTo = HeaderName{/* contains filtered or unexported fields */} HeaderKeywords = HeaderName{/* contains filtered or unexported fields */} HeaderReceived = HeaderName{/* contains filtered or unexported fields */} HeaderMessageID = HeaderName{/* contains filtered or unexported fields */} HeaderReferences = HeaderName{/* contains filtered or unexported fields */} HeaderReturnPath = HeaderName{/* contains filtered or unexported fields */} HeaderMimeVersion = HeaderName{/* contains filtered or unexported fields */} HeaderContentDescription = HeaderName{/* contains filtered or unexported fields */} HeaderContentID = HeaderName{/* contains filtered or unexported fields */} HeaderContentLanguage = HeaderName{/* contains filtered or unexported fields */} HeaderContentLocation = HeaderName{/* contains filtered or unexported fields */} HeaderContentTransferEncoding = HeaderName{/* contains filtered or unexported fields */} HeaderContentType = HeaderName{/* contains filtered or unexported fields */} HeaderContentDisposition = HeaderName{/* contains filtered or unexported fields */} HeaderResentTo = HeaderName{/* contains filtered or unexported fields */} HeaderResentFrom = HeaderName{/* contains filtered or unexported fields */} HeaderResentBcc = HeaderName{/* contains filtered or unexported fields */} HeaderResentCc = HeaderName{/* contains filtered or unexported fields */} HeaderResentSender = HeaderName{/* contains filtered or unexported fields */} HeaderResentDate = HeaderName{/* contains filtered or unexported fields */} HeaderResentMessageID = HeaderName{/* contains filtered or unexported fields */} HeaderListArchive = HeaderName{/* contains filtered or unexported fields */} HeaderListHelp = HeaderName{/* contains filtered or unexported fields */} HeaderListID = HeaderName{/* contains filtered or unexported fields */} HeaderListOwner = HeaderName{/* contains filtered or unexported fields */} HeaderListPost = HeaderName{/* contains filtered or unexported fields */} HeaderListSubscribe = HeaderName{/* contains filtered or unexported fields */} HeaderListUnsubscribe = HeaderName{/* contains filtered or unexported fields */} HeaderArcAuthenticationResults = HeaderName{/* contains filtered or unexported fields */} HeaderArcMessageSignature = HeaderName{/* contains filtered or unexported fields */} HeaderArcSeal = HeaderName{/* contains filtered or unexported fields */} HeaderDkimSignature = HeaderName{/* contains filtered or unexported fields */} HeaderDkim2Signature = HeaderName{/* contains filtered or unexported fields */} HeaderMessageInstance = HeaderName{/* contains filtered or unexported fields */} )
Known header names.
Functions ¶
func AddHTMLToken ¶
AddHTMLToken appends token to result, optionally preceded by a space. A token of the form "&name;", "&#nnn;" or "&#xhh;" is decoded as an HTML entity; unknown or malformed entities are appended verbatim.
func Base64Decode ¶
Base64Decode decodes a base64 encoded value, ignoring ASCII whitespace. It reports false on invalid input.
func Base64DecodeStream ¶
Base64DecodeStream decodes a base64 encoded value from a byte sequence, stopping successfully when stopChar is found outside of the base64 alphabet.
func DecodeHex ¶
DecodeHex decodes a %XX percent-encoded byte string (RFC2231 extended parameter values), reporting success and the decoded bytes.
func HTMLToText ¶
HTMLToText extracts the readable text of an HTML document: tags, comments and head/style/script/template contents are dropped, entities are decoded, whitespace runs collapse to a single space, and <br> and closing </p> tags become newlines.
func ParseAddressDetailPart ¶
ParseAddressDetailPart returns the text between the last '+' before the '@' of an e-mail address and the '@' itself (possibly empty), reporting false when there is no such '+'.
func ParseAddressDomain ¶
ParseAddressDomain returns the text after the first '@' of an e-mail address, reporting false when either side of the '@' is empty.
func ParseAddressLocalPart ¶
ParseAddressLocalPart returns the text before the first '@' of an e-mail address, reporting false when the address has no non-empty local part followed by a non-empty remainder.
func ParseAddressUserPart ¶
ParseAddressUserPart returns the text before the first '+' of an e-mail address when that '+' precedes the '@', and otherwise the local part.
func PreviewHTML ¶
PreviewHTML converts HTML to text and truncates it to at most maxLen bytes, appending "..." when maxLen > 6.
func PreviewText ¶
PreviewText truncates text at a UTF-8 character boundary so the result is at most maxLen bytes, appending "..." when maxLen > 6 (the dots count toward the limit).
func QuotedPrintableDecode ¶
QuotedPrintableDecode decodes a quoted-printable encoded value, reporting false on invalid input.
func QuotedPrintableDecodeChar ¶
QuotedPrintableDecodeChar decodes a single =XX escape from its two hex digit characters, reporting false when either digit is invalid.
func TextToHTML ¶
TextToHTML wraps plain text in a minimal HTML document, converting newlines to <br/> and escaping '<'.
func ThreadName ¶
ThreadName returns the base thread name of a Subject value: it strips reply/forward prefixes ("re:", "fwd[5]:", localized variants), leading mailing-list "[...]" blobs, "[fwd: ...]" wrappers and trailing "(fwd)" suffixes, returning a substring of text.
func TrimTrailingFwd ¶
TrimTrailingFwd trims leading/trailing whitespace and any number of trailing "(fwd)"-style groups from text, returning a substring.
It scans in reverse. The whitespace arm's continue skips the textStart update, which is how leading trim happens, and a stripped group re-arms trimEnd.
func TruncateHTML ¶
TruncateHTML truncates HTML markup to at most maxLen bytes, appending "..." when maxLen > 6. The cut never lands inside a tag or comment: when it would, the result is rolled back to the end of the last complete tag (or to just before an unfinished one).
func TruncateText ¶
TruncateText truncates text to at most maxLen bytes at a UTF-8 character boundary. It is an alias of PreviewText.
Types ¶
type Addr ¶
type Addr struct {
// Name is the address display name including comments; "" when absent.
Name string
// Address is an e-mail address (RFC5322/RFC2369) or URL (RFC2369);
// "" when absent.
Address string
}
Addr is a single RFC5322 or RFC2369 internet address.
Both fields are plain strings and "" means absent, the shape used by net/mail.Address: callers read a.Name and a.Address directly, with no nil check and no dereference. Absent and present-but-empty are therefore one state, not two. The wire form maps "" to null and back, so a JSON round trip is stable; the one input class that told the two apart in the Rust original is recorded in DEVIATIONS.md 11.
func NewAddr ¶
NewAddr returns an Addr with the given display name and address. An empty string means that field is absent.
func (Addr) MarshalJSON ¶
MarshalJSON writes the wire form, encoding an absent name or address as null.
func (*Addr) UnmarshalJSON ¶
UnmarshalJSON reads the wire form, decoding null as "".
type Address ¶
type Address struct {
// contains filtered or unexported fields
}
Address is an RFC5322 address header value: either a flat address list or a list of named groups.
func AddressGroups ¶
AddressGroups returns an Address holding grouped addresses.
func AddressList ¶
AddressList returns an Address holding a flat list of addresses.
func (*Address) All ¶
All iterates over every address: the list elements, or all groups' addresses flattened in order.
func (*Address) AsGroup ¶
AsGroup returns the groups; ok is false when the address holds a flat list.
func (*Address) AsList ¶
AsList returns the flat list of addresses; ok is false when the address holds groups.
func (*Address) Contains ¶
Contains reports whether any address field equals addr ASCII-case-insensitively. Display names are ignored, and an Addr with no Address never matches.
func (*Address) First ¶
First returns the first address in the list, or the first address across the groups (empty groups are skipped).
func (*Address) Last ¶
Last returns the last address in the list, or the last address across the groups (empty groups are skipped).
func (Address) MarshalJSON ¶
MarshalJSON serializes the externally tagged Address variants: {"List": [...]} or {"Group": [...]}.
func (*Address) ToGroups ¶
ToGroups converts the address into groups. A flat list becomes one singleton Group PER address, each with an empty name, not a single group holding all of them.
func (*Address) ToList ¶
ToList converts the address into a flat list of Addr, flattening all groups' addresses in order.
func (*Address) UnmarshalJSON ¶
UnmarshalJSON decodes the externally tagged Address variants.
type Attribute ¶
Attribute is a single Content-Type/Content-Disposition attribute.
func (Attribute) MarshalJSON ¶
MarshalJSON writes the wire form.
func (*Attribute) UnmarshalJSON ¶
UnmarshalJSON reads the wire form. Both shapes are accepted: the map {"name":..,"value":..} and the pair ["name","value"], which is what the content_type.json fixture uses.
type ContentType ¶
type ContentType struct {
Type string
Subtype *string // nil when absent
// Attributes is nil when the header has no attributes; it serializes to
// JSON null.
Attributes []Attribute
}
ContentType is an RFC2047 Content-Type or RFC2183 Content-Disposition header value.
func (*ContentType) Attribute ¶
func (c *ContentType) Attribute(name string) (string, bool)
Attribute returns the value of the first attribute with the given name. The match is case-SENSITIVE: the parser already lowercases attribute names.
func (*ContentType) HasAttribute ¶
func (c *ContentType) HasAttribute(name string) bool
HasAttribute reports whether an attribute with the given name is present (case-sensitive).
func (*ContentType) IsAttachment ¶
func (c *ContentType) IsAttachment() bool
IsAttachment reports whether the Content-Disposition type is "attachment", ASCII-case-insensitively.
func (*ContentType) IsInline ¶
func (c *ContentType) IsInline() bool
IsInline reports whether the Content-Disposition type is "inline", ASCII-case-insensitively.
func (ContentType) MarshalJSON ¶
func (c ContentType) MarshalJSON() ([]byte, error)
MarshalJSON writes the wire form.
func (*ContentType) RemoveAttribute ¶
func (c *ContentType) RemoveAttribute(name string) (string, bool)
RemoveAttribute removes the first attribute with the given name (case-sensitive) and returns its value. The last attribute moves into the freed slot, so order is not preserved.
func (*ContentType) UnmarshalJSON ¶
func (c *ContentType) UnmarshalJSON(data []byte) error
UnmarshalJSON reads the wire form.
type DateTime ¶
type DateTime struct {
Year uint16
Month uint8
Day uint8
Hour uint8
Minute uint8
Second uint8
TZBeforeGMT bool
TZHour uint8
TZMinute uint8
}
DateTime is an RFC5322 date and time. Malformed input is preserved verbatim, so fields may hold out-of-range values (e.g. Second == 232) and the narrow unsigned widths wrap on overflow.
func DateTimeFromTimestamp ¶
DateTimeFromTimestamp builds a DateTime from a Unix timestamp. The result is always UTC: TZBeforeGMT false, zero offset.
func ParseRFC822 ¶
ParseRFC822 parses an RFC822 date, or returns nil if it does not parse.
func ParseRFC3339 ¶
ParseRFC3339 parses an RFC3339 date, or returns nil if it does not parse.
func (DateTime) Compare ¶
Compare returns -1, 0 or 1 as d is before, equal to, or after other by timestamp.
func (DateTime) MarshalJSON ¶
MarshalJSON writes the wire form.
func (DateTime) ToRFC3339 ¶
ToRFC3339 returns an RFC3339 representation of the parsed RFC5322 datetime field.
func (DateTime) ToTimestamp ¶
ToTimestamp returns the number of seconds since 1970-01-01T00:00:00Z (Unix epoch).
func (DateTime) ToTimestampLocal ¶
ToTimestampLocal returns the number of seconds since 1970-01-01T00:00:00Z (Unix epoch) in local time.
func (DateTime) ToTimezone ¶
ToTimezone converts the DateTime to the given timezone (signed seconds offset from GMT).
func (*DateTime) UnmarshalJSON ¶
UnmarshalJSON reads the wire form.
type DecodeFnc ¶
type DecodeFnc func(stream *MessageStream, boundary []byte) (int, []byte)
DecodeFnc is a MIME body decoder: it decodes the stream while scanning for the given multipart boundary and returns the offset where the decoded body ends (math.MaxInt when a non-empty boundary was not found) together with the decoded bytes.
type DecodeWordFnc ¶
type DecodeWordFnc func(stream *MessageStream) ([]byte, bool)
DecodeWordFnc is an RFC2047 encoded-word decoder: it decodes the stream up to the closing "?=" sequence and reports whether the word was valid.
type DecoderFnc ¶
DecoderFnc decodes bytes in a legacy character set into a UTF-8 string.
func CharsetDecoder ¶
func CharsetDecoder(charset []byte) (DecoderFnc, bool)
CharsetDecoder returns the decoder function for a character set name. Names match ASCII case-insensitively with '-' treated as '_', and only the first 45 bytes are significant.
type Encoding ¶
type Encoding uint8
Encoding is a MIME part transfer encoding.
func EncodingFrom ¶
EncodingFrom converts a raw byte: 1 and 2 map to their encodings, anything else to EncodingNone.
func (Encoding) MarshalJSON ¶
MarshalJSON writes the encoding as its name string. MessagePart.Encoding is skipped, so this only matters when the type is used standalone.
func (*Encoding) UnmarshalJSON ¶
UnmarshalJSON reads the wire form. Unknown names error loudly.
type Greeting ¶
type Greeting uint8
Greeting is the SMTP greeting command recorded in a Received header.
func (Greeting) MarshalJSON ¶
MarshalJSON serializes the bare variant identifier string.
func (*Greeting) UnmarshalJSON ¶
UnmarshalJSON decodes the bare variant identifier string.
type Group ¶
type Group struct {
// Name is the group display name; "" when absent.
Name string
// Addresses are the members of the group.
Addresses []Addr
}
Group is an RFC5322 address group.
A Group is always held by value - no exported signature in this package returns a *Group - so callers never nil-check a Group itself. An unnamed group is one with Name == "", which is what "To: a@b.com;" and Address.ToGroups on a flat list produce.
func NewGroup ¶
NewGroup returns a Group with the given display name and addresses. An empty name means an unnamed group.
func (Group) MarshalJSON ¶
MarshalJSON writes the wire form, encoding an unnamed group as null.
func (*Group) UnmarshalJSON ¶
UnmarshalJSON reads the wire form, decoding null as "".
type HdrParseFunc ¶
type HdrParseFunc func(*MessageStream) HeaderValue
HdrParseFunc parses one header value from the stream, leaving it positioned after the field's terminating newline.
type Header ¶
type Header struct {
Name HeaderName
Value HeaderValue
// OffsetField is the offset of the header name in the raw message;
// OffsetStart/OffsetEnd delimit the raw value.
OffsetField int
OffsetStart int
OffsetEnd int
}
Header is a single message header field.
func (Header) MarshalJSON ¶
MarshalJSON writes the wire form.
func (*Header) UnmarshalJSON ¶
UnmarshalJSON reads the wire form.
type HeaderForm ¶
type HeaderForm uint8
HeaderForm selects how HeaderAs re-parses a raw header value.
const ( // HeaderFormRaw yields the raw UTF-8 text, whitespace-trimmed. HeaderFormRaw HeaderForm = iota // HeaderFormText re-parses as an unstructured text header. HeaderFormText // HeaderFormAddresses re-parses as an address header. HeaderFormAddresses // HeaderFormGroupedAddresses re-parses as an address header. Identical // to HeaderFormAddresses at this layer. HeaderFormGroupedAddresses // HeaderFormMessageIDs re-parses as a Message-ID/References header. HeaderFormMessageIDs // HeaderFormDate re-parses as an RFC5322 date header. HeaderFormDate // HeaderFormURLs re-parses as a list of URLs. It routes to the address // parser: RFC2369 List-* URLs parse as addresses. HeaderFormURLs )
type HeaderID ¶
type HeaderID uint8
HeaderID identifies a known header name.
const ( HeaderIDSubject HeaderID = 0 HeaderIDFrom HeaderID = 1 HeaderIDTo HeaderID = 2 HeaderIDCc HeaderID = 3 HeaderIDDate HeaderID = 4 HeaderIDBcc HeaderID = 5 HeaderIDReplyTo HeaderID = 6 HeaderIDSender HeaderID = 7 HeaderIDComments HeaderID = 8 HeaderIDInReplyTo HeaderID = 9 HeaderIDKeywords HeaderID = 10 HeaderIDReceived HeaderID = 11 HeaderIDMessageID HeaderID = 12 HeaderIDReferences HeaderID = 13 HeaderIDReturnPath HeaderID = 14 HeaderIDMimeVersion HeaderID = 15 HeaderIDContentDescription HeaderID = 16 HeaderIDContentID HeaderID = 17 HeaderIDContentLanguage HeaderID = 18 HeaderIDContentLocation HeaderID = 19 HeaderIDContentTransferEncoding HeaderID = 20 HeaderIDContentType HeaderID = 21 HeaderIDContentDisposition HeaderID = 22 HeaderIDResentTo HeaderID = 23 HeaderIDResentFrom HeaderID = 24 HeaderIDResentBcc HeaderID = 25 HeaderIDResentCc HeaderID = 26 HeaderIDResentSender HeaderID = 27 HeaderIDResentDate HeaderID = 28 HeaderIDResentMessageID HeaderID = 29 HeaderIDListArchive HeaderID = 30 HeaderIDListHelp HeaderID = 31 HeaderIDListID HeaderID = 32 HeaderIDListOwner HeaderID = 33 HeaderIDListPost HeaderID = 34 HeaderIDListSubscribe HeaderID = 35 HeaderIDListUnsubscribe HeaderID = 36 HeaderIDOther HeaderID = 37 HeaderIDArcAuthenticationResults HeaderID = 38 HeaderIDArcMessageSignature HeaderID = 39 HeaderIDArcSeal HeaderID = 40 HeaderIDDkimSignature HeaderID = 41 HeaderIDDkim2Signature HeaderID = 42 HeaderIDMessageInstance HeaderID = 43 )
type HeaderName ¶
type HeaderName struct {
// contains filtered or unexported fields
}
HeaderName is a header field name: either one of the known names or an arbitrary ("Other") name. Other names compare ASCII case-insensitively.
func HeaderNameFrom ¶
func HeaderNameFrom(s string) HeaderName
HeaderNameFrom converts a string into a HeaderName. Known names match ASCII-case-insensitively; any other valid name is kept verbatim as an Other name. Invalid input (empty, or a character outside [A-Za-z0-9_-]) gives Other("").
func HeaderNameFromID ¶
func HeaderNameFromID(id HeaderID) HeaderName
HeaderNameFromID maps an id back to a name. Ids with no reverse mapping (HeaderIDOther, Dkim2Signature, MessageInstance, out of range) yield HeaderOther("").
func HeaderOther ¶
func HeaderOther(name string) HeaderName
HeaderOther returns an arbitrary header name.
func ParseHeaderName ¶
func ParseHeaderName(data string) (HeaderName, bool)
ParseHeaderName parses and validates a standalone header-name string, returning the matched well-known HeaderName or an Other name holding the input unchanged. It reports false when the input is empty or contains a character outside [A-Za-z0-9_-].
func (HeaderName) Equal ¶
func (h HeaderName) Equal(o HeaderName) bool
Equal compares two header names. Known names match only the same known name; Other names compare ASCII-case-insensitively. A known name never equals an Other name even when the text matches: Other("From") != From.
func (HeaderName) ID ¶
func (h HeaderName) ID() HeaderID
ID returns the header's numeric id (HeaderIDOther for arbitrary names).
func (HeaderName) IsMimeHeader ¶
func (h HeaderName) IsMimeHeader() bool
IsMimeHeader reports whether this is one of the Content-* MIME headers.
func (HeaderName) IsOther ¶
func (h HeaderName) IsOther() bool
IsOther reports whether this is an arbitrary (non-registered) header name.
func (HeaderName) Len ¶
func (h HeaderName) Len() int
Len returns the byte length of the display name.
func (HeaderName) MapKey ¶
func (h HeaderName) MapKey() HeaderName
MapKey normalizes the name for use as a map key: Other names are ASCII-lowercased so lookups agree with Equal.
func (HeaderName) MarshalJSON ¶
func (h HeaderName) MarshalJSON() ([]byte, error)
MarshalJSON writes known names as their snake_case string and Other names as {"other": name}, case preserved.
func (HeaderName) Other ¶
func (h HeaderName) Other() string
Other returns the arbitrary header name ("" for known names).
func (HeaderName) StaticString ¶
func (h HeaderName) StaticString() string
StaticString is like String but returns "" for Other names.
func (HeaderName) String ¶
func (h HeaderName) String() string
String returns the display name: the canonical spelling for known headers ("Message-ID", "MIME-Version", ...), or the Other name unchanged.
func (*HeaderName) UnmarshalJSON ¶
func (h *HeaderName) UnmarshalJSON(data []byte) error
UnmarshalJSON decodes either form of HeaderName.
type HeaderSlice ¶
type HeaderSlice []Header
HeaderSlice adds lookups to a []Header such as MessagePart.Headers. It scans in reverse, so a repeated header resolves to its LAST occurrence.
func (HeaderSlice) Header ¶
func (hs HeaderSlice) Header(name HeaderName) *Header
Header returns the last header matching name, or nil. Matching uses HeaderName.Equal (ASCII-case-insensitive for Other names).
func (HeaderSlice) HeaderValue ¶
func (hs HeaderSlice) HeaderValue(name HeaderName) *HeaderValue
HeaderValue returns the value of the last header matching name, or nil.
type HeaderValue ¶
type HeaderValue struct {
// contains filtered or unexported fields
}
HeaderValue is a parsed header value. The zero value is Empty.
func AddressValue ¶
func AddressValue(a Address) HeaderValue
AddressValue returns an Address header value.
func ContentTypeValue ¶
func ContentTypeValue(ct ContentType) HeaderValue
ContentTypeValue returns a ContentType header value.
func DateTimeValue ¶
func DateTimeValue(dt DateTime) HeaderValue
DateTimeValue returns a DateTime header value.
func ReceivedValue ¶
func ReceivedValue(r Received) HeaderValue
ReceivedValue returns a Received header value.
func TextListValue ¶
func TextListValue(l []string) HeaderValue
TextListValue returns a TextList header value.
func (*HeaderValue) AsAddress ¶
func (v *HeaderValue) AsAddress() *Address
AsAddress returns the Address value, or nil for any other variant.
func (*HeaderValue) AsContentType ¶
func (v *HeaderValue) AsContentType() *ContentType
AsContentType returns the ContentType value, or nil for any other variant.
func (*HeaderValue) AsDateTime ¶
func (v *HeaderValue) AsDateTime() *DateTime
AsDateTime returns the DateTime value, or nil for any other variant.
func (*HeaderValue) AsReceived ¶
func (v *HeaderValue) AsReceived() *Received
AsReceived returns the Received value, or nil for any other variant.
func (*HeaderValue) AsText ¶
func (v *HeaderValue) AsText() (string, bool)
AsText returns the text of a Text value, or the LAST element of a TextList. Last, not first: the header getters rely on it.
func (*HeaderValue) AsTextList ¶
func (v *HeaderValue) AsTextList() ([]string, bool)
AsTextList returns the TextList value, promoting a Text value to a single-element list.
func (*HeaderValue) IsEmpty ¶
func (v *HeaderValue) IsEmpty() bool
IsEmpty reports whether the value is the Empty variant.
func (*HeaderValue) Kind ¶
func (v *HeaderValue) Kind() HeaderValueKind
Kind returns the value variant.
func (*HeaderValue) Len ¶
func (v *HeaderValue) Len() int
Len is a heuristic content length. DateTime is always 24 and Received always 1. Address sums the name and address bytes of every flattened Addr; group display names do not count.
func (HeaderValue) MarshalJSON ¶
func (v HeaderValue) MarshalJSON() ([]byte, error)
MarshalJSON serializes the externally tagged HeaderValue variants; the unit variant Empty is the bare string "Empty".
func (*HeaderValue) ToText ¶
func (v *HeaderValue) ToText() (string, bool)
ToText returns the text of a Text value only. Unlike AsText, a TextList yields false.
func (*HeaderValue) UnmarshalJSON ¶
func (v *HeaderValue) UnmarshalJSON(data []byte) error
UnmarshalJSON decodes the externally tagged HeaderValue variants.
func (*HeaderValue) UnwrapAddress ¶
func (v *HeaderValue) UnwrapAddress() Address
UnwrapAddress returns the Address value, or panics.
func (*HeaderValue) UnwrapContentType ¶
func (v *HeaderValue) UnwrapContentType() ContentType
UnwrapContentType returns the ContentType value, or panics.
func (*HeaderValue) UnwrapDateTime ¶
func (v *HeaderValue) UnwrapDateTime() DateTime
UnwrapDateTime returns the DateTime value, or panics.
func (*HeaderValue) UnwrapReceived ¶
func (v *HeaderValue) UnwrapReceived() Received
UnwrapReceived returns the Received value, or panics.
func (*HeaderValue) UnwrapText ¶
func (v *HeaderValue) UnwrapText() string
UnwrapText returns the Text value, or panics.
func (*HeaderValue) UnwrapTextList ¶
func (v *HeaderValue) UnwrapTextList() []string
UnwrapTextList returns the TextList value, promoting a Text value to a single-element list, or panics.
type HeaderValueKind ¶
type HeaderValueKind uint8
HeaderValueKind discriminates the variants of a HeaderValue.
const ( // HeaderValueKindEmpty is the zero value. HeaderValueKindEmpty HeaderValueKind = iota HeaderValueKindText HeaderValueKindTextList HeaderValueKindAddress HeaderValueKindDateTime HeaderValueKindContentType HeaderValueKindReceived )
type Host ¶
type Host struct {
// contains filtered or unexported fields
}
Host is a hostname or IP address in a Received header.
func (Host) MarshalJSON ¶
MarshalJSON serializes the externally tagged Host variants: {"Name": "host"} or {"IpAddr": "1.2.3.4"}.
func (*Host) UnmarshalJSON ¶
UnmarshalJSON decodes the externally tagged Host variants.
type Message ¶
type Message struct {
// HTMLBody, TextBody and Attachments hold indexes into Parts.
HTMLBody []int
TextBody []int
Attachments []int
Parts []MessagePart
// RawMessage is the raw message bytes this Message was parsed from.
// Parts reference it by offset. It is not serialized to JSON.
RawMessage []byte
}
Message is a parsed RFC5322/RFC822 message.
Example (Attachments) ¶
ExampleMessage_attachments walks every attachment, descending into nested messages. It prints names rather than writing files, to keep the example free of file-system side effects.
package main
import (
"fmt"
"github.com/yokohola/mailparser"
)
func main() {
input := []byte(`From: Art Vandelay <art@vandelay.com> (Vandelay Industries)
To: "Colleagues": "James Smythe" <james@vandelay.com>; Friends:
jane@example.com, =?UTF-8?Q?John_Sm=C3=AEth?= <john@example.com>;
Date: Sat, 20 Nov 2021 14:22:01 -0800
Subject: Why not both importing AND exporting? =?utf-8?b?4pi6?=
Content-Type: multipart/mixed; boundary="festivus";
--festivus
Content-Type: text/html; charset="us-ascii"
Content-Transfer-Encoding: base64
PGh0bWw+PHA+SSB3YXMgdGhpbmtpbmcgYWJvdXQgcXVpdHRpbmcgdGhlICZsZHF1bztle
HBvcnRpbmcmcmRxdW87IHRvIGZvY3VzIGp1c3Qgb24gdGhlICZsZHF1bztpbXBvcnRpbm
cmcmRxdW87LDwvcD48cD5idXQgdGhlbiBJIHRob3VnaHQsIHdoeSBub3QgZG8gYm90aD8
gJiN4MjYzQTs8L3A+PC9odG1sPg==
--festivus
Content-Type: message/rfc822; name="Exporting my book about coffee tables.eml"
Content-Disposition: inline; filename="Exporting my book about coffee tables.eml"
Content-Transfer-Encoding: 7bit
From: "Cosmo Kramer" <kramer@kramerica.com>
Subject: Exporting my book about coffee tables
Content-Type: multipart/mixed; boundary="giddyup";
--giddyup
Content-Type: text/plain; charset="utf-16"
Content-Transfer-Encoding: quoted-printable
=FF=FE=0C!5=D8"=DD5=D8)=DD5=D8-=DD =005=D8*=DD5=D8"=DD =005=D8"=
=DD5=D85=DD5=D8-=DD5=D8,=DD5=D8/=DD5=D81=DD =005=D8*=DD5=D86=DD =
=005=D8=1F=DD5=D8,=DD5=D8,=DD5=D8(=DD =005=D8-=DD5=D8)=DD5=D8"=
=DD5=D8=1E=DD5=D80=DD5=D8"=DD!=00
--giddyup
Content-Type: image/gif; name*1="about "; name*0="Book ";
name*2*=utf-8''%e2%98%95 tables.gif
Content-Transfer-Encoding: Base64
Content-Disposition: attachment
R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
--giddyup--
--festivus--
`)
printAttachments(mailparser.NewMessageParser().Parse(input))
}
// printAttachments prints the name of every attachment it finds.
func printAttachments(message *mailparser.Message) {
for attachment := range message.AllAttachments() {
if !attachment.IsMessage() {
name, ok := attachment.AttachmentName()
if !ok {
name = "Untitled"
}
fmt.Println(name)
} else {
printAttachments(attachment.Message())
}
}
}
Output:
func (*Message) AllAttachments ¶
func (m *Message) AllAttachments() iter.Seq[*MessagePart]
AllAttachments iterates over the attachment parts, stopping early on a bad part id. Named All* because Attachments is already the index field.
func (*Message) AllBcc ¶
AllBcc iterates over all Bcc headers as Addresses in message order. RFC5322 section 4.5.3 allows the header to repeat.
func (*Message) AllCc ¶
AllCc iterates over all Cc headers as Addresses in message order. RFC5322 section 4.5.3 allows the header to repeat.
func (*Message) AllTo ¶
AllTo iterates over all To headers as Addresses in message order. RFC5322 section 4.5.3 allows the header to repeat.
func (*Message) Attachment ¶
func (m *Message) Attachment(pos int) *MessagePart
Attachment returns the pos-th attachment part, or nil.
func (*Message) AttachmentCount ¶
AttachmentCount returns the number of attachments.
func (*Message) AttachmentName ¶
AttachmentName returns the attachment file name, if any.
func (*Message) BodyHTML ¶
BodyHTML returns the pos-th HTML body part as text/html. An HTML part comes back as-is, a Text part is converted with TextToHTML, and any other part type yields false.
func (*Message) BodyPreview ¶
BodyPreview returns a preview of the message body of at most previewLen bytes. Text bodies take absolute priority: if TextBody is non-empty but its first part is unusable, the result is false without falling back to HTML.
func (*Message) BodyText ¶
BodyText returns the pos-th text body part as text/plain. A Text part comes back as-is, an HTML part is converted with HTMLToText, and any other part type yields false.
func (*Message) Comments ¶
func (m *Message) Comments() *HeaderValue
Comments returns the last Comments value, or Empty.
func (*Message) ContentDescription ¶
ContentDescription returns the root part's Content-Description field.
func (*Message) ContentDisposition ¶
func (m *Message) ContentDisposition() *ContentType
ContentDisposition returns the root part's Content-Disposition field.
func (*Message) ContentLanguage ¶
func (m *Message) ContentLanguage() *HeaderValue
ContentLanguage returns the root part's Content-Language value, or the Empty value (never nil).
func (*Message) ContentLocation ¶
ContentLocation returns the root part's Content-Location field.
func (*Message) ContentTransferEncoding ¶
ContentTransferEncoding returns the root part's Content-Transfer-Encoding field.
func (*Message) ContentType ¶
func (m *Message) ContentType() *ContentType
ContentType returns the root part's Content-Type field.
func (*Message) HTMLBodies ¶
func (m *Message) HTMLBodies() iter.Seq[*MessagePart]
HTMLBodies iterates over the HTML body parts.
func (*Message) HTMLBodyCount ¶
HTMLBodyCount returns the number of HTML body parts.
func (*Message) HTMLPart ¶
func (m *Message) HTMLPart(pos int) *MessagePart
HTMLPart returns the pos-th inline HTML body part, or nil.
func (*Message) Header ¶
func (m *Message) Header(name HeaderName) *HeaderValue
Header returns the value of the last header matching name, or nil.
func (*Message) HeaderAs ¶
func (m *Message) HeaderAs(name HeaderName, form HeaderForm) []HeaderValue
HeaderAs re-parses EVERY header matching name from its raw bytes according to form, in message order. A header whose offsets fall outside RawMessage contributes an Empty value, so there is always one entry per match.
func (*Message) HeaderRaw ¶
func (m *Message) HeaderRaw(name HeaderName) (string, bool)
HeaderRaw returns the raw text of the last header matching name. ok is false when the header is absent or its raw bytes are not valid UTF-8.
func (*Message) HeaderValues ¶
func (m *Message) HeaderValues(name HeaderName) iter.Seq[*HeaderValue]
HeaderValues iterates over the values of ALL headers matching name, in message order.
func (*Message) HeadersRaw ¶
HeadersRaw iterates over (display name, raw text) pairs for every header in message order. Headers whose raw bytes are not valid UTF-8 are silently skipped.
func (*Message) InReplyTo ¶
func (m *Message) InReplyTo() *HeaderValue
InReplyTo returns the last In-Reply-To value, or Empty.
func (*Message) IsContentType ¶
IsContentType reports whether the Content-Type matches type and subtype.
func (*Message) IsEmpty ¶
IsEmpty reports whether no header field was successfully parsed (the message has no parts).
func (*Message) Keywords ¶
func (m *Message) Keywords() *HeaderValue
Keywords returns the last Keywords value, or Empty.
func (*Message) ListArchive ¶
func (m *Message) ListArchive() *HeaderValue
ListArchive returns the last List-Archive value, or the Empty value (never nil).
func (*Message) ListHelp ¶
func (m *Message) ListHelp() *HeaderValue
ListHelp returns the last List-Help value, or Empty.
func (*Message) ListID ¶
func (m *Message) ListID() *HeaderValue
ListID returns the last List-ID value, or Empty.
func (*Message) ListOwner ¶
func (m *Message) ListOwner() *HeaderValue
ListOwner returns the last List-Owner value, or Empty.
func (*Message) ListPost ¶
func (m *Message) ListPost() *HeaderValue
ListPost returns the last List-Post value, or Empty.
func (*Message) ListSubscribe ¶
func (m *Message) ListSubscribe() *HeaderValue
ListSubscribe returns the last List-Subscribe value, or the Empty value (never nil).
func (*Message) ListUnsubscribe ¶
func (m *Message) ListUnsubscribe() *HeaderValue
ListUnsubscribe returns the last List-Unsubscribe value, or Empty.
func (Message) MarshalJSON ¶
MarshalJSON writes the wire form; RawMessage is never emitted.
func (*Message) MimeVersion ¶
func (m *Message) MimeVersion() *HeaderValue
MimeVersion returns the last MIME-Version value, or the Empty value (never nil).
func (*Message) Part ¶
func (m *Message) Part(pos int) *MessagePart
Part returns the message part at pos, or nil.
func (*Message) ReceivedAll ¶
ReceivedAll iterates over all Received headers in the order they appear in the message.
func (*Message) References ¶
func (m *Message) References() *HeaderValue
References returns the last References value, or Empty.
func (*Message) RemoveHeader ¶
func (m *Message) RemoveHeader(name HeaderName) (HeaderValue, bool)
RemoveHeader removes the FIRST header matching name and returns its value. The LAST header moves into the freed slot, so order is not preserved.
func (*Message) ResentDate ¶
func (m *Message) ResentDate() *HeaderValue
ResentDate returns the last Resent-Date value, or Empty.
func (*Message) ResentFrom ¶
ResentFrom returns the last Resent-From header as an Address.
func (*Message) ResentMessageID ¶
func (m *Message) ResentMessageID() *HeaderValue
ResentMessageID returns the last Resent-Message-ID value, or Empty.
func (*Message) ResentSender ¶
ResentSender returns the last Resent-Sender header as an Address.
func (*Message) ReturnAddress ¶
ReturnAddress returns the return address from Return-Path or From. A Text Return-Path wins. A TextList Return-Path yields its LAST element, or nothing at all if the list is empty; it does not fall through. Otherwise the first From address's Address field is used, and if that Addr has no address there is no further fallback.
func (*Message) ReturnPath ¶
func (m *Message) ReturnPath() *HeaderValue
ReturnPath returns the last Return-Path value, or Empty.
func (*Message) RootPart ¶
func (m *Message) RootPart() *MessagePart
RootPart returns the root message part.
func (*Message) RootRawMessage ¶
RootRawMessage returns RawMessage[OffsetHeader:OffsetEnd] of Parts[0], or nil when out of range. Not the RawMessage field, which is the whole input.
func (*Message) TextBodies ¶
func (m *Message) TextBodies() iter.Seq[*MessagePart]
TextBodies iterates over the text body parts.
func (*Message) TextBodyCount ¶
TextBodyCount returns the number of plain text body parts.
func (*Message) TextPart ¶
func (m *Message) TextPart(pos int) *MessagePart
TextPart returns the pos-th inline text body part, or nil.
func (*Message) ThreadName ¶
ThreadName returns the message thread name or "base subject" as defined in RFC5256 section 2.1; ok is false only when the message has no Subject.
func (*Message) UnmarshalJSON ¶
UnmarshalJSON reads the wire form. Missing keys take their zero value and RawMessage is left nil.
type MessageParser ¶
type MessageParser struct {
// contains filtered or unexported fields
}
MessageParser is a configurable RFC5322/RFC822 message parser.
With no custom header parsers registered, every IANA-registered header defined in HeaderName is parsed with its corresponding parser and other headers are parsed raw. Registering even one custom parser replaces that built-in dispatch entirely: headers are then looked up in the custom map, falling back to the default parser.
Example (Custom) ¶
ExampleMessageParser_custom builds parsers that handle only a chosen subset of headers.
package main
import (
"github.com/yokohola/mailparser"
)
func main() {
input := []byte(`From: Art Vandelay <art@vandelay.com> (Vandelay Industries)
To: "Colleagues": "James Smythe" <james@vandelay.com>; Friends:
jane@example.com, =?UTF-8?Q?John_Sm=C3=AEth?= <john@example.com>;
Date: Sat, 20 Nov 2021 14:22:01 -0800
Subject: Why not both importing AND exporting? =?utf-8?b?4pi6?=
Content-Type: multipart/mixed; boundary="festivus";
--festivus
Content-Type: text/html; charset="us-ascii"
Content-Transfer-Encoding: base64
PGh0bWw+PHA+SSB3YXMgdGhpbmtpbmcgYWJvdXQgcXVpdHRpbmcgdGhlICZsZHF1bztle
HBvcnRpbmcmcmRxdW87IHRvIGZvY3VzIGp1c3Qgb24gdGhlICZsZHF1bztpbXBvcnRpbm
cmcmRxdW87LDwvcD48cD5idXQgdGhlbiBJIHRob3VnaHQsIHdoeSBub3QgZG8gYm90aD8
gJiN4MjYzQTs8L3A+PC9odG1sPg==
--festivus
Content-Type: message/rfc822
From: "Cosmo Kramer" <kramer@kramerica.com>
Subject: Exporting my book about coffee tables
Content-Type: multipart/mixed; boundary="giddyup";
--giddyup
Content-Type: text/plain; charset="utf-16"
Content-Transfer-Encoding: quoted-printable
=FF=FE=0C!5=D8"=DD5=D8)=DD5=D8-=DD =005=D8*=DD5=D8"=DD =005=D8"=
=DD5=D85=DD5=D8-=DD5=D8,=DD5=D8/=DD5=D81=DD =005=D8*=DD5=D86=DD =
=005=D8=1F=DD5=D8,=DD5=D8,=DD5=D8(=DD =005=D8-=DD5=D8)=DD5=D8"=
=DD5=D8=1E=DD5=D80=DD5=D8"=DD!=00
--giddyup
Content-Type: image/gif; name*1="about "; name*0="Book ";
name*2*=utf-8''%e2%98%95 tables.gif
Content-Transfer-Encoding: Base64
Content-Disposition: attachment
R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
--giddyup--
--festivus--
`)
// Parse only the message headers
_ = mailparser.NewMessageParser().ParseHeaders(input).Headers()
// Parse only the message body, ignoring all headers (except MIME
// headers, which are required to parse the body)
_ = mailparser.NewMessageParser().
WithMimeHeaders().
DefaultHeaderIgnore().
Parse(input)
// Parse only To, From, Date, and Subject headers. All other headers
// are parsed as raw.
_ = mailparser.NewMessageParser().
WithMimeHeaders().
HeaderText(mailparser.HeaderSubject).
HeaderAddress(mailparser.HeaderFrom).
HeaderAddress(mailparser.HeaderTo).
HeaderDate(mailparser.HeaderDate).
DefaultHeaderRaw().
Parse(input)
}
Output:
func NewMessageParser ¶
func NewMessageParser() *MessageParser
NewMessageParser creates a message parser with the default settings:
- IANA-registered headers defined in HeaderName are parsed with their corresponding parser.
- Other headers (HeaderName Other) are parsed as raw.
func (*MessageParser) DefaultHeaderIgnore ¶
func (p *MessageParser) DefaultHeaderIgnore() *MessageParser
DefaultHeaderIgnore ignores and skips parsing all other headers.
func (*MessageParser) DefaultHeaderRaw ¶
func (p *MessageParser) DefaultHeaderRaw() *MessageParser
DefaultHeaderRaw parses all other headers as raw strings, no RFC 2047 decoding is done.
func (*MessageParser) DefaultHeaderText ¶
func (p *MessageParser) DefaultHeaderText() *MessageParser
DefaultHeaderText parses all other headers as text decoding RFC 2047 encoded words.
func (*MessageParser) HeaderAddress ¶
func (p *MessageParser) HeaderAddress(header HeaderName) *MessageParser
HeaderAddress parses a header as an address.
func (*MessageParser) HeaderCommaSeparated ¶
func (p *MessageParser) HeaderCommaSeparated(header HeaderName) *MessageParser
HeaderCommaSeparated parses a header as a comma-separated list of values.
func (*MessageParser) HeaderContentType ¶
func (p *MessageParser) HeaderContentType(header HeaderName) *MessageParser
HeaderContentType parses a header as a MIME Content-Type or Content-Disposition type.
func (*MessageParser) HeaderDate ¶
func (p *MessageParser) HeaderDate(header HeaderName) *MessageParser
HeaderDate parses a header as a RFC 5322 date.
func (*MessageParser) HeaderID ¶
func (p *MessageParser) HeaderID(header HeaderName) *MessageParser
HeaderID parses a header as an ID.
func (*MessageParser) HeaderRaw ¶
func (p *MessageParser) HeaderRaw(header HeaderName) *MessageParser
HeaderRaw parses a header as a raw string, no RFC 2047 decoding is done.
func (*MessageParser) HeaderReceived ¶
func (p *MessageParser) HeaderReceived(header HeaderName) *MessageParser
HeaderReceived parses a header as a received header.
func (*MessageParser) HeaderText ¶
func (p *MessageParser) HeaderText(header HeaderName) *MessageParser
HeaderText parses a header as text decoding RFC 2047 encoded words.
func (*MessageParser) IgnoreHeader ¶
func (p *MessageParser) IgnoreHeader(header HeaderName) *MessageParser
IgnoreHeader ignores and skips parsing a header. The header bytes are still consumed from the stream so subsequent offsets stay correct.
func (*MessageParser) Parse ¶
func (p *MessageParser) Parse(rawMessage []byte) *Message
Parse parses a byte slice containing the RFC5322 raw message and returns a Message.
This function never panics, a best-effort is made to parse the message and if no headers are found nil is returned.
Example ¶
ExampleMessageParser_Parse walks a parsed message's headers and bodies.
package main
import (
"encoding/json"
"fmt"
"github.com/yokohola/mailparser"
)
func main() {
input := []byte(`From: Art Vandelay <art@vandelay.com> (Vandelay Industries)
To: "Colleagues": "James Smythe" <james@vandelay.com>; Friends:
jane@example.com, =?UTF-8?Q?John_Sm=C3=AEth?= <john@example.com>;
Date: Sat, 20 Nov 2021 14:22:01 -0800
Subject: Why not both importing AND exporting? =?utf-8?b?4pi6?=
Content-Type: multipart/mixed; boundary="festivus";
--festivus
Content-Type: text/html; charset="us-ascii"
Content-Transfer-Encoding: base64
PGh0bWw+PHA+SSB3YXMgdGhpbmtpbmcgYWJvdXQgcXVpdHRpbmcgdGhlICZsZHF1bztle
HBvcnRpbmcmcmRxdW87IHRvIGZvY3VzIGp1c3Qgb24gdGhlICZsZHF1bztpbXBvcnRpbm
cmcmRxdW87LDwvcD48cD5idXQgdGhlbiBJIHRob3VnaHQsIHdoeSBub3QgZG8gYm90aD8
gJiN4MjYzQTs8L3A+PC9odG1sPg==
--festivus
Content-Type: message/rfc822
From: "Cosmo Kramer" <kramer@kramerica.com>
Subject: Exporting my book about coffee tables
Content-Type: multipart/mixed; boundary="giddyup";
--giddyup
Content-Type: text/plain; charset="utf-16"
Content-Transfer-Encoding: quoted-printable
=FF=FE=0C!5=D8"=DD5=D8)=DD5=D8-=DD =005=D8*=DD5=D8"=DD =005=D8"=
=DD5=D85=DD5=D8-=DD5=D8,=DD5=D8/=DD5=D81=DD =005=D8*=DD5=D86=DD =
=005=D8=1F=DD5=D8,=DD5=D8,=DD5=D8(=DD =005=D8-=DD5=D8)=DD5=D8"=
=DD5=D8=1E=DD5=D80=DD5=D8"=DD!=00
--giddyup
Content-Type: image/gif; name*1="about "; name*0="Book ";
name*2*=utf-8''%e2%98%95 tables.gif
Content-Transfer-Encoding: Base64
Content-Disposition: attachment
R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
--giddyup--
--festivus--
`)
message := mailparser.NewMessageParser().Parse(input)
// Parses addresses (including comments), lists and groups
from := message.From().First()
fmt.Printf("%s <%s>\n", from.Name, from.Address)
groups, _ := message.To().AsGroup()
for _, group := range groups {
for _, addr := range group.Addresses {
fmt.Printf("%s: %s\n", group.Name, addr.Address)
}
}
fmt.Println(message.Date().ToRFC3339())
// RFC2047 support for encoded text in message readers
subject, _ := message.Subject()
fmt.Println(subject)
// HTML and text body parts are returned conforming to RFC8621,
// Section 4.1.4
bodyHTML, _ := message.BodyHTML(0)
fmt.Println(bodyHTML)
// HTML parts are converted to plain text (and viceversa) when missing
bodyText, _ := message.BodyText(0)
fmt.Println(bodyText)
// Supports nested messages as well as multipart/digest
nestedMessage := message.Attachment(0).Message()
nestedSubject, _ := nestedMessage.Subject()
fmt.Println(nestedSubject)
// Handles UTF-* as well as many legacy encodings
nestedText, _ := nestedMessage.BodyText(0)
fmt.Println(nestedText)
nestedHTML, _ := nestedMessage.BodyHTML(0)
fmt.Println(nestedHTML)
nestedAttachment := nestedMessage.Attachment(0)
fmt.Println(nestedAttachment.Len())
// Full RFC2231 support for continuations and character sets
attachmentName, _ := nestedAttachment.AttachmentName()
fmt.Println(attachmentName)
// Integrates with encoding/json
pretty, _ := json.MarshalIndent(message, "", " ")
fmt.Println(string(pretty))
}
Output:
func (*MessageParser) ParseHeaders ¶
func (p *MessageParser) ParseHeaders(rawMessage []byte) *Message
ParseHeaders parses a byte slice containing the RFC5322 raw message and returns a Message containing only the headers, or nil if no headers were parsed.
func (*MessageParser) WithAddressHeaders ¶
func (p *MessageParser) WithAddressHeaders() *MessageParser
WithAddressHeaders registers parsers for all address headers:
- From
- Sender
- Reply-To
- To
- Cc
- Bcc
- Resent-From
- Resent-Sender
- Resent-To
- Resent-Cc
- Resent-Bcc
func (*MessageParser) WithDateHeaders ¶
func (p *MessageParser) WithDateHeaders() *MessageParser
WithDateHeaders registers parsers for all Date headers:
- Date
- Resent-Date
func (*MessageParser) WithMessageIDs ¶
func (p *MessageParser) WithMessageIDs() *MessageParser
WithMessageIDs registers parsers for all ID headers:
- Message-Id
- In-Reply-To
- References
- Resent-Message-Id
func (*MessageParser) WithMimeHeaders ¶
func (p *MessageParser) WithMimeHeaders() *MessageParser
WithMimeHeaders registers parsers for all MIME headers:
- Content-Type
- Content-Disposition
- Content-Id
- Content-Description
- Content-Location
- Content-Transfer-Encoding
Adding these MIME headers is required in order to parse message bodies.
func (*MessageParser) WithMinimalHeaders ¶
func (p *MessageParser) WithMinimalHeaders() *MessageParser
WithMinimalHeaders registers parsers for all MIME headers plus:
- Date
- Subject
- From
- Reply-To
- To
- Cc
- Bcc
func (*MessageParser) WithoutHeader ¶
func (p *MessageParser) WithoutHeader(header HeaderName) *MessageParser
WithoutHeader removes a custom header parser.
type MessagePart ¶
type MessagePart struct {
Headers []Header
IsEncodingProblem bool
Body PartType
// Encoding is the transfer encoding used by the raw body.
// It is not serialized to JSON.
Encoding Encoding
OffsetHeader int
OffsetBody int
OffsetEnd int
}
MessagePart is a single MIME part of a message.
func (*MessagePart) AttachmentName ¶
func (p *MessagePart) AttachmentName() (string, bool)
AttachmentName returns the attachment file name, if any.
func (*MessagePart) ContentDescription ¶
func (p *MessagePart) ContentDescription() (string, bool)
ContentDescription returns the part's Content-Description field.
func (*MessagePart) ContentDisposition ¶
func (p *MessagePart) ContentDisposition() *ContentType
ContentDisposition returns the part's Content-Disposition field.
func (*MessagePart) ContentID ¶
func (p *MessagePart) ContentID() (string, bool)
ContentID returns the part's Content-ID field.
func (*MessagePart) ContentLanguage ¶
func (p *MessagePart) ContentLanguage() *HeaderValue
ContentLanguage returns the part's Content-Language value, or the Empty value (never nil).
func (*MessagePart) ContentLocation ¶
func (p *MessagePart) ContentLocation() (string, bool)
ContentLocation returns the part's Content-Location field.
func (*MessagePart) ContentTransferEncoding ¶
func (p *MessagePart) ContentTransferEncoding() (string, bool)
ContentTransferEncoding returns the part's Content-Transfer-Encoding field.
func (*MessagePart) ContentType ¶
func (p *MessagePart) ContentType() *ContentType
ContentType returns the part's Content-Type field.
func (*MessagePart) Contents ¶
func (p *MessagePart) Contents() []byte
Contents returns the body as bytes: text bytes for Text/HTML, decoded bytes for binary, the nested raw message for message parts, nil for multipart. Text/HTML callers get a copy, since Go cannot alias a string's bytes.
func (*MessagePart) IsBinary ¶
func (p *MessagePart) IsBinary() bool
IsBinary reports whether the part is binary (Binary or InlineBinary).
func (*MessagePart) IsContentType ¶
func (p *MessagePart) IsContentType(ctype, subtype string) bool
IsContentType reports whether the Content-Type matches type and subtype.
func (*MessagePart) IsEmpty ¶
func (p *MessagePart) IsEmpty() bool
IsEmpty reports whether the body part is empty.
func (*MessagePart) IsMessage ¶
func (p *MessagePart) IsMessage() bool
IsMessage reports whether the part is a nested message.
func (*MessagePart) IsMultipart ¶
func (p *MessagePart) IsMultipart() bool
IsMultipart reports whether the part is multipart.
func (*MessagePart) IsText ¶
func (p *MessagePart) IsText() bool
IsText reports whether the part is a text/* part (Text or HTML).
func (*MessagePart) IsTextHTML ¶
func (p *MessagePart) IsTextHTML() bool
IsTextHTML reports whether the part is a text/html part.
func (*MessagePart) Len ¶
func (p *MessagePart) Len() int
Len returns the body content length in bytes, 0 for multipart parts.
func (MessagePart) MarshalJSON ¶
func (p MessagePart) MarshalJSON() ([]byte, error)
MarshalJSON writes the wire form; Encoding is never emitted.
func (*MessagePart) Message ¶
func (p *MessagePart) Message() *Message
Message returns the nested message, or nil.
func (*MessagePart) RawBodyOffset ¶
func (p *MessagePart) RawBodyOffset() int
RawBodyOffset returns the raw body offset of this part.
func (*MessagePart) RawEndOffset ¶
func (p *MessagePart) RawEndOffset() int
RawEndOffset returns the raw end offset of this part.
func (*MessagePart) RawHeaderOffset ¶
func (p *MessagePart) RawHeaderOffset() int
RawHeaderOffset returns the raw header offset of this part.
func (*MessagePart) RawLen ¶
func (p *MessagePart) RawLen() int
RawLen returns OffsetEnd - OffsetHeader, saturating at 0 so the result is never negative.
func (*MessagePart) String ¶
func (p *MessagePart) String() string
String returns the text contents, or "[no contents]" when there are none.
func (*MessagePart) SubParts ¶
func (p *MessagePart) SubParts() ([]int, bool)
SubParts returns the child part indexes of a multipart part; ok is false for any other part type.
func (*MessagePart) TextContents ¶
func (p *MessagePart) TextContents() (string, bool)
TextContents returns the body as a string. Binary and message parts convert only when their bytes are valid UTF-8, with no replacement characters. Multipart parts have no contents.
func (*MessagePart) UnmarshalJSON ¶
func (p *MessagePart) UnmarshalJSON(data []byte) error
UnmarshalJSON reads the wire form; Encoding is left as EncodingNone.
type MessageStream ¶
type MessageStream struct {
// contains filtered or unexported fields
}
MessageStream is a cursor over a raw message, used by every parsing routine. The position may run past the end of the data, which Offset clamps. There is a single checkpoint/restore slot.
func NewMessageStream ¶
func NewMessageStream(data []byte) *MessageStream
NewMessageStream returns a stream over data.
func (*MessageStream) Bytes ¶
func (s *MessageStream) Bytes(start, end int) []byte
Bytes returns the data in [start, end).
func (*MessageStream) Checkpoint ¶
func (s *MessageStream) Checkpoint()
Checkpoint records the current position for a later Restore.
func (*MessageStream) DecodeBase64MIME ¶
func (s *MessageStream) DecodeBase64MIME(boundary []byte) (int, []byte)
DecodeBase64MIME decodes a base64 MIME body while scanning for the multipart boundary. It returns the offset where the encoded body ends (math.MaxInt when a non-empty boundary was not found) and the decoded bytes.
func (*MessageStream) DecodeBase64Word ¶
func (s *MessageStream) DecodeBase64Word() ([]byte, bool)
DecodeBase64Word decodes an RFC2047 base64 encoded word up to the closing "?=" sequence, reporting false on invalid input.
func (*MessageStream) DecodeQuotedPrintableMIME ¶
func (s *MessageStream) DecodeQuotedPrintableMIME(boundary []byte) (int, []byte)
DecodeQuotedPrintableMIME decodes a quoted-printable MIME body while scanning for the multipart boundary. It returns the offset where the encoded body ends (math.MaxInt when a non-empty boundary was not found) and the decoded bytes.
func (*MessageStream) DecodeQuotedPrintableWord ¶
func (s *MessageStream) DecodeQuotedPrintableWord() ([]byte, bool)
DecodeQuotedPrintableWord decodes an RFC2047 quoted-printable encoded word up to the closing "?=" sequence, reporting false on invalid input.
func (*MessageStream) DecodeRFC2047 ¶
func (s *MessageStream) DecodeRFC2047() (string, bool)
DecodeRFC2047 decodes an RFC2047 encoded word ("charset?encoding?data?=", positioned after the leading "=?"), reporting false when the stream does not hold a valid encoded word.
func (*MessageStream) IsEOF ¶
func (s *MessageStream) IsEOF() bool
IsEOF reports whether all data has been consumed.
func (*MessageStream) IsMultipartEnd ¶
func (s *MessageStream) IsMultipartEnd() bool
IsMultipartEnd reports whether the bytes following a matched boundary mark the final "--boundary--" terminator. It consumes "\r\n", "--", "\n", or a whitespace run (via SkipCRLF) on recognized input, and restores the position on unrecognized input.
func (*MessageStream) MIMEPart ¶
func (s *MessageStream) MIMEPart(boundary []byte) (int, []byte)
MIMEPart reads one part body up to "--" followed by boundary, returning the offset where the content ends and the raw content bytes (a subslice of the stream data, never a copy). When a non-empty boundary is not found the position is restored to the part start and the returned offset is math.MaxInt (the "boundary not found" sentinel), with the bytes still holding the whole tail. An empty boundary consumes to EOF and returns the end offset.
func (*MessageStream) Next ¶
func (s *MessageStream) Next() (byte, bool)
Next consumes and returns the next byte. The position keeps advancing even when reading past the end.
func (*MessageStream) NextIsSpace ¶
func (s *MessageStream) NextIsSpace() bool
NextIsSpace consumes the next byte and reports whether it was a space or tab.
func (*MessageStream) Offset ¶
func (s *MessageStream) Offset() int
Offset returns the current position, clamped to the data length.
func (*MessageStream) ParseAddress ¶
func (s *MessageStream) ParseAddress() HeaderValue
ParseAddress parses one folded address header body into an Address value (a flat list or grouped addresses), or an Empty value when nothing was captured. It consumes the stream up to and including the header-terminating newline.
func (*MessageStream) ParseAndIgnore ¶
func (s *MessageStream) ParseAndIgnore()
ParseAndIgnore consumes a header value without parsing it, advancing the stream past the unfolded header end.
func (*MessageStream) ParseCommaSeparated ¶
func (s *MessageStream) ParseCommaSeparated() HeaderValue
ParseCommaSeparated parses a comma-separated header value (e.g. Keywords, Content-Language) with RFC2047 encoded-word support into Text, TextList or Empty.
func (*MessageStream) ParseContentType ¶
func (s *MessageStream) ParseContentType() HeaderValue
ParseContentType parses an RFC2045 Content-Type or RFC2183 Content-Disposition header body into a ContentType, or Empty when no type is present. It handles RFC2231 parameter continuations and charset encoding, RFC2047 encoded words in parameter values, and comments.
func (*MessageStream) ParseDate ¶
func (s *MessageStream) ParseDate() HeaderValue
ParseDate parses an RFC5322 Date header field, returning a DateTime value or Empty.
func (*MessageStream) ParseHeaders ¶
func (s *MessageStream) ParseHeaders(conf *MessageParser, headers *[]Header) bool
ParseHeaders parses all headers of the current MIME part into headers, dispatching each value to conf's parser for that header name. It returns true when the blank line ending the header block was reached (a body follows) and false on EOF.
func (*MessageStream) ParseID ¶
func (s *MessageStream) ParseID() HeaderValue
ParseID parses a Message-ID/References/In-Reply-To style header into one (Text) or many (TextList) angle-bracket-delimited ids, with a fallback for broken clients that omit the brackets.
func (*MessageStream) ParseRaw ¶
func (s *MessageStream) ParseRaw() HeaderValue
ParseRaw captures the raw header value up to the unfolded header end as a single Text (edge whitespace trimmed, interior folding bytes preserved), or Empty. Unlike the other field parsers, text pending at end of input is still returned.
func (*MessageStream) ParseReceived ¶
func (s *MessageStream) ParseReceived() HeaderValue
ParseReceived parses a Received header field, returning a Received value or Empty when not a single field could be extracted.
func (*MessageStream) ParseUnstructured ¶
func (s *MessageStream) ParseUnstructured() HeaderValue
ParseUnstructured parses an unstructured header (Subject, Comments, ...) into a single Text with folding removed and RFC2047 encoded words decoded, or Empty.
func (*MessageStream) Peek ¶
func (s *MessageStream) Peek() (byte, bool)
Peek returns the next byte without consuming it.
func (*MessageStream) PeekBytes ¶
func (s *MessageStream) PeekBytes(n int) []byte
PeekBytes returns the next n bytes without consuming them, or nil if fewer than n remain.
func (*MessageStream) PeekChar ¶
func (s *MessageStream) PeekChar(ch byte) bool
PeekChar reports whether the next byte equals ch.
func (*MessageStream) PeekNextIsSpace ¶
func (s *MessageStream) PeekNextIsSpace() bool
PeekNextIsSpace reports whether the next byte is a space or tab.
func (*MessageStream) ReadHeaderName ¶
func (s *MessageStream) ReadHeaderName() (HeaderName, bool)
ReadHeaderName consumes one header name from the stream, up to and including the ':' separator (or EOF), and returns the matched well-known HeaderName or an Other name holding the original text. It reports false on a '\n' before any usable colon or when no name characters were seen.
func (*MessageStream) Remaining ¶
func (s *MessageStream) Remaining() int
Remaining returns the number of unread bytes.
func (*MessageStream) Reset ¶
func (s *MessageStream) Reset()
Reset clears the checkpoint without moving.
func (*MessageStream) Restore ¶
func (s *MessageStream) Restore()
Restore rewinds to the last Checkpoint and clears it.
func (*MessageStream) SeekEnd ¶
func (s *MessageStream) SeekEnd()
SeekEnd moves the position to the end of the data.
func (*MessageStream) SeekNextPart ¶
func (s *MessageStream) SeekNextPart(boundary []byte) bool
SeekNextPart scans forward for "--" followed by boundary. On a match the stream is left positioned right after the boundary text and it returns true; otherwise the original position is restored and it returns false. An empty boundary never matches. The match is not anchored to line starts.
func (*MessageStream) SeekNextPartOffset ¶
func (s *MessageStream) SeekNextPartOffset(boundary []byte) (offset int, ok bool)
SeekNextPartOffset scans forward for "--" followed by boundary and, on a match, returns the offset where the content before the boundary line ends (the start of its terminating newline) with ok true, leaving the stream positioned after the boundary text. When no match is found the original position is restored and ok is false.
func (*MessageStream) SeekPartEnd ¶
func (s *MessageStream) SeekPartEnd(boundary []byte) (int, bool)
SeekPartEnd advances past the current part, returning the offset where its content ends and whether the boundary was found. A nil boundary seeks to EOF and reports true. A non-nil boundary, empty or not, scans for "--" followed by the boundary; on EOF without a match it reports (Offset(), false) and leaves the stream at EOF without restoring.
func (*MessageStream) SkipBytes ¶
func (s *MessageStream) SkipBytes(n int)
SkipBytes advances the position by n.
func (*MessageStream) SkipCRLF ¶
func (s *MessageStream) SkipCRLF()
SkipCRLF consumes any run of '\r', space and '\t' bytes, stops after consuming a single '\n', and stops before any other byte.
func (*MessageStream) TryNextIsSpace ¶
func (s *MessageStream) TryNextIsSpace() bool
TryNextIsSpace consumes the next byte only if it is a space or tab.
func (*MessageStream) TrySkip ¶
func (s *MessageStream) TrySkip(bytes []byte) bool
TrySkip consumes bytes if the stream starts with them.
func (*MessageStream) TrySkipChar ¶
func (s *MessageStream) TrySkipChar(ch byte) bool
TrySkipChar consumes the next byte if it equals ch.
type MimeHeaders ¶
type MimeHeaders interface {
// ContentDescription returns the Content-Description field.
ContentDescription() (string, bool)
// ContentDisposition returns the Content-Disposition field, or nil.
ContentDisposition() *ContentType
// ContentID returns the Content-ID field.
ContentID() (string, bool)
// ContentTransferEncoding returns the Content-Transfer-Encoding field.
ContentTransferEncoding() (string, bool)
// ContentType returns the Content-Type field, or nil.
ContentType() *ContentType
// ContentLanguage returns the Content-Language value, or the Empty
// value (never nil).
ContentLanguage() *HeaderValue
// ContentLocation returns the Content-Location field.
ContentLocation() (string, bool)
// AttachmentName returns the attachment file name, if any: the
// Content-Disposition "filename" attribute, falling back to the
// Content-Type "name" attribute.
AttachmentName() (string, bool)
// IsContentType reports whether the Content-Type matches the given
// type and subtype, ASCII-case-insensitively.
IsContentType(ctype, subtype string) bool
}
MimeHeaders gives access to the MIME header fields. Implemented by *Message (via its root part) and *MessagePart.
type PartType ¶
type PartType struct {
// contains filtered or unexported fields
}
PartType is the decoded body of a message part: a text/* part, a text/html part, binary content, inline binary content, a nested RFC5322 message, or the list of child part indexes of a multipart part.
The zero value is an empty multipart.
func PartTypeInlineBinary ¶
PartTypeInlineBinary returns an inline binary body.
func PartTypeMessage ¶
PartTypeMessage returns a nested message body.
func PartTypeMultipart ¶
PartTypeMultipart returns a multipart body holding child part indexes.
func (*PartType) Len ¶
Len returns the byte length of the body: text length for Text/HTML, byte length for the binary variants, 0 for Multipart. For a Message part it is the nested message's ENTIRE RawMessage buffer, unlike MessagePart.Len, which measures only the root-part slice.
func (PartType) MarshalJSON ¶
MarshalJSON serializes the externally tagged PartType variants: {"Text": "..."}, {"Html": "..."}, {"Binary": [n, ...]}, {"InlineBinary": [n, ...]}, {"Message": {...}} and {"Multipart": [id, ...]}.
func (*PartType) UnmarshalJSON ¶
UnmarshalJSON decodes the externally tagged PartType variants.
type Protocol ¶
type Protocol uint8
Protocol is an IANA mail transmission type from a Received "with" clause.
const ( // IANA Mail Transmission Types ProtocolSMTP Protocol = iota ProtocolESMTP ProtocolESMTPA ProtocolESMTPS ProtocolESMTPSA ProtocolLMTP ProtocolLMTPA ProtocolLMTPS ProtocolLMTPSA ProtocolMMS ProtocolUTF8SMTP ProtocolUTF8SMTPA ProtocolUTF8SMTPS ProtocolUTF8SMTPSA ProtocolUTF8LMTP ProtocolUTF8LMTPA ProtocolUTF8LMTPS ProtocolUTF8LMTPSA // Non-Standard Mail Transmission Types ProtocolHTTP ProtocolHTTPS ProtocolIMAP ProtocolPOP3 ProtocolLocal // includes stdin, socket, etc. )
func (Protocol) AsStr ¶
AsStr returns the display name of the protocol. It matches the JSON name, so that table is reused.
func (Protocol) MarshalJSON ¶
MarshalJSON serializes the bare variant identifier string.
func (*Protocol) UnmarshalJSON ¶
UnmarshalJSON decodes the bare variant identifier string.
type Received ¶
type Received struct {
From *Host
FromIP *netip.Addr
FromIPRev *string
By *Host
For *string
With *Protocol
TLSVersion *TLSVersion
TLSCipher *string
ID *string
Ident *string
Helo *Host
HeloCmd *Greeting
Via *string
Date *DateTime
}
Received is a parsed Received header (RFC5321/RFC5322 trace field).
func (Received) MarshalJSON ¶
MarshalJSON writes the wire form.
func (*Received) UnmarshalJSON ¶
UnmarshalJSON reads the wire form.
type TLSVersion ¶
type TLSVersion uint8
TLSVersion is a TLS protocol version from a Received header.
const ( SSLv2 TLSVersion = iota SSLv3 TLSv1_0 TLSv1_1 TLSv1_2 TLSv1_3 DTLSv1_0 DTLSv1_2 DTLSv1_3 )
The constant spellings are load-bearing: the JSON form ("TLSv1_2") and the display form ("TLSv1.2") both derive from them.
func (TLSVersion) AsStr ¶
func (t TLSVersion) AsStr() string
AsStr returns the display name of the TLS version.
func (TLSVersion) MarshalJSON ¶
func (t TLSVersion) MarshalJSON() ([]byte, error)
MarshalJSON serializes the bare variant identifier string.
func (*TLSVersion) UnmarshalJSON ¶
func (t *TLSVersion) UnmarshalJSON(data []byte) error
UnmarshalJSON decodes the bare variant identifier string.
Source Files
¶
- address.go
- builder.go
- charset.go
- charset_map.go
- charset_multi_byte.go
- charset_single_byte.go
- charset_utf.go
- decoder.go
- decoder_base64.go
- decoder_encoded_word.go
- decoder_hex.go
- decoder_html.go
- decoder_quoted_printable.go
- field_address.go
- field_content_type.go
- field_date.go
- field_id.go
- field_list.go
- field_raw.go
- field_received.go
- field_thread.go
- field_unstructured.go
- header.go
- json.go
- message.go
- parse_header.go
- parse_message.go
- parse_mime.go
- preview.go
- stream.go
- types.go