mirror of
https://github.com/jhillyerd/inbucket.git
synced 2025-12-22 12:07:04 +00:00
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.
This commit is contained in:
81
app/inbucket/mime.go
Normal file
81
app/inbucket/mime.go
Normal file
@@ -0,0 +1,81 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user