
go-message
Open Source Go Library for Email & Internet Message Format
Parse, Generate & Handle RFC 5322, MIME, and Content-Disposition Headers via Streaming Go API.
What is go-message?
go-message is a high-performance, streaming Go library designed for parsing and generating email messages conforming to the Internet Message Format (RFC 5322), MIME extensions (RFC 2045–2047), and Content-Disposition headers (RFC 2183). It enables Go developers to process email content efficiently without loading entire messages into memory, making it ideal for scalable mail servers and clients. The library supports automatic charset decoding and integrates seamlessly with Go’s standard library.
Built with modularity and extensibility in mind, go-message includes dedicated subpackages like `mail` for high-level mail handling and `textproto` for low-level protocol parsing. Its DKIM-friendly design ensures compatibility with modern email authentication workflows. With built-in streaming capabilities and charset normalization, go-message simplifies complex email processing tasks such as parsing multipart bodies, decoding encoded headers, and handling nested MIME structures—all while maintaining memory efficiency and performance.
Getting Started with go-message
To begin using go-message, install it via `go get` from the official [go-message GitHub](https://github.com/emersion/go-message) repository. The recommended approach is to use Go modules: run `go get github.com/emersion/go-message` in your project directory. For charset decoding support, include `import _ "github.com/emersion/go-message/charset"` to enable all standard encodings. The library is lightweight, dependency-free, and integrates smoothly into existing Go applications.
Install go-message via Go Modules
go get github.com/emersion/go-message
# Optional: enable full charset support
import _ "github.com/emersion/go-message/charset"
Streaming Email Parsing
go-message provides a streaming parser that processes email messages incrementally without loading the entire content into memory. This is especially beneficial for handling large emails or high-volume mail processing. The parser reads headers and body parts sequentially, allowing developers to inspect or forward messages in real time. It supports both RFC-compliant and malformed messages gracefully, making it suitable for production mail servers. By leveraging Go’s `io.Reader`, the library integrates naturally with network and file I/O operations.
How to Parse an Email Message via Streaming API?
import (
"bytes"
"github.com/emersion/go-message"
)
func parseEmail(data []byte) error {
r := bytes.NewReader(data)
m, err := message.Read(r)
if err != nil {
return err
}
// Access headers and body parts
return nil
}
MIME Multipart Handling
go-message fully supports parsing and generating MIME multipart messages as defined in RFC 2045 and RFC 2046. Developers can navigate complex multipart structures—including nested parts—using intuitive APIs. The library automatically decodes transfer encodings (e.g., base64, quoted-printable) and provides access to individual parts via the `Part` interface. This enables robust email composition and extraction of attachments, HTML/text alternatives, and embedded resources. Its streaming nature ensures efficient handling even for large multipart messages with many parts.
How to Extract Multipart Parts from an Email?
import (
"github.com/emersion/go-message"
"github.com/emersion/go-message/textproto"
)
func extractParts(m *message.Message) error {
if m.Multipart() {
for _, p := range m.Parts() {
// Process each part (e.g., text, attachment)
mediaType, params, _ := p.Header.MediaType()
if mediaType == "text/plain" {
// Read plain text content
content, _ := io.ReadAll(p.Body)
}
}
}
return nil
}
Charset & Encoding Support
go-message includes robust automatic charset and encoding handling for email headers and body content. It supports decoding of RFC 2047-encoded headers (e.g., `=?utf-8?B?...?=`) and body text in various charsets (UTF-8, ISO-8859, etc.). By importing the optional `github.com/emersion/go-message/charset` package, developers gain access to all registered IANA charsets via `golang.org/x/text/encoding`. This ensures accurate rendering of international email content, including non-Latin scripts and special symbols, without manual charset detection or conversion.
How to Decode a Charset-Encoded Header?
import (
"github.com/emersion/go-message"
_ "github.com/emersion/go-message/charset" // Enable all charsets
)
func decodeSubject(m *message.Message) (string, error) {
subject, err := m.Header.Get("Subject")
if err != nil {
return "", err
}
// Automatically decoded using registered charsets
return subject, nil
}
DKIM-Friendly Message Signing
go-message is designed to be DKIM-friendly, enabling seamless integration with cryptographic signing and verification workflows. Its streaming parser preserves message structure integrity, allowing signers to sign only the canonicalized body and selected headers without re-encoding. The library avoids unnecessary transformations (e.g., line-ending normalization) that could break DKIM signatures. Developers can build email signing pipelines by combining go-message with libraries like `github.com/emersion/go-dkim`, ensuring compliance with RFC 6376 for domain-based message authentication.
How to Prepare a Message for DKIM Signing?
import (
"bytes"
"github.com/emersion/go-message"
"github.com/emersion/go-message/textproto"
)
func prepareForDKIM(m *message.Message) (*bytes.Buffer, error) {
var buf bytes.Buffer
// Write canonicalized headers and body
h := m.Header
h.WriteTo(&buf)
buf.WriteString("\r\n")
if _, err := io.Copy(&buf, m.Body); err != nil {
return nil, err
}
return &buf, nil
}
