1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2025-12-17 09:37:02 +00:00

More MIME parsing progress!

After parsing MIME into a tree of nodes, we can now issue
BreadthFirstSearch commands against it to locate the text and HTML
portions of the email.
This commit is contained in:
James Hillyerd
2012-10-15 22:56:45 -07:00
parent a2070dd60a
commit bc7526abef

View File

@@ -2,33 +2,56 @@ package inbucket
import (
"bytes"
"container/list"
"fmt"
"io"
"mime"
"mime/multipart"
"net/mail"
"os"
)
const MIME_BUF_BYTES = 1024
type MIMEMessage struct {
text string
html string
}
type MIMENodeMatcher func(node *MIMENode) bool
type MIMENode struct {
Parent *MIMENode
FirstChild *MIMENode
NextSibling *MIMENode
Type string
Content *bytes.Buffer
Content []byte
}
type MIMEMessage struct {
Text string
Html string
Root *MIMENode
}
func NewMIMENode(parent *MIMENode, contentType string) *MIMENode {
return &MIMENode{Parent: parent, Type: contentType}
}
func (n *MIMENode) BreadthFirstSearch(matcher MIMENodeMatcher) *MIMENode {
q := list.New()
q.PushBack(n)
// Push children onto queue and attempt to match in that order
for q.Len() > 0 {
e := q.Front()
n := e.Value.(*MIMENode)
if matcher(n) {
return n
}
q.Remove(e)
c := n.FirstChild
for c != nil {
q.PushBack(c)
c = c.NextSibling
}
}
return nil
}
func (n *MIMENode) String() string {
children := ""
siblings := ""
@@ -66,9 +89,32 @@ func ParseMIMEMessage(mailMsg *mail.Message) (*MIMEMessage, error) {
err = parseNodes(root, mailMsg.Body, boundary)
fmt.Println(root.String())
// Locate text body
match := root.BreadthFirstSearch(func(node *MIMENode) bool {
return node.Type == "text/plain"
})
if match != nil {
mimeMsg.Text = string(match.Content)
}
// Locate HTML body
match = root.BreadthFirstSearch(func(node *MIMENode) bool {
return node.Type == "text/html"
})
if match != nil {
mimeMsg.Html = string(match.Content)
}
fmt.Println(mimeMsg.String())
return mimeMsg, err
}
func (m *MIMEMessage) String() string {
return fmt.Sprintf("----TEXT----\n%v\n----HTML----\n%v\n----END----\n", m.Text, m.Html)
}
func parseNodes(parent *MIMENode, reader io.Reader, boundary string) error {
var prevSibling *MIMENode
@@ -106,14 +152,12 @@ func parseNodes(parent *MIMENode, reader io.Reader, boundary string) error {
}
} else {
// Content is data, allocate a buffer
node.Content = new(bytes.Buffer)
_, err = io.Copy(node.Content, part)
buf := new(bytes.Buffer)
_, err = buf.ReadFrom(part)
if err != nil {
return err
}
fmt.Printf("\n----\n")
io.Copy(os.Stdout, node.Content)
fmt.Printf("\n----\n")
node.Content = buf.Bytes()
}
}