1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2025-12-18 01:57:02 +00:00
Files
go-inbucket/app/inbucket/mime.go
James Hillyerd 46b123606b Started work on MIME parser
I'm hoping to mostly rely on the official mime and mime/multipart
packages, but Inbucket is still going to have to decided what to
do with the various parts it reads.
2012-10-14 23:11:39 -07:00

82 lines
1.7 KiB
Go

package inbucket
import (
"bytes"
"fmt"
"io"
"mime"
"mime/multipart"
"net/mail"
)
const MIME_BUF_BYTES = 1024
type MIMEMessage struct {
text string
html string
}
func ParseMIMEMessage(mailMsg *mail.Message) (*MIMEMessage, error) {
mimeMsg := new(MIMEMessage)
// 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")
}
// Buffer used by Part.Read to hand us chunks of data
readBytes := make([]byte, MIME_BUF_BYTES)
// Loop over MIME parts
mr := multipart.NewReader(mailMsg.Body, boundary)
for {
part, err := mr.NextPart()
if err != nil {
if err == io.EOF {
// This is a clean end-of-message signal
break
}
return nil, err
}
mediatype, params, err = mime.ParseMediaType(part.Header.Get("Content-Type"))
if err != nil {
return nil, err
}
if mediatype == "text/plain" && mimeMsg.text == "" {
// First text section, we'll have that, but first we have to deal with
// the odd way Part lets us read data.
var buf bytes.Buffer
for {
n, err := part.Read(readBytes)
if err != nil {
if err == io.EOF {
// Clean end of part signal
break
}
return nil, err
}
// Extra data in readBytes is not cleared, so we must respect
// the value returned in 'n'
buf.Write(readBytes[:n])
}
mimeMsg.text = buf.String()
fmt.Printf("text: '%v'\n", mimeMsg.text)
}
}
return mimeMsg, nil
}