go-imap

repository·v2·Indexed 25 days ago

https://github.com/emersion/go-imap

A 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.

Tokens
13.1K
Snippets
24
Records
79
Agent score
81%

What's inside go-imap

  1. Access go-imap documentation

    v2

    The library provides separate documentation for client-side and server-side implementations:

    • Client implementation: Use the imapclient package documentation.
    • Server implementation: Use the imapserver package documentation.
  2. Construct search criteria for the SEARCH command

    v2

    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: Use the Not field, which takes a slice of SearchCriteria.
    • OR: Use the 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"}},
    	}},
    }
  3. Traverse message body structures with BodyStructure.Walk

    v2

    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)

    • The callback f receives the path (a slice of integers representing the part numbers, e.g., []int{1, 2}) and the part itself.
    • If the callback returns false, the traversal stops for that branch (it will not visit the children of that part).
  4. Understand BodyStructure types and metadata

    v2

    The imap.BodyStructure interface provides a unified way to handle different MIME parts.

    BodyStructureSinglePart

    Represents a single MIME part.

    • MediaType(): Returns the MIME type (e.g., text/plain).
    • Filename(): Decodes the filename from the Disposition or Params.
    • Specialized Metadata:
      • MessageRFC822: Available for message/rfc822 parts.
      • Text: Available for text/* parts (contains NumLines).

    BodyStructureMultiPart

    Represents a container for multiple parts.

    • Children: A slice of BodyStructure objects.
    • MediaType(): Returns multipart/ followed by the subtype.
  5. Use the NumSet interface for polymorphic message sets

    v2

    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.
  6. Execute IMAP commands and wait for responses

    v2

    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.

  7. Handle unsolicited server data with UnilateralDataHandler

    v2

    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.
  8. Connect to an IMAP server

    v2

    The imapclient package provides several ways to establish a connection to an IMAP server depending on the required security:

    • Implicit TLS: Use DialTLS(address string, options *Options) for connections that start with TLS (e.g., port 993).
    • STARTTLS: Use DialStartTLS(address string, options *Options) to upgrade an unencrypted connection to TLS.
    • Insecure: Use DialInsecure(address string, options *Options) for plain TCP connections without encryption.
    • Manual: Use 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.

  9. Initialize and run an IMAP server

    v2

    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.
  10. Configure imapclient.Options

    v2

    The Options struct allows you to customize the client behavior:

    FieldTypeDescription
    TLSConfig*tls.ConfigTLS configuration for DialTLS and DialStartTLS.
    DebugWriterio.WriterWrites raw ingress and egress data. Warning: May contain sensitive credentials.
    UnilateralDataHandler*UnilateralDataHandlerHandler for unsolicited server data (e.g., during IDLE).
    WordDecoder*mime.WordDecoderDecoder for RFC 2047 words (e.g., non-UTF-8 subjects).
    Dialer*net.DialerCustom 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)
  11. Configure imapserver.Options

    v2

    The Options struct defines the behavior of the IMAP server.

    FieldTypeDescription
    NewSessionfunc(*Conn) (Session, *GreetingData, error)Required. Called when a client connects.
    Capsimap.CapSetSupported capabilities. Must contain imap.CapIMAP4rev1 or imap.CapIMAP4rev2.
    LoggerLoggerInterface for error logging. Defaults to log.Default() if nil.
    TLSConfig*tls.ConfigTLS configuration for STARTTLS. If nil, STARTTLS is disabled.
    InsecureAuthboolIf true, allows authentication without TLS.
    DebugWriterio.WriterWrites raw ingress and egress data. Note: may contain sensitive credentials.