1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2025-12-20 02:57:05 +00:00

Basic MIME parsing is now integrated, this closes #1

This commit is contained in:
James Hillyerd
2012-10-17 21:10:02 -07:00
parent e76fad1523
commit 0efb28ef38
4 changed files with 68 additions and 52 deletions

View File

@@ -5,6 +5,7 @@ import (
"container/list"
"fmt"
"io"
"io/ioutil"
"mime"
"mime/multipart"
"net/mail"
@@ -20,7 +21,7 @@ type MIMENode struct {
Content []byte
}
type MIMEMessage struct {
type MIMEBody struct {
Text string
Html string
Root *MIMENode
@@ -79,50 +80,59 @@ func IsMIMEMessage(mailMsg *mail.Message) bool {
return false
}
func ParseMIMEMessage(mailMsg *mail.Message) (*MIMEMessage, error) {
mimeMsg := new(MIMEMessage)
func ParseMIMEBody(mailMsg *mail.Message) (*MIMEBody, error) {
mimeMsg := new(MIMEBody)
// Parse top-level multipart
ctype := mailMsg.Header.Get("Content-Type")
mediatype, params, err := mime.ParseMediaType(ctype)
if err != nil {
return nil, err
}
switch mediatype {
case "multipart/alternative":
// Good
default:
return nil, fmt.Errorf("Unknown mediatype: %v", mediatype)
}
boundary := params["boundary"]
if boundary == "" {
return nil, fmt.Errorf("Unable to locate boundary param in Content-Type header")
if !IsMIMEMessage(mailMsg) {
// Parse as text only
bodyBytes, err := ioutil.ReadAll(mailMsg.Body)
if err != nil {
return nil, err
}
mimeMsg.Text = string(bodyBytes)
} else {
// Parse top-level multipart
ctype := mailMsg.Header.Get("Content-Type")
mediatype, params, err := mime.ParseMediaType(ctype)
if err != nil {
return nil, err
}
switch mediatype {
case "multipart/alternative":
// Good
default:
return nil, fmt.Errorf("Unknown mediatype: %v", mediatype)
}
boundary := params["boundary"]
if boundary == "" {
return nil, fmt.Errorf("Unable to locate boundary param in Content-Type header")
}
// Root Node of our tree
root := NewMIMENode(nil, mediatype)
err = parseNodes(root, mailMsg.Body, boundary)
// 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)
}
}
// Root Node of our tree
root := NewMIMENode(nil, mediatype)
err = parseNodes(root, mailMsg.Body, boundary)
// 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)
}
return mimeMsg, err
return mimeMsg, nil
}
func (m *MIMEMessage) String() string {
func (m *MIMEBody) String() string {
return fmt.Sprintf("----TEXT----\n%v\n----HTML----\n%v\n----END----\n", m.Text, m.Html)
}