Skip to content

Commit

Permalink
Add another doc example, cleanups for #15
Browse files Browse the repository at this point in the history
  • Loading branch information
jhillyerd committed Dec 18, 2016
1 parent 4e572b7 commit 95c1169
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 6 deletions.
11 changes: 6 additions & 5 deletions envelope.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,10 @@ func (e *Envelope) AddressList(key string) ([]*mail.Address, error) {
return ret, nil
}

// ReadEnvelope 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.
// 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.
func ReadEnvelope(r io.Reader) (*Envelope, error) {
// Read MIME parts from reader
root, err := ReadParts(r)
Expand All @@ -67,9 +68,9 @@ func ReadEnvelope(r io.Reader) (*Envelope, error) {
return EnvelopeFromPart(root)
}

// EnvelopeFromPart uses the provided Part tree to build an Envelope,, downconverting HTML to plain
// 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.
// slices. Errors are collected from all Parts and placed into the Envelopes Errors slice.
func EnvelopeFromPart(root *Part) (*Envelope, error) {
e := &Envelope{
Root: root,
Expand Down
105 changes: 104 additions & 1 deletion example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package enmime_test

import (
"fmt"
"io/ioutil"
"os"
"strings"

"github.com/jhillyerd/enmime"
)

func Example() {
func ExampleReadEnvelope() {
// Open a sample message file
r, err := os.Open("testdata/mail/qp-utf8-header.raw")
if err != nil {
Expand Down Expand Up @@ -55,3 +57,104 @@ func Example() {
// Inlines: 0
// Attachments: 0
}

// ExampleEnvelope demonstrates the relationship between Envelope and Parts.
func ExampleEnvelope() {
// 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 is available to be read.
content, _ := ioutil.ReadAll(part3)
fmt.Printf("Part 3 Content: %q\n", content)

// part3 contained a malformed header line, enmime has attached an Error to it
p3error := part3.Errors[0]
fmt.Println(p3error.String())
fmt.Println()

// All Part errors are collected and placed into Envelope.Errors
fmt.Println("Envelope errors:")
for _, e := range env.Errors {
fmt.Println(e.String())
}

// 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
}

0 comments on commit 95c1169

Please sign in to comment.