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([]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([]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([]byte) error
- type DecoderFnc
- type Encoding
- type Greeting
- type Group
- 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([]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([]byte) error
- func (v *HeaderValue) UnwrapAddress() (Address, error)
- func (v *HeaderValue) UnwrapContentType() (ContentType, error)
- func (v *HeaderValue) UnwrapDateTime() (DateTime, error)
- func (v *HeaderValue) UnwrapReceived() (Received, error)
- func (v *HeaderValue) UnwrapText() (string, error)
- func (v *HeaderValue) UnwrapTextList() ([]string, error)
- 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) AllReceived() iter.Seq[*Received]
- 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) 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() *DateTime
- func (m *Message) ResentFrom() *Address
- func (m *Message) ResentMessageID() (string, bool)
- 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([]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([]byte) error
- 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([]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.
var ErrJSONDecodingUnsupported = errors.New("mailparser: JSON decoding is not supported; store the raw message and re-parse")
ErrJSONDecodingUnsupported is returned by every exported UnmarshalJSON on this package's types. A Message carries offsets, raw bytes and gated header storage that the wire form does not preserve, so decoding one back yields a Message the parser never produces. Keep the raw message and re-parse it.
var ErrWrongKind = errors.New("mailparser: header value has a different kind")
ErrWrongKind is returned by the Unwrap methods when the header value holds a different kind, or when the kind is set but its payload pointer is not.
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. It drops tags, comments and head/style/script/template contents, decodes entities, collapses whitespace runs, and turns <br> and closing </p> into 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, stripping reply/forward prefixes, leading mailing-list "[...]" blobs, "[fwd: ...]" wrappers and trailing "(fwd)" suffixes. The result is a substring of text.
func TrimTrailingFwd ¶
TrimTrailingFwd trims leading and trailing whitespace and any number of trailing "(fwd)"-style groups from text, returning a substring. It scans in reverse, and a stripped group re-arms the trailing trim.
func TruncateHTML ¶
TruncateHTML truncates HTML markup to at most maxLen bytes, appending "..." when maxLen > 6. A cut that lands inside a tag or comment rolls back to the end of the last complete tag.
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, so absent and present-but-empty are one state and callers need no nil check. The wire form maps "" to null and back.
func (Addr) MarshalJSON ¶
MarshalJSON writes the wire form, encoding an absent name or address as null.
func (*Addr) UnmarshalJSON ¶
UnmarshalJSON always fails: see ErrJSONDecodingUnsupported.
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 (*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, skipping empty groups. It is never nil on a value a Message address accessor returns; other values can hold nothing to return.
func (*Address) Last ¶
Last returns the last address in the list, or the last address across the groups, skipping empty groups. It is never nil on a value a Message address accessor returns; other values can hold nothing to return.
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 always fails: see ErrJSONDecodingUnsupported.
type Attribute ¶
Attribute is a single Content-Type/Content-Disposition attribute.
func (Attribute) MarshalJSON ¶
MarshalJSON writes the wire form.
func (*Attribute) UnmarshalJSON ¶
UnmarshalJSON always fails: see ErrJSONDecodingUnsupported.
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([]byte) error
UnmarshalJSON always fails: see ErrJSONDecodingUnsupported.
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 always fails: see ErrJSONDecodingUnsupported.
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 always fails: see ErrJSONDecodingUnsupported.
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 always fails: see ErrJSONDecodingUnsupported.
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 travels by value, never as a pointer, so callers never nil-check one. An unnamed group has Name == "".
func (Group) MarshalJSON ¶
MarshalJSON writes the wire form, encoding an unnamed group as null.
func (*Group) UnmarshalJSON ¶
UnmarshalJSON always fails: see ErrJSONDecodingUnsupported.
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 always fails: see ErrJSONDecodingUnsupported.
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 and any other valid name is kept verbatim as an Other name. Empty input, or a byte 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 validates a standalone header-name string and returns the matched well-known HeaderName or an Other name holding it unchanged. It reports false on empty input or a byte 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([]byte) error
UnmarshalJSON always fails: see ErrJSONDecodingUnsupported.
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 (*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. A kind whose payload pointer is missing counts 0.
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([]byte) error
UnmarshalJSON always fails: see ErrJSONDecodingUnsupported.
func (*HeaderValue) UnwrapAddress ¶
func (v *HeaderValue) UnwrapAddress() (Address, error)
UnwrapAddress returns the Address value, or the zero Address and ErrWrongKind.
func (*HeaderValue) UnwrapContentType ¶
func (v *HeaderValue) UnwrapContentType() (ContentType, error)
UnwrapContentType returns the ContentType value, or the zero ContentType and ErrWrongKind.
func (*HeaderValue) UnwrapDateTime ¶
func (v *HeaderValue) UnwrapDateTime() (DateTime, error)
UnwrapDateTime returns the DateTime value, or the zero DateTime and ErrWrongKind.
func (*HeaderValue) UnwrapReceived ¶
func (v *HeaderValue) UnwrapReceived() (Received, error)
UnwrapReceived returns the Received value, or the zero Received and ErrWrongKind.
func (*HeaderValue) UnwrapText ¶
func (v *HeaderValue) UnwrapText() (string, error)
UnwrapText returns the Text value, or "" and ErrWrongKind.
func (*HeaderValue) UnwrapTextList ¶
func (v *HeaderValue) UnwrapTextList() ([]string, error)
UnwrapTextList returns the TextList value, promoting a Text value to a single-element list. Any other kind gives nil and ErrWrongKind.
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 always fails: see ErrJSONDecodingUnsupported.
type Message ¶
type Message struct {
// HTMLBody, TextBody and Attachments hold indexes into Parts.
HTMLBody []int
TextBody []int
Attachments []int
Parts []MessagePart
// RawMessage holds the raw message bytes this Message comes 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, and prints names rather than writing files.
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. Headers carrying no usable address are skipped, so no yielded value is nil.
func (*Message) AllCc ¶
AllCc iterates over all Cc headers as Addresses in message order. RFC5322 section 4.5.3 allows the header to repeat. Headers carrying no usable address are skipped, so no yielded value is nil.
func (*Message) AllReceived ¶ added in v0.1.5
AllReceived iterates over all Received headers in the order they appear in the message. Headers whose value is not a usable Received are skipped, so no yielded value is nil.
func (*Message) AllTo ¶
AllTo iterates over all To headers as Addresses in message order. RFC5322 section 4.5.3 allows the header to repeat. Headers carrying no usable address are skipped, so no yielded value is nil.
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) Bcc ¶
Bcc returns the last Bcc header as an Address, or nil when the header is absent or carries no usable address.
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) Cc ¶
Cc returns the last Cc header as an Address, or nil when the header is absent or carries no usable address.
func (*Message) Comments ¶
func (m *Message) Comments() *HeaderValue
Comments returns the last Comments value, or nil when the header is absent.
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 nil when the header is absent.
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) Date ¶
Date returns the DateTime of the last Date header, or nil when the header is absent or its value is not a usable date.
func (*Message) From ¶
From returns the last From header as an Address, or nil when the header is absent or carries no usable address. A non-nil result needs no further check: First() and Last() resolve and every Addr in it has an Address.
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, its offsets fall outside RawMessage, 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 offsets fall outside RawMessage or 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 nil when the header is absent.
func (*Message) IsContentType ¶
IsContentType reports whether the Content-Type matches type and subtype.
func (*Message) IsEmpty ¶
IsEmpty reports whether the message has no parts. Only a hand-built value is ever empty: Parse returns nil rather than a part-less Message, so a non-nil parse result always has at least one part.
func (*Message) Keywords ¶
func (m *Message) Keywords() *HeaderValue
Keywords returns the last Keywords value, or nil when the header is absent.
func (*Message) ListArchive ¶
func (m *Message) ListArchive() *HeaderValue
ListArchive returns the last List-Archive value, or nil when the header is absent.
func (*Message) ListHelp ¶
func (m *Message) ListHelp() *HeaderValue
ListHelp returns the last List-Help value, or nil when the header is absent.
func (*Message) ListID ¶
func (m *Message) ListID() *HeaderValue
ListID returns the last List-ID value, or nil when the header is absent.
func (*Message) ListOwner ¶
func (m *Message) ListOwner() *HeaderValue
ListOwner returns the last List-Owner value, or nil when the header is absent.
func (*Message) ListPost ¶
func (m *Message) ListPost() *HeaderValue
ListPost returns the last List-Post value, or nil when the header is absent.
func (*Message) ListSubscribe ¶
func (m *Message) ListSubscribe() *HeaderValue
ListSubscribe returns the last List-Subscribe value, or nil when the header is absent.
func (*Message) ListUnsubscribe ¶
func (m *Message) ListUnsubscribe() *HeaderValue
ListUnsubscribe returns the last List-Unsubscribe value, or nil when the header is absent.
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 nil when the header is absent.
func (*Message) Part ¶
func (m *Message) Part(pos int) *MessagePart
Part returns the message part at pos, or nil.
func (*Message) Received ¶
Received returns the LAST Received header, or nil when the header is absent or its value is not a usable Received.
func (*Message) References ¶
func (m *Message) References() *HeaderValue
References returns the last References value, or nil when the header is absent.
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) ReplyTo ¶
ReplyTo returns the last Reply-To header as an Address, or nil when the header is absent or carries no usable address.
func (*Message) ResentBcc ¶
ResentBcc returns the last Resent-Bcc header as an Address, or nil when the header is absent or carries no usable address.
func (*Message) ResentCc ¶
ResentCc returns the last Resent-Cc header as an Address, or nil when the header is absent or carries no usable address.
func (*Message) ResentDate ¶
ResentDate returns the DateTime of the last Resent-Date header, or nil when the header is absent or its value is not a usable date.
func (*Message) ResentFrom ¶
ResentFrom returns the last Resent-From header as an Address, or nil when the header is absent or carries no usable address.
func (*Message) ResentMessageID ¶
ResentMessageID returns the text of the last Resent-Message-ID header.
func (*Message) ResentSender ¶
ResentSender returns the last Resent-Sender header as an Address, or nil when the header is absent or carries no usable address.
func (*Message) ResentTo ¶
ResentTo returns the last Resent-To header as an Address, or nil when the header is absent or carries no usable address.
func (*Message) ReturnAddress ¶
ReturnAddress returns the return address from Return-Path or From. A Text Return-Path wins, a TextList one yields its last element and never falls through. Otherwise From supplies its first address, and a From with none yields false. The parser gates From, so a stored From always has a first address; a transplanted value that does not still yields false.
func (*Message) ReturnPath ¶
func (m *Message) ReturnPath() *HeaderValue
ReturnPath returns the last Return-Path value, or nil when the header is absent.
func (*Message) RootPart ¶
func (m *Message) RootPart() *MessagePart
RootPart returns the root message part, or nil when the message has no parts. The parser never produces that state; a hand-built Message can.
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) Sender ¶
Sender returns the last Sender header as an Address, or nil when the header is absent or carries no usable address.
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 when there is no usable Subject text, exactly as Subject() reports it - a present but empty Subject included.
func (*Message) To ¶
To returns the last To header as an Address, or nil when the header is absent or carries no usable address.
func (*Message) UnmarshalJSON ¶
UnmarshalJSON always fails: see ErrJSONDecodingUnsupported.
type MessageParser ¶
type MessageParser struct {
// contains filtered or unexported fields
}
MessageParser is a configurable RFC5322/RFC822 message parser.
With no custom parser registered it parses every IANA-registered header with that header's parser and everything else raw. Registering one custom parser replaces that dispatch with the custom map plus 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 that parses every IANA-registered header with that header's parser and every Other header 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 an RFC5322 raw message and returns a Message. It never panics and parses on a best-effort basis. It returns nil only when the input yields neither a body part nor a header field: an input with no header line still parses when a body does ("\n" gives one empty text part), and a header block with no body parses as a headers-only message.
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() // well-formed input: From() is non-nil and then guarantees a usable address
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 on the export side only. Unmarshal
// returns ErrJSONDecodingUnsupported, so keep the raw message.
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 the 11 RFC5322 address headers: From, Sender, Reply-To, To, Cc, Bcc and their Resent- forms.
func (*MessageParser) WithDateHeaders ¶
func (p *MessageParser) WithDateHeaders() *MessageParser
WithDateHeaders registers parsers for Date and Resent-Date.
func (*MessageParser) WithMessageIDs ¶
func (p *MessageParser) WithMessageIDs() *MessageParser
WithMessageIDs registers parsers for Message-Id, In-Reply-To, References and Resent-Message-Id.
func (*MessageParser) WithMimeHeaders ¶
func (p *MessageParser) WithMimeHeaders() *MessageParser
WithMimeHeaders registers parsers for Content-Type, Content-Disposition, Content-Id, Content-Description, Content-Location and Content-Transfer-Encoding. Parsing message bodies requires them.
func (*MessageParser) WithMinimalHeaders ¶
func (p *MessageParser) WithMinimalHeaders() *MessageParser
WithMinimalHeaders registers parsers for all MIME headers plus Date, Subject, From, Reply-To, To, Cc and 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 nil when the header is absent.
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([]byte) error
UnmarshalJSON always fails: see ErrJSONDecodingUnsupported.
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 nil when the
// header is absent.
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: text, HTML, binary, inline binary, a nested RFC5322 message, or the 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. A Message part measures the nested message's entire RawMessage buffer, and 0 when that message is nil.
func (PartType) MarshalJSON ¶
MarshalJSON serializes the externally tagged PartType variants: {"Text": "..."}, {"Html": "..."}, {"Binary": [n, ...]}, {"InlineBinary": [n, ...]}, {"Message": {...}} and {"Multipart": [id, ...]}.
func (*PartType) UnmarshalJSON ¶
UnmarshalJSON always fails: see ErrJSONDecodingUnsupported.
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 always fails: see ErrJSONDecodingUnsupported.
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 always fails: see ErrJSONDecodingUnsupported.
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([]byte) error
UnmarshalJSON always fails: see ErrJSONDecodingUnsupported.
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