func DecodeFromMime(m string) (*MimeMessage, error) {
	// Make sure it's using CRLF to be fully MIME compliant
	m = strings.Replace(m, "\r\n", "\n", -1)
	m = strings.Replace(m, "\n", "\r\n", -1)

	mDecodedMsg := &MimeMessage{}

	msg, err := mail.ReadMessage(bytes.NewBufferString(m))
	if err != nil {
		return mDecodedMsg, err
	}

	mDecodedMsg.To, _ = (&mail.AddressParser{}).ParseList(msg.Header.Get("To"))
	mDecodedMsg.From, _ = (&mail.AddressParser{}).Parse(msg.Header.Get("From"))
	mDecodedMsg.Subject = msg.Header.Get("Subject")
	mDecodedMsg.Date, _ = msg.Header.Date()
	mDecodedMsg.ID = msg.Header.Get("Message-Id")

	var mimeParts string
	var hasDefaultBlock bool
	mDecodedMsg.Attachments = make(map[string][]byte)

	for name, values := range msg.Header {
		if !strings.HasPrefix(name, "Content") {
			continue
		}
		for _, val := range values {
			mimeParts = fmt.Sprintf("%s%s: %s\r\n", mimeParts, name, decodeRFC2047(val))
		}
	}

	mediaType, params, err := mime.ParseMediaType(msg.Header.Get("Content-Type"))
	if err != nil {
		log.Fatal(err)
	}

	if strings.HasPrefix(mediaType, "multipart/") {
		mimeParts, mDecodedMsg.Blocks, mDecodedMsg.Attachments, err = readParts(mimeParts, mDecodedMsg.Blocks, mDecodedMsg.Attachments, msg.Body, params["boundary"], 0)
	} else {
		mimeParts = fmt.Sprintf("%sX-Bitmaelum-Block: default", mimeParts)
		body, err := ioutil.ReadAll(msg.Body)
		if err != nil {
			return mDecodedMsg, err
		}

		hasDefaultBlock = true
		mDecodedMsg.Blocks = append(mDecodedMsg.Blocks, "default,"+string(body))
	}

	// If there is no default block then set the first "text/plain" as default
	if !hasDefaultBlock {
		if err := renameBlock("text/plain", "default", &mDecodedMsg.Blocks); err == nil {
			hasDefaultBlock = true
			mimeParts = strings.Replace(mimeParts, "text/plain", "default", 1)
		}
	}

	// If no "text/plain" is found then set the first "text/html" as default
	if !hasDefaultBlock {
		if err := renameBlock("text/html", "default", &mDecodedMsg.Blocks); err == nil {
			hasDefaultBlock = true
			mimeParts = strings.Replace(mimeParts, "text/html", "default", 1)
		}
	}

	// It no "text/html" and not "text/plain" are found then set the first block as default
	if !hasDefaultBlock {
		parts := strings.SplitN(mDecodedMsg.Blocks[0], ",", 2)
		mimeParts = strings.Replace(mimeParts, parts[0], "default", 1)
		mDecodedMsg.Blocks[0] = "default," + parts[1]
	}

	mDecodedMsg.Blocks = append(mDecodedMsg.Blocks, "mimeparts,"+mimeParts)

	return mDecodedMsg, err
}
// DecodeFromMime will decode a mime message and return a MimeMessage struct
DecodeFromMime will decode a mime message and return a MimeMessage struct
// DecodeFromMime will decode a mime message and return a MimeMessage struct
func DecodeFromMime(m string) (*MimeMessage, error) {
	m = strings.Replace(m, "\r\n", "\n", -1)
	m = strings.Replace(m, "\n", "\r\n", -1)
	mDecodedMsg := &MimeMessage{}
	msg, err := mail.ReadMessage(bytes.NewBufferString(m))
	if err != nil {
		return mDecodedMsg, err
	}
	mDecodedMsg.To, _ = (&mail.AddressParser{}).ParseList(msg.Header.Get("To"))
	mDecodedMsg.From, _ = (&mail.AddressParser{}).Parse(msg.Header.Get("From"))
	mDecodedMsg.Subject = msg.Header.Get("Subject")
	mDecodedMsg.Date, _ = msg.Header.Date()
	mDecodedMsg.ID = msg.Header.Get("Message-Id")
	var mimeParts string
	var hasDefaultBlock bool
	mDecodedMsg.Attachments = make(map[string][]byte)
	for name, values := range msg.Header {
		if !strings.HasPrefix(name, "Content") {
			continue
		}
		for _, val := range values {
			mimeParts = fmt.Sprintf("%s%s: %s\r\n", mimeParts, name, decodeRFC2047(val))
		}
	}
	mediaType, params, err := mime.ParseMediaType(msg.Header.Get("Content-Type"))
	if err != nil {
		log.Fatal(err)
	}
	if strings.HasPrefix(mediaType, "multipart/") {
		mimeParts, mDecodedMsg.Blocks, mDecodedMsg.Attachments, err = readParts(mimeParts, mDecodedMsg.Blocks, mDecodedMsg.Attachments, msg.Body, params["boundary"], 0)
	} else {
		mimeParts = fmt.Sprintf("%sX-Bitmaelum-Block: default", mimeParts)
		body, err := ioutil.ReadAll(msg.Body)
		if err != nil {
			return mDecodedMsg, err
		}
		hasDefaultBlock = true
		mDecodedMsg.Blocks = append(mDecodedMsg.Blocks, "default,"+string(body))
	}
	if !hasDefaultBlock {
		if err := renameBlock("text/plain", "default", &mDecodedMsg.Blocks); err == nil {
			hasDefaultBlock = true
			mimeParts = strings.Replace(mimeParts, "text/plain", "default", 1)
		}
	}
	if !hasDefaultBlock {
		if err := renameBlock("text/html", "default", &mDecodedMsg.Blocks); err == nil {
			hasDefaultBlock = true
			mimeParts = strings.Replace(mimeParts, "text/html", "default", 1)
		}
	}
	if !hasDefaultBlock {
		parts := strings.SplitN(mDecodedMsg.Blocks[0], ",", 2)
		mimeParts = strings.Replace(mimeParts, parts[0], "default", 1)
		mDecodedMsg.Blocks[0] = "default," + parts[1]
	}
	mDecodedMsg.Blocks = append(mDecodedMsg.Blocks, "mimeparts,"+mimeParts)
	return mDecodedMsg, err
}
func DecodeFromMime ( m string ) ( * MimeMessage , error ) { m = strings . Replace ( m , " \r \n " , " \n " , - 1 ) m = strings . Replace ( m , " \n " , " \r \n " , - 1 ) mDecodedMsg := & MimeMessage { } msg , err := mail . ReadMessage ( bytes . NewBufferString ( m ) ) if err != nil { return mDecodedMsg , err } mDecodedMsg . To , _ = ( & mail . AddressParser { } ) . ParseList ( msg . Header . Get ( " " ) ) mDecodedMsg . From , _ = ( & mail . AddressParser { } ) . Parse ( msg . Header . Get ( " " ) ) mDecodedMsg . Subject = msg . Header . Get ( " " ) mDecodedMsg . Date , _ = msg . Header . Date ( ) mDecodedMsg . ID = msg . Header . Get ( " " ) var mimeParts string var hasDefaultBlock bool mDecodedMsg . Attachments = make ( map [ string ] [ ] byte ) for name , values := range msg . Header { if ! strings . HasPrefix ( name , " " ) { continue } for _ , val := range values { mimeParts = fmt . Sprintf ( " \r \n " , mimeParts , name , decodeRFC2047 ( val ) ) } } mediaType , params , err := mime . ParseMediaType ( msg . Header . Get ( " " ) ) if err != nil { log . Fatal ( err ) } if strings . HasPrefix ( mediaType , " " ) { mimeParts , mDecodedMsg . Blocks , mDecodedMsg . Attachments , err = readParts ( mimeParts , mDecodedMsg . Blocks , mDecodedMsg . Attachments , msg . Body , params [ " " ] , 0 ) } else { mimeParts = fmt . Sprintf ( " " , mimeParts ) body , err := ioutil . ReadAll ( msg . Body ) if err != nil { return mDecodedMsg , err } hasDefaultBlock = true mDecodedMsg . Blocks = append ( mDecodedMsg . Blocks , " " + string ( body ) ) } if ! hasDefaultBlock { if err := renameBlock ( " " , " " , & mDecodedMsg . Blocks ) ; err == nil { hasDefaultBlock = true mimeParts = strings . Replace ( mimeParts , " " , " " , 1 ) } } if ! hasDefaultBlock { if err := renameBlock ( " " , " " , & mDecodedMsg . Blocks ) ; err == nil { hasDefaultBlock = true mimeParts = strings . Replace ( mimeParts , " " , " " , 1 ) } } if ! hasDefaultBlock { parts := strings . SplitN ( mDecodedMsg . Blocks [ 0 ] , " " , 2 ) mimeParts = strings . Replace ( mimeParts , parts [ 0 ] , " " , 1 ) mDecodedMsg . Blocks [ 0 ] = " " + parts [ 1 ] } mDecodedMsg . Blocks = append ( mDecodedMsg . Blocks , " " + mimeParts ) return mDecodedMsg , err }
DecodeFromMime will decode a mime message and return a MimeMessage struct
DecodeFromMime will decode a mime message and return a MimeMessage struct
// Make sure it's using CRLF to be fully MIME compliant // If there is no default block then set the first "text/plain" as default // If no "text/plain" is found then set the first "text/html" as default // It no "text/html" and not "text/plain" are found then set the first block as default