Install go-imap v2
v2To add the go-imap v2 library to your Go project, use the go get command. Note that v2 is an IMAP4rev2 implementation and is currently under development.
go get github.com/emersion/go-imap/v2repository·v2·Indexed 25 days ago
https://github.com/emersion/go-imapA modular Go implementation of the IMAP protocol providing both client and server capabilities. Version 2 is an IMAP4rev2 implementation. The library includes packages for client-side (imapclient) and server-side (imapserver) implementations, support for IMAP4 ACL extensions (RFC 2086), and a CLI tool called imapmemserver for in-memory IMAP server testing.
To add the go-imap v2 library to your Go project, use the go get command. Note that v2 is an IMAP4rev2 implementation and is currently under development.
go get github.com/emersion/go-imap/v2The library provides separate documentation for client-side and server-side implementations:
imapclient package documentation.imapserver package documentation.The SearchCriteria struct is used to define the filters for an IMAP SEARCH command. When multiple fields are populated in a single SearchCriteria instance, the resulting search is an intersection (logical AND) of all those fields.
You can combine criteria using logical Not and Or operators:
Not field, which takes a slice of SearchCriteria.Or field, which takes a slice of [2]SearchCriteria (pairs of criteria to be OR-ed together).Note on Dates: For Since, Before, SentSince, and SentBefore, only the date component is used; time and timezone information are ignored.
Note on ModSeq: The ModSeq field requires the CONDSTORE extension.
// Example: Match messages NOT containing "hello"
SearchCriteria{
Not: []SearchCriteria{{
Body: []string{"hello"},
}},
}
// Example: Match messages containing either "hello" or "world"
SearchCriteria{
Or: [][2]SearchCriteria{{
{Body: []string{"hello"}},
{Body: []string{"world"}},
}},
}The imap.BodyStructure interface represents the MIME tree of a message. It can be either a *BodyStructureSinglePart or a *BodyStructureMultiPart.
To inspect the parts of a message, use the Walk method. It performs a depth-first pre-order traversal of the tree.
Walk(f BodyStructureWalkFunc)
f receives the path (a slice of integers representing the part numbers, e.g., []int{1, 2}) and the part itself.false, the traversal stops for that branch (it will not visit the children of that part).The imap.BodyStructure interface provides a unified way to handle different MIME parts.
Represents a single MIME part.
MediaType(): Returns the MIME type (e.g., text/plain).Filename(): Decodes the filename from the Disposition or Params.MessageRFC822: Available for message/rfc822 parts.Text: Available for text/* parts (contains NumLines).Represents a container for multiple parts.
Children: A slice of BodyStructure objects.MediaType(): Returns multipart/ followed by the subtype.The NumSet interface provides a common way to interact with both SeqSet (sequence numbers) and UIDSet (UIDs). This is useful when writing functions that need to handle message identifiers without caring whether they are sequence-based or UID-based.
Supported methods:
String() string: Returns the IMAP string representation of the set (e.g., "1:5,10" or "$" for search results).Dynamic() bool: Returns true if the set contains dynamic elements like *, ranges like n:*, or represents the special SEARCHRES marker.IMAP commands are exposed as methods on the Client. These methods are non-blocking; they send the command to the server and immediately return a *Command object. To wait for the server's response, you must call the .Wait() method on the returned command.
This pattern allows for command pipelining (executing multiple commands concurrently), though care must be taken to avoid ambiguity. Some commands, like Authenticate or Idle, will block the client during execution.
When using commands like IDLE or NOTIFY, the server may send unsolicited responses (e.g., FETCH, EXPUNGE, or STATUS updates). You can handle these by providing a UnilateralDataHandler in your Options.
Note: Handlers are invoked in an arbitrary goroutine and will block the client while running. If you need to perform slow operations, use a buffered channel and a separate goroutine within the handler.
Available handler functions:
Expunge(seqNum uint32): Called on EXPUNGE responses.Mailbox(data *UnilateralDataMailbox): Called on mailbox status changes.Fetch(msg *FetchMessageData): Called on unsolicited FETCH responses.Metadata(mailbox string, entries []string): Requires ENABLE METADATA or ENABLE SERVER-METADATA.List(data *imap.ListData): Called on unsolicited LIST responses (useful with NOTIFY).Status(data *imap.StatusData): Called on unsolicited STATUS responses.NotificationOverflow(): Called when the server disables NOTIFY notifications.The imapclient package provides several ways to establish a connection to an IMAP server depending on the required security:
DialTLS(address string, options *Options) for connections that start with TLS (e.g., port 993).DialStartTLS(address string, options *Options) to upgrade an unencrypted connection to TLS.DialInsecure(address string, options *Options) for plain TCP connections without encryption.New(conn net.Conn, options *Options) if you have already established a net.Conn.A nil options pointer is treated as a zero-value Options struct.
To create an IMAP server, use imapserver.New(options) and then call Serve(ln), ListenAndServe(addr), or ListenAndServeTLS(addr).
An Options struct is required. The most critical field is NewSession, a factory function that is called whenever a new client connects. This function must return a Session and GreetingData (or an error).
Key Configuration Options:
NewSession: Required. Defines how new client connections are handled.Caps: A imap.CapSet defining supported capabilities. If nil, the server defaults to imap.CapIMAP4rev1. At least IMAP4rev1 or IMAP4rev2 must be present.TLSConfig: A *tls.Config used for STARTTLS. If nil, STARTTLS is disabled.InsecureAuth: If true, allows authentication without TLS (use with caution).Logger: An implementation of the Logger interface. Defaults to log.Default() if nil.The Options struct allows you to customize the client behavior:
| Field | Type | Description |
|---|---|---|
TLSConfig | *tls.Config | TLS configuration for DialTLS and DialStartTLS. |
DebugWriter | io.Writer | Writes raw ingress and egress data. Warning: May contain sensitive credentials. |
UnilateralDataHandler | *UnilateralDataHandler | Handler for unsolicited server data (e.g., during IDLE). |
WordDecoder | *mime.WordDecoder | Decoder for RFC 2047 words (e.g., non-UTF-8 subjects). |
Dialer | *net.Dialer | Custom dialer for establishing connections. |
To enable advanced charset decoding for message subjects, use a mime.WordDecoder with a charset reader:
import (
"mime"
"github.com/emersion/go-message/charset"
)
options := &imapclient.Options{
WordDecoder: &mime.WordDecoder{CharsetReader: charset.Reader},
}
client, err := imapclient.DialTLS("imap.example.org:993", options)The Options struct defines the behavior of the IMAP server.
| Field | Type | Description |
|---|---|---|
NewSession | func(*Conn) (Session, *GreetingData, error) | Required. Called when a client connects. |
Caps | imap.CapSet | Supported capabilities. Must contain imap.CapIMAP4rev1 or imap.CapIMAP4rev2. |
Logger | Logger | Interface for error logging. Defaults to log.Default() if nil. |
TLSConfig | *tls.Config | TLS configuration for STARTTLS. If nil, STARTTLS is disabled. |
InsecureAuth | bool | If true, allows authentication without TLS. |
DebugWriter | io.Writer | Writes raw ingress and egress data. Note: may contain sensitive credentials. |