1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 |
- package mail
- import (
- "bufio"
- "io"
- "net/textproto"
- "github.com/flashmob/go-guerrilla/mail/mimeparse"
- )
- // MimeDotReader parses the mime structure while reading using the underlying reader
- type MimeDotReader struct {
- R io.Reader
- p *mimeparse.Parser
- mimeErr error
- }
- // Read parses the mime structure wile reading. Results are immediately available in
- // the data-structure returned from Parts() after each read.
- func (r *MimeDotReader) Read(p []byte) (n int, err error) {
- n, err = r.R.Read(p)
- if n > 0 {
- if r.mimeErr == nil {
- r.mimeErr = r.p.Parse(p)
- }
- }
- return
- }
- // Close closes the underlying reader if it's a ReadCloser and closes the mime parser
- func (r MimeDotReader) Close() (err error) {
- defer func() {
- if err == nil && r.mimeErr != nil {
- err = r.mimeErr
- }
- }()
- if rc, t := r.R.(io.ReadCloser); t {
- err = rc.Close()
- }
- // parser already closed?
- if r.mimeErr != nil {
- return
- }
- // close the parser
- r.mimeErr = r.p.Close()
- return
- }
- // Parts returns the mime-header parts built by the parser
- func (r *MimeDotReader) Parts() mimeparse.Parts {
- return r.p.Parts
- }
- // Returns the underlying io.Reader (which is a dotReader from textproto)
- // useful for reading from directly if mime parsing is not desirable.
- func (r *MimeDotReader) DotReader() io.Reader {
- return r.R
- }
- // NewMimeDotReader returns a pointer to a new MimeDotReader
- // br is the underlying reader it will read from
- // maxNodes limits the number of nodes can be added to the mime tree before the mime-parser aborts
- func NewMimeDotReader(br *bufio.Reader, maxNodes int) *MimeDotReader {
- r := new(MimeDotReader)
- r.R = textproto.NewReader(br).DotReader()
- if maxNodes > 0 {
- r.p = mimeparse.NewMimeParserLimited(maxNodes)
- } else {
- r.p = mimeparse.NewMimeParser()
- }
- r.p.Open()
- return r
- }
|