Documentation ¶
Overview ¶
Package enmime implements a MIME encoding and decoding library. It's built on top of Go's included mime/multipart support where possible, but is geared towards parsing MIME encoded emails.
Overview ¶
The enmime API has two conceptual layers. The lower layer is a tree of Part structs, representing each component of a decoded MIME message. The upper layer, called an Envelope provides an intuitive way to interact with a MIME message.
Part Tree ¶
Calling ReadParts causes enmime to parse the body of a MIME message into a tree of Part objects, each of which is aware of its content type, filename and headers. The content of a Part is available as a slice of bytes via the Content field.
If the part was encoded in quoted-printable or base64, it is decoded prior to being placed in Content. If the Part contains text in a character set other than utf-8, enmime will attempt to convert it to utf-8.
To locate a particular Part, pass a custom PartMatcher function into the BreadthMatchFirst() or DepthMatchFirst() methods to search the Part tree. BreadthMatchAll() and DepthMatchAll() will collect all Parts matching your criteria.
Envelope ¶
ReadEnvelope returns an Envelope struct. Behind the scenes a Part tree is constructed, and then sorted into the correct fields of the Envelope.
The Envelope contains both the plain text and HTML portions of the email. If there was no plain text Part available, the HTML Part will be down-converted using the html2text library1. The root of the Part tree, as well as slices of the inline and attachment Parts are also available.
Headers ¶
Every MIME Part has its own headers, accessible via the Part.Header field. The raw headers for an Envelope are available in Root.Header. Envelope also provides helper methods to fetch headers: GetHeader(key) will return the RFC 2047 decoded value of the specified header. AddressList(key) will convert the specified address header into a slice of net/mail.Address values.
Errors ¶
enmime attempts to be tolerant of poorly encoded MIME messages. In situations where parsing is not possible, the ReadEnvelope and ReadParts functions will return a hard error. If enmime is able to continue parsing the message, it will add an entry to the Errors slice on the relevant Part. After parsing is complete, all Part errors will be appended to the Envelope Errors slice. The Error* constants can be used to identify a specific class of error.
Please note that enmime parses messages into memory, so it is not likely to perform well with multi-gigabyte attachments.
enmime is open source software released under the MIT License. The latest version can be found at https://github.com/jhillyerd/enmime
Index ¶
- Constants
- Variables
- func AllowCorruptTextPartErrorPolicy(p *Part, err error) bool
- func DecodeHeaders(b []byte, addtlHeaders ...string) (textproto.MIMEHeader, error)
- func DecodeRFC2047(s string) string
- func IsBase64CorruptInputError(err error) bool
- func ParseAddressList(list string) ([]*mail.Address, error)
- func ParseMediaType(ctype string) (mtype string, params map[string]string, invalidParams []string, err error)deprecated
- func ReadHeader(r *bufio.Reader, p ErrorCollector) (textproto.MIMEHeader, error)
- type CustomParseMediaType
- type Envelope
- func (e *Envelope) AddHeader(name string, value string) error
- func (e *Envelope) AddressList(key string) ([]*mail.Address, error)
- func (e *Envelope) Clone() *Envelope
- func (e *Envelope) Date() (time.Time, error)
- func (e *Envelope) DeleteHeader(name string) error
- func (e *Envelope) GetHeader(name string) string
- func (e *Envelope) GetHeaderKeys() (headers []string)
- func (e *Envelope) GetHeaderValues(name string) []string
- func (e *Envelope) SetHeader(name string, value []string) error
- type Error
- type ErrorCollector
- type MailBuilder
- func (p MailBuilder) AddAttachment(b []byte, contentType string, fileName string) MailBuilder
- func (p MailBuilder) AddAttachmentWithReader(r io.Reader, contentType string, fileName string) MailBuilder
- func (p MailBuilder) AddFileAttachment(path string) MailBuilder
- func (p MailBuilder) AddFileInline(path string) MailBuilder
- func (p MailBuilder) AddFileOtherPart(path string) MailBuilder
- func (p MailBuilder) AddInline(b []byte, contentType string, fileName string, contentID string) MailBuilder
- func (p MailBuilder) AddOtherPart(b []byte, contentType string, fileName string, contentID string) MailBuilder
- func (p MailBuilder) BCC(name, addr string) MailBuilder
- func (p MailBuilder) BCCAddrs(bcc []mail.Address) MailBuilder
- func (p MailBuilder) Build() (*Part, error)
- func (p MailBuilder) CC(name, addr string) MailBuilder
- func (p MailBuilder) CCAddrs(cc []mail.Address) MailBuilder
- func (p MailBuilder) Date(date time.Time) MailBuilder
- func (p MailBuilder) Equals(o MailBuilder) bool
- func (p MailBuilder) Error() error
- func (p MailBuilder) From(name, addr string) MailBuilder
- func (p *MailBuilder) GetBCC() []mail.Address
- func (p *MailBuilder) GetCC() []mail.Address
- func (p *MailBuilder) GetDate() time.Time
- func (p *MailBuilder) GetFrom() mail.Address
- func (p *MailBuilder) GetHTML() []byte
- func (p *MailBuilder) GetHeader(name string) string
- func (p *MailBuilder) GetReplyTo() []mail.Address
- func (p *MailBuilder) GetSubject() string
- func (p *MailBuilder) GetText() []byte
- func (p *MailBuilder) GetTo() []mail.Address
- func (p MailBuilder) HTML(body []byte) MailBuilder
- func (p MailBuilder) Header(name, value string) MailBuilder
- func (p MailBuilder) RandSeed(seed int64) MailBuilder
- func (p MailBuilder) ReplyTo(name, addr string) MailBuilder
- func (p MailBuilder) ReplyToAddrs(replyTo []mail.Address) MailBuilder
- func (p MailBuilder) Send(sender Sender) error
- func (p MailBuilder) SendWithReversePath(sender Sender, from string) error
- func (p MailBuilder) Subject(subject string) MailBuilder
- func (p MailBuilder) Text(body []byte) MailBuilder
- func (p MailBuilder) To(name, addr string) MailBuilder
- func (p MailBuilder) ToAddrs(to []mail.Address) MailBuilder
- type Option
- func DisableCharacterDetection(disableCharacterDetection bool) Option
- func DisableTextConversion(disableTextConversion bool) Option
- func MaxStoredPartErrors(n int) Option
- func MultipartWOBoundaryAsSinglePart(a bool) Option
- func RawContent(a bool) Option
- func SetCustomParseMediaType(customParseMediaType CustomParseMediaType) Option
- func SetReadPartErrorPolicy(f ReadPartErrorPolicy) Option
- func SkipMalformedParts(s bool) Option
- func StripMediaTypeInvalidCharacters(stripMediaTypeInvalidCharacters bool) Option
- type Parser
- type Part
- func (p *Part) AddChild(child *Part)
- func (p *Part) BreadthMatchAll(matcher PartMatcher) []*Part
- func (p *Part) BreadthMatchFirst(matcher PartMatcher) *Part
- func (p *Part) Clone(parent *Part) *Part
- func (p *Part) DepthMatchAll(matcher PartMatcher) []*Part
- func (p *Part) DepthMatchFirst(matcher PartMatcher) *Part
- func (p *Part) Encode(writer io.Writer) error
- func (p *Part) TextContent() bool
- type PartMatcher
- type ReadPartErrorPolicy
- type SMTPSender
- type Sender
Examples ¶
Constants ¶
const ( // ErrorMalformedBase64 name. ErrorMalformedBase64 = "Malformed Base64" // ErrorMalformedHeader name. ErrorMalformedHeader = "Malformed Header" // ErrorMissingBoundary name. ErrorMissingBoundary = "Missing Boundary" // ErrorMissingContentType name. ErrorMissingContentType = "Missing Content-Type" // ErrorCharsetConversion name. ErrorCharsetConversion = "Character Set Conversion" // ErrorContentEncoding name. ErrorContentEncoding = "Content Encoding" // ErrorPlainTextFromHTML name. ErrorPlainTextFromHTML = "Plain Text from HTML" // ErrorCharsetDeclaration name. ErrorCharsetDeclaration = "Character Set Declaration Mismatch" // ErrorMissingRecipient name. ErrorMissingRecipient = "no recipients (to, cc, bcc) set" // ErrorMalformedChildPart name. ErrorMalformedChildPart = "Malformed child part" )
Variables ¶
var AddressHeaders = map[string]bool{ "bcc": true, "cc": true, "delivered-to": true, "from": true, "reply-to": true, "to": true, "sender": true, "resent-bcc": true, "resent-cc": true, "resent-from": true, "resent-reply-to": true, "resent-to": true, "resent-sender": true, }
AddressHeaders is the set of SMTP headers that contain email addresses, used by Envelope.AddressList(). Key characters must be all lowercase.
var MaxPartErrors = 0
MaxPartErrors limits number of part parsing errors, errors after the limit are ignored. 0 means unlimited.
Deprecated: This limit may be set via the `MaxStoredPartErrors` Parser option.
Functions ¶
func AllowCorruptTextPartErrorPolicy ¶ added in v0.10.1
AllowCorruptTextPartErrorPolicy recovers partial content from base64.CorruptInputError when content type is text/plain or text/html.
func DecodeHeaders ¶ added in v0.7.0
func DecodeHeaders(b []byte, addtlHeaders ...string) (textproto.MIMEHeader, error)
DecodeHeaders returns a limited selection of mime headers for use by user agents Default header list:
"Date", "Subject", "Sender", "From", "To", "CC" and "BCC"
Additional headers provided will be formatted canonically:
h, err := enmime.DecodeHeaders(b, "content-type", "user-agent")
func DecodeRFC2047 ¶ added in v0.11.0
DecodeRFC2047 decodes the given string according to RFC 2047 and returns the decoded UTF-8 equivalent. If the input is not using RFC 2047 encoding, or the charset is not recognized, it will return the input unmodified.
func IsBase64CorruptInputError ¶ added in v0.10.1
IsBase64CorruptInputError returns true when err is of type base64.CorruptInputError.
It can be used to create ReadPartErrorPolicy functions.
func ParseAddressList ¶ added in v0.9.4
ParseAddressList returns a mail.Address slice with RFC 2047 encoded names converted to UTF-8. It is more tolerant of malformed headers than the ParseAddressList func provided in Go's net/mail package.
func ParseMediaType
deprecated
added in
v0.6.0
func ParseMediaType(ctype string) (mtype string, params map[string]string, invalidParams []string, err error)
ParseMediaType is a more tolerant implementation of Go's mime.ParseMediaType function.
Tolerances accounted for:
- Missing ';' between content-type and media parameters
- Repeating media parameters
- Unquoted values in media parameters containing 'tspecials' characters
Deprecated: Use mediaType.Parse instead
func ReadHeader ¶ added in v1.1.0
func ReadHeader(r *bufio.Reader, p ErrorCollector) (textproto.MIMEHeader, error)
ReadHeader reads a block of SMTP or MIME headers and returns a textproto.MIMEHeader. Header parse warnings & errors will be added to ErrorCollector, io errors will be returned directly.
Types ¶
type CustomParseMediaType ¶ added in v1.1.0
type CustomParseMediaType func(ctype string) (mtype string, params map[string]string, invalidParams []string, err error)
CustomParseMediaType parses media type. See ParseMediaType for more details
type Envelope ¶
type Envelope struct { Text string // The plain text portion of the message HTML string // The HTML portion of the message Root *Part // The top-level Part Attachments []*Part // All parts having a Content-Disposition of attachment Inlines []*Part // All parts having a Content-Disposition of inline // All non-text parts that were not placed in Attachments or Inlines, such as multipart/related // content. OtherParts []*Part Errors []*Error // Errors encountered while parsing // contains filtered or unexported fields }
Envelope is a simplified wrapper for MIME email messages.
Example ¶
ExampleEnvelope demonstrates the relationship between Envelope and Parts.
package main import ( "fmt" "strings" "github.com/jhillyerd/enmime" ) func main() { // Create sample message in memory raw := `From: user@inbucket.org Subject: Example message Content-Type: multipart/alternative; boundary=Enmime-100 --Enmime-100 Content-Type: text/plain X-Comment: part1 hello! --Enmime-100 Content-Type: text/html X-Comment: part2 <b>hello!</b> --Enmime-100 Content-Type: text/plain Content-Disposition: attachment; filename=hi.txt X-Comment: part3 hello again! --Enmime-100-- ` // Parse message body with enmime.ReadEnvelope r := strings.NewReader(raw) env, err := enmime.ReadEnvelope(r) if err != nil { fmt.Print(err) return } // The root Part contains the message header, which is also available via the // Envelope.GetHeader() method. fmt.Printf("Root Part Subject: %q\n", env.Root.Header.Get("Subject")) fmt.Printf("Envelope Subject: %q\n", env.GetHeader("Subject")) fmt.Println() // The text from part1 is consumed and placed into the Envelope.Text field. fmt.Printf("Text Content: %q\n", env.Text) // But part1 is also available as a child of the root Part. Only the headers may be accessed, // because the content has been consumed. part1 := env.Root.FirstChild fmt.Printf("Part 1 X-Comment: %q\n", part1.Header.Get("X-Comment")) fmt.Println() // The HTML from part2 is consumed and placed into the Envelope.HTML field. fmt.Printf("HTML Content: %q\n", env.HTML) // And part2 is available as the second child of the root Part. Only the headers may be // accessed, because the content has been consumed. part2 := env.Root.FirstChild.NextSibling fmt.Printf("Part 2 X-Comment: %q\n", part2.Header.Get("X-Comment")) fmt.Println() // Because part3 has a disposition of attachment, it is added to the Envelope.Attachments // slice fmt.Printf("Attachment 1 X-Comment: %q\n", env.Attachments[0].Header.Get("X-Comment")) // And is still available as the third child of the root Part part3 := env.Root.FirstChild.NextSibling.NextSibling fmt.Printf("Part 3 X-Comment: %q\n", part3.Header.Get("X-Comment")) // The content of Attachments, Inlines and OtherParts are available as a slice of bytes fmt.Printf("Part 3 Content: %q\n", part3.Content) // part3 contained a malformed header line, enmime has attached an Error to it p3error := part3.Errors[0] fmt.Println(p3error.Error()) fmt.Println() // All Part errors are collected and placed into Envelope.Errors fmt.Println("Envelope errors:") for _, e := range env.Errors { fmt.Println(e.Error()) } }
Output: Root Part Subject: "Example message" Envelope Subject: "Example message" Text Content: "hello!" Part 1 X-Comment: "part1" HTML Content: "<b>hello!</b>" Part 2 X-Comment: "part2" Attachment 1 X-Comment: "part3" Part 3 X-Comment: "part3" Part 3 Content: "hello again!" [W] Malformed Header: Continued line "filename=hi.txt" was not indented Envelope errors: [W] Malformed Header: Continued line "filename=hi.txt" was not indented
func EnvelopeFromPart ¶
EnvelopeFromPart uses the provided Part tree to build an Envelope, downconverting HTML to plain text if needed, and sorting the attachments, inlines and other parts into their respective slices. Errors are collected from all Parts and placed into the Envelopes Errors slice.
func ReadEnvelope ¶
ReadEnvelope is a wrapper around ReadParts and EnvelopeFromPart. It parses the content of the provided reader into an Envelope, downconverting HTML to plain text if needed, and sorting the attachments, inlines and other parts into their respective slices. Errors are collected from all Parts and placed into the Envelope.Errors slice. Uses default parser.
Example ¶
package main import ( "fmt" "os" "github.com/jhillyerd/enmime" ) func main() { // Open a sample message file. r, err := os.Open("testdata/mail/qp-utf8-header.raw") if err != nil { fmt.Print(err) return } // Parse message body with enmime. env, err := enmime.ReadEnvelope(r) if err != nil { fmt.Print(err) return } // Headers can be retrieved via Envelope.GetHeader(name). fmt.Printf("From: %v\n", env.GetHeader("From")) // Address-type headers can be parsed into a list of decoded mail.Address structs. alist, _ := env.AddressList("To") for _, addr := range alist { fmt.Printf("To: %s <%s>\n", addr.Name, addr.Address) } // enmime can decode quoted-printable headers. fmt.Printf("Subject: %v\n", env.GetHeader("Subject")) // The plain text body is available as mime.Text. fmt.Printf("Text Body: %v chars\n", len(env.Text)) // The HTML body is stored in mime.HTML. fmt.Printf("HTML Body: %v chars\n", len(env.HTML)) // mime.Inlines is a slice of inlined attacments. fmt.Printf("Inlines: %v\n", len(env.Inlines)) // mime.Attachments contains the non-inline attachments. fmt.Printf("Attachments: %v\n", len(env.Attachments)) }
Output: From: James Hillyerd <jamehi03@jamehi03lx.noa.com>, André Pirard <PIRARD@vm1.ulg.ac.be> To: Mirosław Marczak <marczak@inbucket.com> Subject: MIME UTF8 Test ¢ More Text Text Body: 1300 chars HTML Body: 1736 chars Inlines: 0 Attachments: 0
func (*Envelope) AddHeader ¶ added in v0.3.0
AddHeader appends given header value to header name without changing existing values. If the header does not exist already, it will be created.
func (*Envelope) AddressList ¶
AddressList returns a mail.Address slice with RFC 2047 encoded names converted to UTF-8
func (*Envelope) DeleteHeader ¶ added in v0.3.0
DeleteHeader deletes given header.
func (*Envelope) GetHeader ¶
GetHeader processes the specified header for RFC 2047 encoded words and returns the result as a UTF-8 string
func (*Envelope) GetHeaderKeys ¶ added in v0.3.0
GetHeaderKeys returns a list of header keys seen in this message. Get individual headers with `GetHeader(name)`
Example ¶
package main import ( "fmt" "os" "sort" "github.com/jhillyerd/enmime" ) func main() { // Open a sample message file. r, err := os.Open("testdata/mail/qp-utf8-header.raw") if err != nil { fmt.Print(err) return } // Parse message with enmime. env, err := enmime.ReadEnvelope(r) if err != nil { fmt.Print(err) return } // A list of headers is retrieved via Envelope.GetHeaderKeys(). headers := env.GetHeaderKeys() sort.Strings(headers) // Print each header, key and value. for _, header := range headers { fmt.Printf("%s: %v\n", header, env.GetHeader(header)) } }
Output: Content-Type: multipart/alternative; boundary="------------020203040006070307010003" Date: Fri, 19 Oct 2012 12:22:49 -0700 From: James Hillyerd <jamehi03@jamehi03lx.noa.com>, André Pirard <PIRARD@vm1.ulg.ac.be> Message-Id: <5081A889.3020108@jamehi03lx.noa.com> Mime-Version: 1.0 Sender: André Pirard <PIRARD@vm1.ulg.ac.be> Subject: MIME UTF8 Test ¢ More Text To: "Mirosław Marczak" <marczak@inbucket.com> User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:16.0) Gecko/20121010 Thunderbird/16.0.1
func (*Envelope) GetHeaderValues ¶ added in v0.3.0
GetHeaderValues processes the specified header for RFC 2047 encoded words and returns all existing values as a list of UTF-8 strings
type Error ¶
type Error struct { Name string // The name or type of error encountered, from Error consts. Detail string // Additional detail about the cause of the error, if available. Severe bool // Indicates that a portion of the message was lost during parsing. }
Error describes an error encountered while parsing.
type ErrorCollector ¶ added in v1.1.0
type ErrorCollector interface { AddError(name string, detailFmt string, args ...any) AddWarning(name string, detailFmt string, args ...any) }
ErrorCollector is an interface for collecting errors and warnings during parsing.
type MailBuilder ¶
type MailBuilder struct {
// contains filtered or unexported fields
}
MailBuilder facilitates the easy construction of a MIME message. Each manipulation method returns a copy of the receiver struct. It can be considered immutable if the caller does not modify the string and byte slices passed in. Immutability allows the headers or entire message to be reused across multiple threads.
func Builder ¶
func Builder() MailBuilder
Builder returns an empty MailBuilder struct.
Example ¶
ExampleBuilder illustrates how to build and send a MIME encoded message.
package main import ( "bytes" "fmt" "time" "github.com/jhillyerd/enmime" ) func main() { // Create an `SMTPSender` which relies on Go's built-in net/smtp package. Advanced users may // provide their own implementation of `Sender`, or mock it in unit tests. // For example: // // smtpHost := "smtp.relay.host:25" // smtpAuth := smtp.PlainAuth("", "user", "pw", "host") // sender := enmime.NewSMTP(smtpHost, smtpAuth) // Instead, we use a fake sender which prints to stdout: sender := &stdoutSender{} // MailBuilder is (mostly) immutable, each method below returns a new MailBuilder without // modifying the original. master := enmime.Builder(). From("Do Not Reply", "noreply@inbucket.org"). Subject("Inbucket Newsletter"). Text([]byte("Text body")). HTML([]byte("<p>HTML body</p>")) // Force stable output for testing; not needed in production. master = master.RandSeed(1).Date(time.Date(2024, 1, 1, 13, 14, 15, 16, time.UTC)) msg := master.To("Esteemed Customer", "user1@inbucket.org") err := msg.Send(sender) if err != nil { panic(err) } msg = master.To("Another Customer", "user2@inbucket.org") err = msg.Send(sender) if err != nil { panic(err) } } type stdoutSender struct{} func (s *stdoutSender) Send(from string, tos []string, msg []byte) error { fmt.Printf("MAIL FROM:<%v>\n", from) for _, to := range tos { fmt.Printf("RCPT TO:<%v>\n", to) } fmt.Println("DATA") lines := bytes.Split(msg, []byte{'\r'}) for _, line := range lines { line = bytes.Trim(line, "\r\n") fmt.Println(string(line)) } return nil }
Output: MAIL FROM:<noreply@inbucket.org> RCPT TO:<user1@inbucket.org> DATA Content-Type: multipart/alternative; boundary=enmime-52fdfc07-2182-454f-963f-5f0f9a621d72 Date: Mon, 01 Jan 2024 13:14:15 +0000 From: "Do Not Reply" <noreply@inbucket.org> Mime-Version: 1.0 Subject: Inbucket Newsletter To: "Esteemed Customer" <user1@inbucket.org> --enmime-52fdfc07-2182-454f-963f-5f0f9a621d72 Content-Type: text/plain; charset=utf-8 Text body --enmime-52fdfc07-2182-454f-963f-5f0f9a621d72 Content-Type: text/html; charset=utf-8 <p>HTML body</p> --enmime-52fdfc07-2182-454f-963f-5f0f9a621d72-- MAIL FROM:<noreply@inbucket.org> RCPT TO:<user2@inbucket.org> DATA Content-Type: multipart/alternative; boundary=enmime-037c4d7b-bb04-47d1-a2c6-4981855ad868 Date: Mon, 01 Jan 2024 13:14:15 +0000 From: "Do Not Reply" <noreply@inbucket.org> Mime-Version: 1.0 Subject: Inbucket Newsletter To: "Another Customer" <user2@inbucket.org> --enmime-037c4d7b-bb04-47d1-a2c6-4981855ad868 Content-Type: text/plain; charset=utf-8 Text body --enmime-037c4d7b-bb04-47d1-a2c6-4981855ad868 Content-Type: text/html; charset=utf-8 <p>HTML body</p> --enmime-037c4d7b-bb04-47d1-a2c6-4981855ad868--
func (MailBuilder) AddAttachment ¶
func (p MailBuilder) AddAttachment(b []byte, contentType string, fileName string) MailBuilder
AddAttachment returns a copy of MailBuilder that includes the specified attachment.
func (MailBuilder) AddAttachmentWithReader ¶ added in v1.0.1
func (p MailBuilder) AddAttachmentWithReader(r io.Reader, contentType string, fileName string) MailBuilder
AddAttachmentWithReader returns a copy of MailBuilder that includes the specified attachment, using an io.Reader to pull the content of the attachment.
func (MailBuilder) AddFileAttachment ¶
func (p MailBuilder) AddFileAttachment(path string) MailBuilder
AddFileAttachment returns a copy of MailBuilder that includes the specified attachment. fileName, will be populated from the base name of path. Content type will be detected from the path extension.
func (MailBuilder) AddFileInline ¶
func (p MailBuilder) AddFileInline(path string) MailBuilder
AddFileInline returns a copy of MailBuilder that includes the specified inline. fileName and contentID will be populated from the base name of path. Content type will be detected from the path extension.
func (MailBuilder) AddFileOtherPart ¶ added in v0.9.4
func (p MailBuilder) AddFileOtherPart(path string) MailBuilder
AddFileOtherPart returns a copy of MailBuilder that includes the specified other part. Filename and contentID will be populated from the base name of path. Content type will be detected from the path extension.
func (MailBuilder) AddInline ¶
func (p MailBuilder) AddInline( b []byte, contentType string, fileName string, contentID string, ) MailBuilder
AddInline returns a copy of MailBuilder that includes the specified inline. fileName and contentID may be left empty.
func (MailBuilder) AddOtherPart ¶ added in v0.9.4
func (p MailBuilder) AddOtherPart( b []byte, contentType string, fileName string, contentID string, ) MailBuilder
AddOtherPart returns a copy of MailBuilder that includes the specified embedded part. fileName may be left empty. It's useful when you want to embed image with CID.
func (MailBuilder) BCC ¶
func (p MailBuilder) BCC(name, addr string) MailBuilder
BCC returns a copy of MailBuilder with this name & address appended to the BCC list. name may be empty. This method only has an effect if the Send method is used to transmit the message, there is no effect on the parts returned by Build().
func (MailBuilder) BCCAddrs ¶
func (p MailBuilder) BCCAddrs(bcc []mail.Address) MailBuilder
BCCAddrs returns a copy of MailBuilder with the specified as the blind CC list. This method only has an effect if the Send method is used to transmit the message, there is no effect on the parts returned by Build().
func (MailBuilder) Build ¶
func (p MailBuilder) Build() (*Part, error)
Build performs some basic validations, then constructs a tree of Part structs from the configured MailBuilder. It will set the Date header to now if it was not explicitly set.
func (MailBuilder) CC ¶
func (p MailBuilder) CC(name, addr string) MailBuilder
CC returns a copy of MailBuilder with this name & address appended to the CC header. name may be empty.
func (MailBuilder) CCAddrs ¶
func (p MailBuilder) CCAddrs(cc []mail.Address) MailBuilder
CCAddrs returns a copy of MailBuilder with the specified CC addresses.
func (MailBuilder) Date ¶
func (p MailBuilder) Date(date time.Time) MailBuilder
Date returns a copy of MailBuilder with the specified Date header.
func (MailBuilder) Equals ¶
func (p MailBuilder) Equals(o MailBuilder) bool
Equals uses the reflect package to test two MailBuilder structs for equality, primarily for unit tests.
func (MailBuilder) Error ¶
func (p MailBuilder) Error() error
Error returns the stored error from a file attachment/inline read or nil.
func (MailBuilder) From ¶
func (p MailBuilder) From(name, addr string) MailBuilder
From returns a copy of MailBuilder with the specified From header.
func (*MailBuilder) GetBCC ¶ added in v0.10.1
func (p *MailBuilder) GetBCC() []mail.Address
GetBCC returns a copy of the stored bcc addresses.
func (*MailBuilder) GetCC ¶ added in v0.10.1
func (p *MailBuilder) GetCC() []mail.Address
GetCC returns a copy of the stored cc addresses.
func (*MailBuilder) GetDate ¶ added in v0.10.1
func (p *MailBuilder) GetDate() time.Time
GetDate returns the stored date.
func (*MailBuilder) GetFrom ¶ added in v0.10.1
func (p *MailBuilder) GetFrom() mail.Address
GetFrom returns the stored from header.
func (*MailBuilder) GetHTML ¶ added in v0.10.1
func (p *MailBuilder) GetHTML() []byte
GetHTML returns a copy of the stored text/html part.
func (*MailBuilder) GetHeader ¶ added in v0.10.1
func (p *MailBuilder) GetHeader(name string) string
GetHeader gets the first value associated with the given header.
func (*MailBuilder) GetReplyTo ¶ added in v0.10.1
func (p *MailBuilder) GetReplyTo() []mail.Address
GetReplyTo returns a copy of the stored replyTo header addresses.
func (*MailBuilder) GetSubject ¶ added in v0.10.1
func (p *MailBuilder) GetSubject() string
GetSubject returns the stored subject header.
func (*MailBuilder) GetText ¶ added in v0.10.1
func (p *MailBuilder) GetText() []byte
GetText returns a copy of the stored text/plain part.
func (*MailBuilder) GetTo ¶ added in v0.10.1
func (p *MailBuilder) GetTo() []mail.Address
GetTo returns a copy of the stored to addresses.
func (MailBuilder) HTML ¶
func (p MailBuilder) HTML(body []byte) MailBuilder
HTML returns a copy of MailBuilder that will use the provided bytes for its text/html Part.
func (MailBuilder) Header ¶
func (p MailBuilder) Header(name, value string) MailBuilder
Header returns a copy of MailBuilder with the specified value added to the named header.
func (MailBuilder) RandSeed ¶ added in v0.11.0
func (p MailBuilder) RandSeed(seed int64) MailBuilder
RandSeed sets the seed for random uuid boundary strings.
func (MailBuilder) ReplyTo ¶
func (p MailBuilder) ReplyTo(name, addr string) MailBuilder
ReplyTo returns a copy of MailBuilder with this name & address appended to the To header. name may be empty.
func (MailBuilder) ReplyToAddrs ¶ added in v1.0.0
func (p MailBuilder) ReplyToAddrs(replyTo []mail.Address) MailBuilder
ReplyToAddrs returns a copy of MailBuilder with the new reply to header list. This method only has an effect if the Send method is used to transmit the message, there is no effect on the parts returned by Build().
func (MailBuilder) Send ¶
func (p MailBuilder) Send(sender Sender) error
Send encodes the message and sends it via the specified Sender, using the address provided to `From()` as the reverse-path.
func (MailBuilder) SendWithReversePath ¶ added in v0.9.0
func (p MailBuilder) SendWithReversePath(sender Sender, from string) error
SendWithReversePath encodes the message and sends it via the specified Sender.
func (MailBuilder) Subject ¶
func (p MailBuilder) Subject(subject string) MailBuilder
Subject returns a copy of MailBuilder with the specified Subject header.
func (MailBuilder) Text ¶
func (p MailBuilder) Text(body []byte) MailBuilder
Text returns a copy of MailBuilder that will use the provided bytes for its text/plain Part.
func (MailBuilder) To ¶
func (p MailBuilder) To(name, addr string) MailBuilder
To returns a copy of MailBuilder with this name & address appended to the To header. name may be empty.
func (MailBuilder) ToAddrs ¶
func (p MailBuilder) ToAddrs(to []mail.Address) MailBuilder
ToAddrs returns a copy of MailBuilder with the specified To addresses.
type Option ¶ added in v0.10.0
type Option interface {
// contains filtered or unexported methods
}
Option to configure parsing.
func DisableCharacterDetection ¶ added in v1.3.0
DisableCharacterDetection sets the disableCharacterDetection option. When true, the parser will use the defined character set if it is defined in the message part.
func DisableTextConversion ¶ added in v1.3.0
DisableTextConversion sets the disableTextConversion option. When true, there will be no automated down conversion of HTML to text when a plain/text body is missing.
func MaxStoredPartErrors ¶ added in v0.11.0
MaxStoredPartErrors limits number of part parsing errors, errors beyond the limit are discarded. Zero, the default, means all errors will be kept.
func MultipartWOBoundaryAsSinglePart ¶ added in v0.10.0
MultipartWOBoundaryAsSinglePart if set to true will treat a multi-part messages without boundary parameter as single-part. Otherwise, will return error that boundary is not found.
func RawContent ¶ added in v1.1.0
RawContent if set to true will not try to decode the CTE and return the raw part content. Otherwise, will try to automatically decode the CTE.
func SetCustomParseMediaType ¶ added in v1.1.0
func SetCustomParseMediaType(customParseMediaType CustomParseMediaType) Option
SetCustomParseMediaType if provided, will be used to parse media type instead of the default ParseMediaType function. This may be used to parse media type parameters that would otherwise be considered malformed. By default parsing happens using ParseMediaType
Example ¶
// for the sake of simplicity replaces space in a very specific invalid content-type: "application/Pamir Viewer" replaceSpecificContentType := func(ctype string) (mtype string, params map[string]string, invalidParams []string, err error) { modifiedStr := strings.ReplaceAll(ctype, "application/Pamir Viewer", "application/PamirViewer") return ParseMediaType(modifiedStr) } invalidMessageContent := `From: <enmime@parser.git> Content-Type: multipart/mixed; boundary="----=_NextPart_000_000F_01D9FAC6.09EB3B60" ------=_NextPart_000_000F_01D9FAC6.09EB3B60 Content-Type: application/Pamir Viewer; name="2023-10-13.pmrv" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="2023-10-13.pmrv" f6En7vFpNql3tfMkoKABP1iBEf+M/qF6LCAIvyRbpH6uDCqcKKGmH3e6OiqN5eCfqUk= ` p := NewParser(SetCustomParseMediaType(replaceSpecificContentType)) e, err := p.ReadEnvelope(strings.NewReader(invalidMessageContent)) fmt.Println(err) fmt.Println(len(e.Attachments)) fmt.Println(e.Attachments[0].ContentType) fmt.Println(e.Attachments[0].FileName)
Output: <nil> 1 application/pamirviewer 2023-10-13.pmrv
func SetReadPartErrorPolicy ¶ added in v0.10.1
func SetReadPartErrorPolicy(f ReadPartErrorPolicy) Option
SetReadPartErrorPolicy sets the given callback function to readPartErrorPolicy.
func SkipMalformedParts ¶ added in v0.10.0
SkipMalformedParts sets parsing to skip parts that's can't be parsed.
func StripMediaTypeInvalidCharacters ¶ added in v1.2.0
StripMediaTypeInvalidCharacters sets stripMediaTypeInvalidCharacters option. If true, invalid characters will be removed from media type during parsing.
type Parser ¶ added in v0.10.0
type Parser struct {
// contains filtered or unexported fields
}
Parser parses MIME. Default parser is a valid one.
func (Parser) EnvelopeFromPart ¶ added in v0.10.0
EnvelopeFromPart is the same as EnvelopeFromPart, but respects parser configurations.
func (Parser) ReadEnvelope ¶ added in v0.10.0
ReadEnvelope is the same as ReadEnvelope, but respects parser configurations.
type Part ¶
type Part struct { PartID string // PartID labels this part's position within the tree. Parent *Part // Parent of this part (can be nil.) FirstChild *Part // FirstChild is the top most child of this part. NextSibling *Part // NextSibling of this part. Header textproto.MIMEHeader // Header for this part. Boundary string // Boundary marker used within this part. ContentID string // ContentID header for cid URL scheme. ContentType string // ContentType header without parameters. ContentTypeParams map[string]string // Params, added to ContentType header. Disposition string // Content-Disposition header without parameters. FileName string // The file-name from disposition or type header. FileModDate time.Time // The modification date of the file. Charset string // The content charset encoding, may differ from charset in header. OrigCharset string // The original content charset when a different charset was detected. Errors []*Error // Errors encountered while parsing this part. Content []byte // Content after decoding, UTF-8 conversion if applicable. ContentReader io.Reader // Reader interface for pulling the content for encoding. Epilogue []byte // Epilogue contains data following the closing boundary marker. // contains filtered or unexported fields }
Part represents a node in the MIME multipart tree. The Content-Type, Disposition and File Name are parsed out of the header for easier access.
func ReadParts ¶
ReadParts reads a MIME document from the provided reader and parses it into tree of Part objects.
func (*Part) AddChild ¶
AddChild adds a child part to either FirstChild or the end of the children NextSibling chain. The child may have siblings and children attached. This method will set the Parent field on child and all its siblings. Safe to call on nil.
func (*Part) BreadthMatchAll ¶
func (p *Part) BreadthMatchAll(matcher PartMatcher) []*Part
BreadthMatchAll performs a breadth first search of the Part tree and returns all parts that cause the given matcher to return true
func (*Part) BreadthMatchFirst ¶
func (p *Part) BreadthMatchFirst(matcher PartMatcher) *Part
BreadthMatchFirst performs a breadth first search of the Part tree and returns the first part that causes the given matcher to return true
func (*Part) DepthMatchAll ¶
func (p *Part) DepthMatchAll(matcher PartMatcher) []*Part
DepthMatchAll performs a depth first search of the Part tree and returns all parts that causes the given matcher to return true
func (*Part) DepthMatchFirst ¶
func (p *Part) DepthMatchFirst(matcher PartMatcher) *Part
DepthMatchFirst performs a depth first search of the Part tree and returns the first part that causes the given matcher to return true
func (*Part) Encode ¶
Encode writes this Part and all its children to the specified writer in MIME format.
func (*Part) TextContent ¶
TextContent indicates whether the content is text based on its content type. This value determines what content transfer encoding scheme to use.
type PartMatcher ¶
PartMatcher is a function type that you must implement to search for Parts using the BreadthMatch* functions. Implementators should inspect the provided Part and return true if it matches your criteria.
type ReadPartErrorPolicy ¶ added in v0.10.1
ReadPartErrorPolicy allows to recover the buffer (or not) on an error when reading a Part content.
See AllowCorruptTextPartErrorPolicy for usage.
type SMTPSender ¶ added in v0.9.0
type SMTPSender struct {
// contains filtered or unexported fields
}
SMTPSender is a Sender backed by Go's built-in net/smtp.SendMail function.
type Sender ¶ added in v0.9.0
type Sender interface { // Sends the provided msg to the specified recipients, providing the specified reverse-path to // the mail server to use for delivery error reporting. // // The message headers should usually include fields such as "From", "To", "Subject", and "Cc". // Sending "Bcc" messages is accomplished by including an email address in the recipients // parameter but not including it in the message headers. Send(reversePath string, recipients []string, msg []byte) error }
Sender provides a method for enmime to send an email.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
mime-dump
Package main outputs a markdown formatted document describing the provided email
|
Package main outputs a markdown formatted document describing the provided email |
mime-extractor
Package main extracts attachments from the provided email
|
Package main extracts attachments from the provided email |
Package dsn meant to work with Delivery Status Notification (DSN) per rfc3464: https://datatracker.ietf.org/doc/html/rfc3464
|
Package dsn meant to work with Delivery Status Notification (DSN) per rfc3464: https://datatracker.ietf.org/doc/html/rfc3464 |
internal
|
|
textproto
Package textproto implements generic support for text-based request/response protocols in the style of HTTP, NNTP, and SMTP.
|
Package textproto implements generic support for text-based request/response protocols in the style of HTTP, NNTP, and SMTP. |