"mime"
"net/textproto"
"os"
- "regexp"
)
// TODO(bradfitz): inline these once the compiler can inline them in
var lf = []byte("\n")
var crlf = []byte("\r\n")
-var headerRegexp *regexp.Regexp = regexp.MustCompile("^([a-zA-Z0-9\\-]+): *([^\r\n]+)")
-
var emptyParams = make(map[string]string)
// A Part represents a single part in a multipart body.
}
func (bp *Part) populateHeaders() os.Error {
- for {
- lineBytes, err := bp.mr.bufReader.ReadSlice('\n')
- if err != nil {
- return err
- }
- line := string(lineBytes)
- if line == "\n" || line == "\r\n" {
- return nil
- }
- if matches := headerRegexp.FindStringSubmatch(line); len(matches) == 3 {
- bp.Header.Add(matches[1], matches[2])
- continue
- }
- return os.NewError("Unexpected header line found parsing multipart body")
+ r := textproto.NewReader(bp.mr.bufReader)
+ header, err := r.ReadMIMEHeader()
+ if err == nil {
+ bp.Header = header
}
- panic("unreachable")
+ return err
}
// Read reads the body of a part, after its headers and before the
}
return s.r.Read(p[:1])
}
+
+func TestLineContinuation(t *testing.T) {
+ // This body, extracted from an email, contains headers that span multiple
+ // lines.
+
+ // TODO: The original mail ended with a double-newline before the
+ // final delimiter; this was manually edited to use a CRLF.
+ testBody :=
+ "\n--Apple-Mail-2-292336769\nContent-Transfer-Encoding: 7bit\nContent-Type: text/plain;\n\tcharset=US-ASCII;\n\tdelsp=yes;\n\tformat=flowed\n\nI'm finding the same thing happening on my system (10.4.1).\n\n\n--Apple-Mail-2-292336769\nContent-Transfer-Encoding: quoted-printable\nContent-Type: text/html;\n\tcharset=ISO-8859-1\n\n<HTML><BODY>I'm finding the same thing =\nhappening on my system (10.4.1).=A0 But I built it with XCode =\n2.0.</BODY></=\nHTML>=\n\r\n--Apple-Mail-2-292336769--\n"
+
+ r := NewReader(strings.NewReader(testBody), "Apple-Mail-2-292336769")
+
+ for i := 0; i < 2; i++ {
+ part, err := r.NextPart()
+ if err != nil {
+ t.Fatalf("didn't get a part")
+ }
+ n, err := io.Copy(ioutil.Discard, part)
+ if err != nil {
+ t.Errorf("error reading part: %v", err)
+ }
+ if n <= 0 {
+ t.Errorf("read %d bytes; expected >0", n)
+ }
+ }
+}