mirror of
https://github.com/jhillyerd/inbucket.git
synced 2025-12-18 01:57:02 +00:00
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.
82 lines
1.7 KiB
Go
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
|
|
}
|