Browse Source

stringify ContentType fully.
More comments.

flashmob 6 years ago
parent
commit
e57359f646
2 changed files with 39 additions and 10 deletions
  1. 2 1
      api_test.go
  2. 37 9
      mail/mime/mime.go

+ 2 - 1
api_test.go

@@ -781,7 +781,8 @@ func TestStreamProcessor(t *testing.T) {
 
 
 var mime = `MIME-Version: 1.0
 var mime = `MIME-Version: 1.0
 X-Mailer: MailBee.NET 8.0.4.428
 X-Mailer: MailBee.NET 8.0.4.428
-Subject: test subject
+Subject: test 
+ subject
 To: [email protected]
 To: [email protected]
 Content-Type: multipart/mixed;
 Content-Type: multipart/mixed;
        boundary="XXXXboundary text"
        boundary="XXXXboundary text"

+ 37 - 9
mail/mime/mime.go

@@ -104,6 +104,7 @@ type contentType struct {
 	superType  string
 	superType  string
 	subType    string
 	subType    string
 	parameters map[string]string
 	parameters map[string]string
+	b          bytes.Buffer
 }
 }
 
 
 type parserMsg struct {
 type parserMsg struct {
@@ -128,8 +129,24 @@ var isTokenSpecial = [128]bool{
 	'=':  true,
 	'=':  true,
 }
 }
 
 
-func (c *contentType) String() string {
-	return fmt.Sprintf("%s/%s", c.superType, c.subType)
+func (c *contentType) params() (ret string) {
+	defer func() {
+		c.b.Reset()
+	}()
+	sp := ""
+	for k, v := range c.parameters {
+		c.b.WriteString(k + "=\"" + v + "\"" + sp)
+		if len(c.parameters) > 1 && sp == "" {
+			sp = " "
+		}
+	}
+	return c.b.String()
+}
+
+func (c *contentType) String() (ret string) {
+	ret = fmt.Sprintf("%s/%s %s", c.superType, c.subType,
+		c.params())
+	return
 }
 }
 
 
 func newPart() *Part {
 func newPart() *Part {
@@ -210,6 +227,12 @@ func (p *Parser) inject(input ...[]byte) {
 	}()
 	}()
 }
 }
 
 
+// Set the buffer and reset p.pos to startPos, which is typically -1
+// The reason why -1 is because peek() implementation becomes more
+// simple, as it only needs to add 1 to p.pos for all cases.
+// We don't read the buffer when we set, only when next() is called.
+// This allows us to peek in to the next buffer while still being on
+// the last element from the previous buffer
 func (p *Parser) set(input []byte) {
 func (p *Parser) set(input []byte) {
 	if p.pos != startPos {
 	if p.pos != startPos {
 		// rewind
 		// rewind
@@ -218,6 +241,8 @@ func (p *Parser) set(input []byte) {
 	p.buf = input
 	p.buf = input
 }
 }
 
 
+// skip advances the pointer n bytes. It will block if not enough bytes left in
+// the buffer, i.e. if bBytes > len(p.buf) - p.pos
 func (p *Parser) skip(nBytes int) {
 func (p *Parser) skip(nBytes int) {
 
 
 	for i := 0; i < nBytes; i++ {
 	for i := 0; i < nBytes; i++ {
@@ -832,13 +857,14 @@ func (p *Parser) Close() error {
 
 
 // Parse takes a byte stream, and feeds it to the MIME Parser, then
 // Parse takes a byte stream, and feeds it to the MIME Parser, then
 // waits for the Parser to consume all input before returning.
 // waits for the Parser to consume all input before returning.
-// The Parser will build a parse tree in p.Parts
-// The reader doesn't decode any input. All it does
+// The parser will build a parse tree in p.Parts
+// The parser doesn't decode any input. All it does
 // is collect information about where the different MIME parts
 // is collect information about where the different MIME parts
 // start and end, and other meta-data. This data can be used
 // start and end, and other meta-data. This data can be used
-// by others later to determine how to store/display
+// later down the stack to determine how to store/display
 // the messages
 // the messages
-// returns error if there's a parse error
+// returns error if there's a parse error, except io.EOF when no
+// error occurred.
 func (p *Parser) Parse(buf []byte) error {
 func (p *Parser) Parse(buf []byte) error {
 	defer func() {
 	defer func() {
 		p.count++
 		p.count++
@@ -846,11 +872,12 @@ func (p *Parser) Parse(buf []byte) error {
 	}()
 	}()
 	p.Lock()
 	p.Lock()
 
 
+	// Feed the new slice. Assumes that the parser is blocked now, waiting
+	// for new data, or not started yet.
 	p.set(buf)
 	p.set(buf)
 
 
 	if p.count == 0 {
 	if p.count == 0 {
-		//open
-
+		// initial step - start the mime parser
 		go func() {
 		go func() {
 			p.next()
 			p.next()
 			err := p.mime(nil, "")
 			err := p.mime(nil, "")
@@ -858,6 +885,7 @@ func (p *Parser) Parse(buf []byte) error {
 			p.result <- parserMsg{err}
 			p.result <- parserMsg{err}
 		}()
 		}()
 	} else {
 	} else {
+		// tell the parser to resume consuming
 		p.gotNewSlice <- true
 		p.gotNewSlice <- true
 	}
 	}
 
 
@@ -865,7 +893,7 @@ func (p *Parser) Parse(buf []byte) error {
 	case <-p.consumed: // wait for prev buf to be consumed
 	case <-p.consumed: // wait for prev buf to be consumed
 		return nil
 		return nil
 	case r := <-p.result:
 	case r := <-p.result:
-		// mime() has returned with a result
+		// mime() has returned with a result (it finished consuming)
 		p.reset()
 		p.reset()
 		return r.err
 		return r.err
 	}
 	}