func (e *Envelope) NewReader() io.Reader {
	return io.MultiReader(
		strings.NewReader(e.DeliveryHeader),
		bytes.NewReader(e.Data.Bytes()),
	)
}
NewReader returns a new reader for reading the email contents, including the delivery headers
package mail
import (
	"bufio"
	"bytes"
	"crypto/md5"
	"errors"
	"fmt"
	"io"
	"mime"
	"net"
	"net/textproto"
	"strings"
	"sync"
	"time"
	"github.com/flashmob/go-guerrilla/mail/rfc5321"
)
var Dec mime.WordDecoder
func init() {
	Dec = mime.WordDecoder{}
}
const maxHeaderChunk = 1 + (4 << 10)  
type Address struct {
	User string
	Host string
	ADL []string
	PathParams [][]string
	NullPath bool
	Quoted bool
	IP net.IP
	DisplayName string
	DisplayNameQuoted bool
}
func (a *Address) String() string {
	var local string
	if a.IsEmpty() {
		return ""
	}
	if a.User == "postmaster" && a.Host == "" {
		return "postmaster"
	}
	if a.Quoted {
		var sb bytes.Buffer
		sb.WriteByte('"')
		for i := 0; i < len(a.User); i++ {
			if a.User[i] == '\\' || a.User[i] == '"' {
				sb.WriteByte('\\')
			}
			sb.WriteByte(a.User[i])
		}
		sb.WriteByte('"')
		local = sb.String()
	} else {
		local = a.User
	}
	if a.Host != "" {
		if a.IP != nil {
			return fmt.Sprintf("%s@[%s]", local, a.Host)
		}
		return fmt.Sprintf("%s@%s", local, a.Host)
	}
	return local
}
func (a *Address) IsEmpty() bool {
	return a.User == "" && a.Host == ""
}
func (a *Address) IsPostmaster() bool {
	if a.User == "postmaster" {
		return true
	}
	return false
}
func NewAddress(str string) (*Address, error) {
	var ap rfc5321.RFC5322
	l, err := ap.Address([]byte(str))
	if err != nil {
		return nil, err
	}
	if len(l.List) == 0 {
		return nil, errors.New("no email address matched")
	}
	a := new(Address)
	addr := &l.List[0]
	a.User = addr.LocalPart
	a.Quoted = addr.LocalPartQuoted
	a.Host = addr.Domain
	a.IP = addr.IP
	a.DisplayName = addr.DisplayName
	a.DisplayNameQuoted = addr.DisplayNameQuoted
	a.NullPath = addr.NullPath
	return a, nil
}
type Envelope struct {
	RemoteIP string
	Helo string
	MailFrom Address
	RcptTo []Address
	Data bytes.Buffer
	Subject string
	TLS bool
	Header textproto.MIMEHeader
	Values map[string]interface{}
	Hashes []string
	DeliveryHeader string
	QueuedId string
	ESMTP bool
	sync.Mutex
}
func NewEnvelope(remoteAddr string, clientID uint64) *Envelope {
	return &Envelope{
		RemoteIP: remoteAddr,
		Values:   make(map[string]interface{}),
		QueuedId: queuedID(clientID),
	}
}
func queuedID(clientID uint64) string {
	return fmt.Sprintf("%x", md5.Sum([]byte(string(time.Now().Unix())+string(clientID))))
}
func (e *Envelope) ParseHeaders() error {
	var err error
	if e.Header != nil {
		return errors.New("headers already parsed")
	}
	buf := e.Data.Bytes()
	if len(buf) > maxHeaderChunk {
		buf = buf[:maxHeaderChunk]
	}
	headerEnd := bytes.Index(buf, []byte{'\n', '\n'})  
	if headerEnd > -1 {
		header := buf[0 : headerEnd+2]
		headerReader := textproto.NewReader(bufio.NewReader(bytes.NewBuffer(header)))
		e.Header, err = headerReader.ReadMIMEHeader()
		if err == nil || err == io.EOF {
			if subject, ok := e.Header["Subject"]; ok {
				e.Subject = MimeHeaderDecode(subject[0])
			}
		}
	} else {
		err = errors.New("header not found")
	}
	return err
}
func (e *Envelope) Len() int {
	return len(e.DeliveryHeader) + e.Data.Len()
}