:envelope: A streaming Go library for the Internet Message Format and mail messages

go-message

godocs.io builds.sr.ht status codecov

A Go library for the Internet Message Format. It implements:

Features

  • Streaming API
  • Automatic encoding and charset handling (to decode all charsets, add import _ "github.com/emersion/go-message/charset" to your application)
  • A mail subpackage to read and write mail messages
  • DKIM-friendly
  • A textproto subpackage that just implements the wire format

License

MIT

Owner
Simon Ser
I work on open-source software.
Simon Ser
Comments
  • textproto: continue parsing on malformed header

    textproto: continue parsing on malformed header

    Hi, I have added an Test which failed before. When there is a Line in the Header which doesnt have a ":", all Headers below that line was not parsed.

    Read() now returns also an usable Entity even if was an error triggered.

    There are use-cases where a developer wants to Parse what is possible and use it, instead of failing the mail.

  • Failed to parse after long header

    Failed to parse after long header

    Hi,

    i receive mails with some strange long header X-CMAE-Envelope, unfortuatelly all headers below that long header cannot be parsed.

    X-CMAE-Envelope: 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
    SomeHeader: xyz
    Subject: Test
    
  • fix: import cycle not allowed

    fix: import cycle not allowed

    The build log looks like this: https://download.copr.fedorainfracloud.org/results/proletarius101/hydroxide/fedora-32-x86_64/01654615-golang-github-emersion-message-textproto/builder-live.log.gz

    I'd say I'm not quite familiar with Go. And as I build the source code manually with the same command there is no error:

    go test -buildmode pie -compiler gc -ldflags " -X github.com/emersion/go-message/textproto/version.commit=master -X github.com/emersion/go-message/textproto/version=0 -extldflags '-Wl,-z,relro -Wl,--as-needed  -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld '"
    

    I just made this commit by some guessing, and it works somehow.

  • returning error on len(line) > maxLineOctets can lead to missing attachments

    returning error on len(line) > maxLineOctets can lead to missing attachments

    Inside readLineSlice function:

    if len(line) > maxLineOctets {
    	return nil, TooBigError{"line"}
    }
    

    This implementation is very useful to ignore the contents that can be spam, however it can cause caller to skip next attachment files in a mail message. Is it possible to use break instead of returning with an error here ?

  • Only supports 2 character sets on Entity.WriteTo()

    Only supports 2 character sets on Entity.WriteTo()

    Hi,

    I will create test mail, but set conent type parames only support utf-8 and us-ascii.

    Source Url https://github.com/emersion/go-message/blob/master/writer.go#L58

    Example ` func main() { var header message.Header //header.SetContentType("text/plain", map[string]string{"charset": "utf-8"}) header.SetContentType("text/plain", map[string]string{"charset": "iso-8859-1"}) header.Set("From", "[email protected]") header.Set("To", "[email protected]")

    entity, err := message.New(header, bytes.NewBufferString("hello world"))
    if err != nil {
    	fmt.Println(err)
    	return
    }
    
    f, err := os.OpenFile("./test.eml", os.O_CREATE|os.O_RDWR, 0644)
    if err != nil {
    	fmt.Println(err)
    	return
    }
    
    err = entity.WriteTo(f)
    if err != nil {
    	fmt.Println(err)
    }
    

    } `

    Error unknown charset: unknown charset: message: unhandled charset "iso-8859-1"

  • Partial reads only leading to invalid multipart parsing

    Partial reads only leading to invalid multipart parsing

    Hi there

    For some reason, my IMAP emails aren't read entirerly. It seems to read only the first 4096 bytes of the message (which seems to be the peekBufferSize in Go's multipart), which leads to incomplete message bodies, and then an error from multipart: `multipart: expecting a new Part; got line "You can also turn email notifications off:\r\n"

    My code is very simple (I'm using go-imap):

    r := msg.GetBody("BODY[]")
    
    		if r == nil {
    			log.Errorf("Server returned empty body")
    			continue
    		}
    
    		bodyParser, err := message.Read(r)
    		if message.IsUnknownEncoding(err) {
    			// Non-fatal error
    			log.Noticef("Unknown encoding: %s", err)
    		} else if err != nil {
    			log.Errorf("Failed to read message: %s", err)
    			continue
    		}
    
    		if mr := bodyParser.MultipartReader(); mr != nil {
    			// This is a multipart message
    			for {
    				p, err := mr.NextPart()
    				if err == io.EOF {
    					break
    				} else if err != nil {
    					log.Errorf("Error parsing email part: %s", err) // This throws the error
    					// log.Infof("%s", msgBytes)
    					continue
    				}
    
    				t, _, _ := p.Header.ContentType()
    				log.Infof("Part is type %s", t)
    
    				part, err := ioutil.ReadAll(p.Body)
    
    				log.Infof("Part: %s", part) // This shows an incomplete email
    			}
    		} else {
    			t, _, _ := bodyParser.Header.ContentType()
    			log.Infof("Non-multipart message of type %s", t)
    		}
    

    E-mails are simple Slack notification emails. I'm going to see if I can anonymize them and include them in the unit tests.

  • Cannot add a message/rfc822 part correctly (Content-Transfer-Encoding is not valid)

    Cannot add a message/rfc822 part correctly (Content-Transfer-Encoding is not valid)

    When creating mails, the library does not allow correct embedding of message/rfc822 parts. When adding a mime part like this, the contents must not be transfer encoded - they are assumed to be already encoded because mime by definition is already transport safe. However, this function does not account for this:

    func initInlineContentTransferEncoding(h *message.Header) {
    	if !h.Has("Content-Transfer-Encoding") {
    		t, _, _ := h.ContentType()
    		if strings.HasPrefix(t, "text/") {
    			h.Set("Content-Transfer-Encoding", "quoted-printable")
    		} else {
    			h.Set("Content-Transfer-Encoding", "base64")
    		}
    	}
    }
    

    And it's usage:

    func encodingWriter(enc string, w io.Writer) (io.WriteCloser, error) {
    	var wc io.WriteCloser
    	switch strings.ToLower(enc) {
    	case "quoted-printable":
    		wc = quotedprintable.NewWriter(w)
    	case "base64":
    		wc = base64.NewEncoder(base64.StdEncoding, textwrapper.NewRFC822(w))
    	case "7bit", "8bit":
    		wc = nopCloser{textwrapper.New(w, "\r\n", 1000)}
    	case "binary", "":
    		wc = nopCloser{w}
    	default:
    		return nil, fmt.Errorf("unhandled encoding %q", enc)
    	}
    	return wc, nil
    }
    

    The only valid encodings for a part like this are 7bit, 8bit and binary. This is in RFC-2048 5.2.1 https://datatracker.ietf.org/doc/html/rfc2046#section-5.2.1

    No encoding other than "7bit", "8bit", or "binary" is permitted for the body of a "message/rfc822" entity. The message header fields are always US-ASCII in any case, and data within the body can still be encoded, in which case the Content-Transfer-Encoding header field in the encapsulated message will reflect this. Non-US-ASCII text in the headers of an encapsulated message can be specified using the mechanisms described in RFC 2047.

    This is actually true for both inline and attachment headers, I've just shown inline. I'll make a PR to handle both because I need this anyway :)

  • Add support for write encoding similar to existing support for read encoding

    Add support for write encoding similar to existing support for read encoding

    I need to be able to write out messages in basically any encoding. This creates a mirror of CharsetReader named CharsetWriter and then makes what I think are appropriate changes to writer.go.

    This has no tests or anything yet. I wanted to share the PR to make sure I was on the correct track first.

  • Save the original raw body in the entity

    Save the original raw body in the entity

    There's a good chance you won't like these changes due to unbounded allocations. I fully agree. This PR is more an invitation to discussion than a proposal of a concrete solution.

    But it's important to have access to the original raw entity body in case it can't be decoded/read (example: messages that specify a transfer encoding yet have illegal base64/qp data). In that case, it's good to still have the original body there to do something with.

    Can you think of any io.Reader magic that would facilitate this without the need for ioutil.ReadAll like I've done? I was thinking about wrapping the source reader in a TeeReader that writes the source data to a buffer, which then becomes RawBody. But that would mean you have to read all from Body before RawBody contains what you want, which isn't so great (you might not care about the decoded body at all and only ever want the raw body and be surprised that it's always empty if you never read from Body).

    Any other smart ideas?

  • Does not correctly ignore 'bad' base64 whitespace characters RFC-2045

    Does not correctly ignore 'bad' base64 whitespace characters RFC-2045

    Honestly, I'm surprised to see this. Got a really unusual error about being unable to decode a base64 transfer encoded part today. The part in question was an image that was wrapped at 998 chars long but indented with a continuation white space, which breaks the base64 decoder.

    This is obviously a bug on the author of the mail part. HOWEVER I went and read the spec, RFC-2045 6.8 () and the following is stated:

    The encoded output stream must be represented in lines of no more than 76 characters each. All line breaks or other characters not found in Table 1 must be ignored by decoding software. In base64 data, characters other than those in Table 1, line breaks, and other white space probably indicate a transmission error, about which a warning message or even a message rejection might be appropriate under some circumstances.

    So, that's 2 counts that the part is breaking the spec on (line length and invalid characters) BUT I read this paragraph that we should be able to ignore this padding white space, and decode the part.

    I believe this can be achieved by imitating what the base64 decoder does internally with it's newlineFilteringReader, we can wrap the raw reader in one that will do exactly the same, but include FWS (folding white space) characters in the list, so space and tab characters.

    Would a PR for this be acceptable?

  • Header.AddressList does not do RFC2047 header decoding

    Header.AddressList does not do RFC2047 header decoding

    https://github.com/emersion/go-message/blob/981888ca7c0807f5dca8fb8e167cb5da3c0bfcd5/mail/header.go#L229

    Program that shows the problem:

        import (
            "bytes"
            "fmt"
            "log"
            "strings"
        
            _ "github.com/emersion/go-message/charset"
            "github.com/emersion/go-message/mail"
        )
        
        func main() {
            raw := `From: =?utf-8?q?Atakan_=C3=87olak?= <[email protected]>
        
        message body
        `
            raw = strings.ReplaceAll(raw, "\n", "\r\n")
            msg := bytes.NewReader([]byte(raw))
        
            m, err := mail.CreateReader(msg)
            if err != nil {
    	        log.Fatal(err)
            }
        
            from, err := m.Header.AddressList("From")
            if err != nil {
    	        log.Fatal("From: ", err)
            }
            fmt.Println(from) // quoted part of address wasn't decoded
        
            decoded, err := m.Header.Text("From") // quoted part decoded 
            if err != nil {
    	        log.Fatal(err)
            }
            fmt.Println(decoded)
    }
    

    output:

        Jeffs-MBP-2:mbox-bug jeff$ go run . 
        [=?utf-8?q?Atakan_=C3=87olak?= <[email protected]>]
        Atakan Çolak <[email protected]>
    

    It seems like h.Text() should be used instead of h.Get()?

    https://github.com/emersion/go-message/blob/981888ca7c0807f5dca8fb8e167cb5da3c0bfcd5/mail/header.go#L230

  • Allows detection of end of end of input empty results

    Allows detection of end of end of input empty results

    Since there wasn't an obvious EOF passed through, or another form of special error. Header couldn't be made nil as it was publicly exposed and would constitute a signature change.

    This does however introduce a behaviour change. message.Read can no return nil. Didn't seem to impact tests will probably impact users

  • Can't parse email where Message-ID has more than one

    Can't parse email where Message-ID has more than one "@" character

    Hi!

    I've noticed that if Message-ID (or any other header using msg-id) has more than one "@" character than parsing via parseMsgID() from header.go fails with:

    missing '>' in msg-id

    as it expects to consume() special chars in the fallowing order: < , @ , >

    i.e.

    Message-ID: <113c01d86b4a$53bb4230$fa9e45a$@[email protected]>

    I'm not sure if using two or more "@" characters in msg-id is correct but I've already seen a few of this headers in the wild.

  • Inline vs Attachment part logic is insufficient for emails in the wild

    Inline vs Attachment part logic is insufficient for emails in the wild

    Hello,

    with the current implementation, interface PartHeader is implemented as either InlineHeader or AttachmentHeader that both embed message.Header. ~~And although it's not documented by the package, the wiki example implies that PartHeader will always be one of the two.~~

    The logic to decide whether its AttachmentHeader or PartHeader,

    if disp == "inline" || (disp != "attachment" && strings.HasPrefix(t, "text/")) {
        mp.Header = &InlineHeader{p.Header}
    } else {
        mp.Header = &AttachmentHeader{p.Header}
    }
    

    unfortunately, doesn't always work for emails in the wild. E.g., I have a message with the following part header:

    Content-Type: text/plain; name="emailreceipt_20121015R2315576090.pdf"
    Content-Disposition: inline; filename=emailreceipt_20121015R2315576090.pdf
    
    %PDF-1.4..%...
    

    It's clearly a PDF attachment, but is currently classified as InlineHeader, so we cannot use AttachmentHeader.Filename to extract the filename.

    To solve this problem, the user code can of course cast PartHeader as Header (which will succeed with the current implementation), and then effectively re-implement AttachmentHeader.Filename logic by perusing Header.ContentDisposition and Header.ContentType methods.

    The alternative would be, at a minimum, to extend PartHeader interface to directly expose ContentDisposition and ContentType, which will help the user code that works with malformed parts. (If this indeed a desired direction, I'm happy to create a pull request).

    Another alternative would be to improve the Inline vs Attachment logic, but it will probably be brittle as you cannot enumerate badness in the wild.

    Thoughts?

  • Long quoted-printable lines break parsing

    Long quoted-printable lines break parsing

    Quoted-printable lines must have a length limit according to the RFC but some software doesn't do that. This ends up error'ing out in the stdlib's parser.

    Tentiative fix in https://github.com/emersion/go-message/pull/120 was rejected.

  • Header decoding issue.

    Header decoding issue.

    go-message seems to suffer an issue which was previously discovered in perl Mail::Header module. https://rt.cpan.org/Public/Bug/Display.html?id=113464

    The issue involves crafted messages that are usually used to transmit malware bypassing content scanners.

    The header looks like this

    --Apple-Mail=_13B14614-BE73-1755-BFC6-C42D9D44027D
    Content-Disposition: inline; filename="04EBD_xxxx.xxxx_A546BB.zip"
    Content-Type: application/x-rar-compressed; x-unix-mode=0600;
    name="04EBD_xxxx.xxxx_A546BB.zip"
    Content-Transfer-Encoding: base64
    

    go-message fails to parse this returning unexpected EOF

  • Textproto should handle missing boundary in a better way ?

    Textproto should handle missing boundary in a better way ?

    When dealing with spam you find lots of malformed messages like some missing the final boundary in multipart messages. In cases like this the parser returns an encapsulated EOF error like so multipart: NextPart: EOF from https://github.com/emersion/go-message/blob/b27fd96b0a989dd508c23531540704675d4d0ca1/textproto/multipart.go#L262 That is hard to detect in the calling code. It would be better to have a named error instead like missing boundary which can be detected in calling code because the message is actually parsed so the error should not fail the whole process

Related tags
Mail-alias-resolve-ldap - Resolve mail alias addresses in LDAP

alias-resolve-ldap alias-resolve-ldap was written to be used as a hook for the c

Jan 30, 2022
Mcopa - A library allows for parsing an email message into a more convenient form than the net/mail provides

Mail content parsing This library allows for parsing an email message into a mor

Jan 1, 2022
Go library for sending mail with the Mailgun API.

Mailgun with Go Go library for interacting with the Mailgun API. Usage package main import ( "context" "fmt" "log" "time" "githu

Dec 25, 2022
Mail_sender - This library is for sending emails from your mail

Mail Sender This library is for sending emails from your mail Installation mail_

Dec 30, 2021
MIME mail encoding and decoding package for Go

enmime enmime is a MIME encoding and decoding library for Go, focused on generating and parsing MIME encoded emails. It is being developed in tandem w

Nov 30, 2022
Filtering spam in mail server, protecting both client privacy and server algorithm

HE Spamfilter SNUCSE 2021 "Intelligent Computing System Design Project" Hyesun Kwak Myeonghwan Ahn Dongwon Lee abstract Naïve Bayesian spam filtering

Mar 23, 2022
Inline styling for html mail in golang

go-premailer Inline styling for HTML mail in golang Document install go get github.com/vanng822/go-premailer/premailer Example import ( "fmt" "gith

Nov 30, 2022
Golang package that generates clean, responsive HTML e-mails for sending transactional mail
Golang package that generates clean, responsive HTML e-mails for sending transactional mail

Hermes Hermes is the Go port of the great mailgen engine for Node.js. Check their work, it's awesome! It's a package that generates clean, responsive

Dec 28, 2022
✉️ Composable all-in-one mail server.

Maddy Mail Server Composable all-in-one mail server. Maddy Mail Server implements all functionality required to run a e-mail server. It can send messa

Dec 27, 2022
an MDA that sends a webhook on recieval of mail

an MDA that sends a webhook on recieval of mail

Aug 13, 2022
📧 Example of sending mail via SendGrid in Golang.

?? go-sendgrid-example Example of sending mail via SendGrid in Golang. Get it started $ make setup # Edit environment variables $ vim ./env/local.env

Jan 11, 2022
Simple tool to test SMTP mail send with various settings including TLS1.1 downgrade

smtptest Simple tool to test SMTP mail send with various settings including TLS1.1 downgrade All settings are configurable in the config.yaml file ser

Sep 19, 2022
Go-mail - Email service using Kafka consumer

?? The Project This project consists in a Kafka consumer that reads messages of

Feb 5, 2022
Send markdown files as MIME-encoded electronic mail.

Send markdown files as MIME-encoded electronic mail.

Aug 9, 2022
Using Mailchain, blockchain users can now send and receive rich-media HTML messages with attachments via a blockchain address.

Mailchain Introduction Mailchain enables blockchain-based email-like messaging with plain or rich text and attachment capabilities. Using blockchain p

Dec 28, 2022
Robust and flexible email library for Go

email Robust and flexible email library for Go Email for humans The email package is designed to be simple to use, but flexible enough so as not to be

Dec 30, 2022
:inbox_tray: An IMAP library for clients and servers

go-imap An IMAP4rev1 library written in Go. It can be used to build a client and/or a server. Usage Client package main import ( "log" "github.com

Jan 6, 2023
A simple Go POP3 client library for connecting and reading mails from POP3 servers.

go-pop3 A simple Go POP3 client library for connecting and reading mails from POP3 servers. This is a full rewrite of TheCreeper/go-pop3 with bug fixe

Dec 17, 2022
:white_check_mark: A Go library for email verification without sending any emails.

email-verifier ✉️ A Go library for email verification without sending any emails. Features Email Address Validation: validates if a string contains a

Dec 30, 2022