Documentation ¶
Overview ¶
Package imap implements an IMAP4rev1 client, as defined in RFC 3501.
The implementation provides low-level access to all protocol features described in the relevant RFCs (see list below), and assumes that the developer is familiar with the basic rules governing connection states, command execution, server responses, and IMAP data types. Reading this documentation alone is not sufficient for writing a working IMAP client. As a starting point, you should read RFC 2683 to understand some of the nuances of the protocol operation.
The rest of the documentation deals with the implementation of this package and not the protocol in general.
Introduction ¶
The package provides three main objects for interacting with an IMAP4 server: Client, Command, and Response. The client sends commands to the server and receives responses. The Response object is capable of representing all possible server responses and provides helper methods for decoding common data formats, such as LIST, FETCH, SEARCH, etc.
The client has two interfaces for issuing commands. The Send method is the raw command interface that can be used for implementing new commands, which are not already supported by the package. All standard commands, as well as those from a number of popular extensions, have dedicated methods that perform capability and field type checks, and properly encode the command arguments before passing them to Send.
Response Delivery ¶
To support execution of multiple concurrent commands, each server response goes through a filtering process to identify its owner. Each command in progress has an associated ResponseFilter function for this purpose. The Client calls all active filters in the command-issue order until one of the filters "claims" the response. Claimed responses are appended to the Command.Data queue of the claimer. Responses rejected by all filters are referred to as "unilateral server data" and are appended to the Client.Data queue. Commands documented as expecting "no specific responses" use a nil ResponseFilter, which never claims anything. Thus, responses for commands such as NOOP are always delivered to Client.Data queue.
The Client/Command state can only be updated by a call to Client.Recv. Each call receives and delivers at most one response, but these calls are often implicit, such as when using the Wait helper function (see below). Be sure to inspect and clear out the Client data queue after all receive operations to avoid missing important server updates. The Client example below demonstrates correct response handling.
Concurrency ¶
The Client and its Command objects cannot be used concurrently from multiple goroutines. It is safe to pass Response objects to other goroutines for processing, but the Client assumes "single-threaded" model of operation, so all method calls for the same connection must be serialized with sync.Mutex or some other synchronization mechanism. Likewise, it is not safe to access Client.Data and Command.Data in parallel with a call that can append new responses to these fields.
Asynchronous Commands ¶
Unless a command is marked as being "synchronous", which is usually those commands that change the connection state, the associated method returns as soon as the command is sent to the server, without waiting for completion. This allows the client to issue multiple concurrent commands, and then process the responses and command completions as they arrive.
A call to Command.Result on a command that is "in progress" will block until that command is finished. There is also a convenience function that turns any asynchronous command into a synchronous one:
cmd, err := imap.Wait(c.Fetch(...))
If err is nil when the call returns, the command was completed with the OK status and all data responses (if any) are queued in cmd.Data.
Logging Out ¶
The Client launches a goroutine to support receive operations with timeouts. The user must call Client.Logout to close the connection and stop the goroutine. The only time it is unnecessary to call Client.Logout is when the server closes the connection first and Client.Recv returns io.EOF error.
RFCs ¶
The following RFCs are implemented by this package:
http://tools.ietf.org/html/rfc2087 -- IMAP4 QUOTA extension http://tools.ietf.org/html/rfc2088 -- IMAP4 non-synchronizing literals http://tools.ietf.org/html/rfc2177 -- IMAP4 IDLE command http://tools.ietf.org/html/rfc2971 -- IMAP4 ID extension http://tools.ietf.org/html/rfc3501 -- INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1 http://tools.ietf.org/html/rfc3516 -- IMAP4 Binary Content Extension http://tools.ietf.org/html/rfc3691 -- Internet Message Access Protocol (IMAP) UNSELECT command http://tools.ietf.org/html/rfc4315 -- Internet Message Access Protocol (IMAP) - UIDPLUS extension http://tools.ietf.org/html/rfc4616 -- The PLAIN Simple Authentication and Security Layer (SASL) Mechanism http://tools.ietf.org/html/rfc4959 -- IMAP Extension for Simple Authentication and Security Layer (SASL) Initial Client Response http://tools.ietf.org/html/rfc4978 -- The IMAP COMPRESS Extension http://tools.ietf.org/html/rfc5161 -- The IMAP ENABLE Extension http://tools.ietf.org/html/rfc5738 -- IMAP Support for UTF-8
The following RFCs are either informational, not fully implemented, or place no implementation requirements on the package, but may be relevant to other parts of a client application:
http://tools.ietf.org/html/rfc2595 -- Using TLS with IMAP, POP3 and ACAP http://tools.ietf.org/html/rfc2683 -- IMAP4 Implementation Recommendations http://tools.ietf.org/html/rfc4466 -- Collected Extensions to IMAP4 ABNF http://tools.ietf.org/html/rfc4469 -- Internet Message Access Protocol (IMAP) CATENATE Extension http://tools.ietf.org/html/rfc4549 -- Synchronization Operations for Disconnected IMAP4 Clients http://tools.ietf.org/html/rfc5530 -- IMAP Response Codes
Index ¶
- Constants
- Variables
- func AsAtom(f Field) string
- func AsBytes(f Field) []byte
- func AsDateTime(f Field) time.Time
- func AsMailbox(f Field) string
- func AsNumber(f Field) uint32
- func AsString(f Field) string
- func ByeFilter(_ *Command, rsp *Response) bool
- func FetchFilter(cmd *Command, rsp *Response) bool
- func NameFilter(cmd *Command, rsp *Response) bool
- func Quote(s string, utf8quoted bool) string
- func QuoteBytes(s []byte, utf8quoted bool) []byte
- func Quoted(f Field) bool
- func QuotedUTF8(f Field) bool
- func UTF7Decode(u string) (s string, err error)
- func UTF7DecodeBytes(u []byte) (s []byte, err error)
- func UTF7Encode(s string) string
- func UTF7EncodeBytes(s []byte) []byte
- func Unquote(q string) (s string, ok bool)
- func UnquoteBytes(q []byte) (s []byte, ok bool)
- type Client
- func (c *Client) Append(mbox string, flags FlagSet, idate *time.Time, msg Literal) (cmd *Command, err error)
- func (c *Client) Auth(a SASL) (cmd *Command, err error)
- func (c *Client) Capability() (cmd *Command, err error)
- func (c *Client) Check() (cmd *Command, err error)
- func (c *Client) Close(expunge bool) (cmd *Command, err error)
- func (c *Client) CompressDeflate(level int) (cmd *Command, err error)
- func (c *Client) Copy(seq *SeqSet, mbox string) (cmd *Command, err error)
- func (c *Client) Create(mbox string) (cmd *Command, err error)
- func (c *Client) Delete(mbox string) (cmd *Command, err error)
- func (c *Client) Enable(caps ...string) (cmd *Command, err error)
- func (c *Client) Expunge(uids *SeqSet) (cmd *Command, err error)
- func (c *Client) Fetch(seq *SeqSet, items ...string) (cmd *Command, err error)
- func (c *Client) GetQuota(root string, quota ...*Quota) (cmd *Command, err error)
- func (c *Client) GetQuotaRoot(mbox string) (cmd *Command, err error)
- func (c *Client) ID(info ...string) (cmd *Command, err error)
- func (c *Client) Idle() (cmd *Command, err error)
- func (c *Client) IdleTerm() (cmd *Command, err error)
- func (c *Client) LSub(ref, mbox string) (cmd *Command, err error)
- func (c *Client) List(ref, mbox string) (cmd *Command, err error)
- func (d Client) Log(mask LogMask, v ...interface{})
- func (d Client) Logf(mask LogMask, format string, v ...interface{})
- func (c *Client) Login(username, password string) (cmd *Command, err error)
- func (d Client) Logln(mask LogMask, v ...interface{})
- func (c *Client) Logout(timeout time.Duration) (cmd *Command, err error)
- func (c *Client) Noop() (cmd *Command, err error)
- func (c *Client) Quote(v interface{}) Field
- func (c *Client) Recv(timeout time.Duration) error
- func (c *Client) Rename(old, new string) (cmd *Command, err error)
- func (c *Client) Search(spec ...Field) (cmd *Command, err error)
- func (c *Client) Select(mbox string, readonly bool) (cmd *Command, err error)
- func (c *Client) Send(name string, fields ...Field) (cmd *Command, err error)
- func (c *Client) SetLiteralReader(lr LiteralReader) LiteralReader
- func (d Client) SetLogMask(mask LogMask) LogMask
- func (d Client) SetLogger(log *log.Logger) *log.Logger
- func (c *Client) SetQuota(root string, quota ...*Quota) (cmd *Command, err error)
- func (c *Client) StartTLS(config *tls.Config) (cmd *Command, err error)
- func (c *Client) State() ConnState
- func (c *Client) Status(mbox string, items ...string) (cmd *Command, err error)
- func (c *Client) Store(seq *SeqSet, item string, value Field) (cmd *Command, err error)
- func (c *Client) Subscribe(mbox string) (cmd *Command, err error)
- func (c *Client) UIDCopy(seq *SeqSet, mbox string) (cmd *Command, err error)
- func (c *Client) UIDFetch(seq *SeqSet, items ...string) (cmd *Command, err error)
- func (c *Client) UIDMove(seq *SeqSet, mbox string) (cmd *Command, err error)
- func (c *Client) UIDSearch(spec ...Field) (cmd *Command, err error)
- func (c *Client) UIDStore(seq *SeqSet, item string, value Field) (cmd *Command, err error)
- func (c *Client) Unsubscribe(mbox string) (cmd *Command, err error)
- type Command
- type CommandConfig
- type ConnState
- type Field
- type FieldMap
- type FieldType
- type FlagSet
- type Literal
- type LiteralInfo
- type LiteralReader
- type LogMask
- type MailboxInfo
- type MailboxStatus
- type MemoryReader
- type MessageInfo
- type MockServer
- type NotAvailableError
- type ParserError
- type ProtocolError
- type Quota
- type RespStatus
- type RespType
- type Response
- func (rsp *Response) Challenge() []byte
- func (rsp *Response) MailboxFlags() FlagSet
- func (rsp *Response) MailboxInfo() *MailboxInfo
- func (rsp *Response) MailboxStatus() *MailboxStatus
- func (rsp *Response) MessageInfo() *MessageInfo
- func (rsp *Response) Quota() (root string, quota []*Quota)
- func (rsp *Response) QuotaRoot() (mbox string, roots []string)
- func (rsp *Response) SearchResults() []uint32
- func (rsp *Response) String() string
- func (rsp *Response) Value() uint32
- type ResponseError
- type ResponseFilter
- type SASL
- type SeqSet
- func (s *SeqSet) Add(set string) error
- func (s *SeqSet) AddNum(q ...uint32)
- func (s *SeqSet) AddRange(start, stop uint32)
- func (s *SeqSet) AddSet(t *SeqSet)
- func (s *SeqSet) Clear()
- func (s SeqSet) Contains(q uint32) bool
- func (s SeqSet) Dynamic() bool
- func (s SeqSet) Empty() bool
- func (s SeqSet) String() string
- type SeqSetError
- type ServerInfo
Examples ¶
Constants ¶
const ( Login // Not authenticated Auth // Authenticated Selected // Mailbox selected Logout // Connection closing Closed = ConnState(0) // Connection closed )
Client connection states.
const ( Status = RespType(1 << iota) // Untagged status Data // Untagged data Continue // Continuation request Done // Tagged command completion )
Server response types.
const ( OK = RespStatus(1 << iota) // Success NO // Operational error BAD // Protocol-level error PREAUTH // Greeting status indicating Auth state (untagged-only) BYE // Connection closing (untagged-only) )
Status conditions used by Status and Done response types.
const ( Atom = FieldType(1 << iota) // String consisting of non-special ASCII characters Number // Unsigned 32-bit integer QuotedString // String enclosed in double quotes LiteralString // String or binary data List // Parenthesized list Bytes // Decoded Base64 data NIL // Case-insensitive atom string "NIL" )
Valid field data types.
const ( LogConn = LogMask(1 << iota) // Connection events LogState // State changes LogCmd // Command execution LogRaw // Raw data stream excluding literals LogGo // Goroutine execution LogAll = LogMask(1<<iota - 1) // All messages LogNone = LogMask(0) // No messages )
Debug message categories.
const DATETIME = `"_2-Jan-2006 15:04:05 -0700"`
Date-time format used by INTERNALDATE.
Variables ¶
var ( ErrCompressionActive = errors.New("imap: compression already enabled") ErrEncryptionActive = errors.New("imap: encryption already enabled") )
Errors returned by the low-level data transport.
var ( DefaultLogger = log.New(os.Stderr, "[imap] ", log.Ltime) DefaultLogMask = LogNone )
Default debug logging configuration for new Client instances.
var BufferSize = 65536
BufferSize sets the size of the send and receive buffers (in bytes). This is also the length limit of physical lines. In practice, the client should restrict line length to approximately 1000 bytes, as described in RFC 2683.
var ErrAborted = errors.New("imap: command aborted")
ErrAborted is returned by Command.Result when the command execution is interrupted prior to receiving a completion response from the server. This is usually caused by a break in the connection.
var ErrBadUTF7 = errors.New("imap: bad utf-7 encoding")
ErrBadUTF7 is returned to indicate invalid modified UTF-7 encoding.
var ErrExclusive = errors.New("imap: exclusive client access violation")
ErrExclusive is returned when an attempt is made to execute multiple commands in parallel, but one of the commands requires exclusive client access.
var ErrNotAllowed = errors.New("imap: command not allowed in the current state")
ErrNotAllowed is returned when a command cannot be issued in the current connection state. Client.CommandConfig[<name>].States determines valid states for each command.
var ErrTimeout = errors.New("imap: operation timeout")
ErrTimeout is returned when an operation does not finish successfully in the allocated time.
var SelectFilter = LabelFilter(
"FLAGS", "EXISTS", "RECENT",
"UNSEEN", "PERMANENTFLAGS", "UIDNEXT", "UIDVALIDITY",
"UIDNOTSTICKY",
)
SelectFilter accepts SELECT and EXAMINE command responses.
Functions ¶
func AsAtom ¶
AsAtom returns the value of an atom field. An empty string is returned if TypeOf(f) != Atom.
func AsBytes ¶
AsBytes returns the value of a data field. Nil is returned if TypeOf(f)&(QuotedString|LiteralString|Bytes) == 0.
func AsDateTime ¶
AsDateTime returns the value of a date-time quoted string field (e.g. INTERNALDATE). The zero value of time.Time is returned if f does not contain a valid date-time string.
func AsMailbox ¶
AsMailbox returns the value of a mailbox name field. All valid atoms and strings encoded as quoted UTF-8 or modified UTF-7 are decoded appropriately. The special case-insensitive name "INBOX" is always converted to upper case.
func AsNumber ¶
AsNumber returns the value of a numeric field. Zero is returned if TypeOf(f) != Number.
func AsString ¶
AsString returns the value of an astring (string or atom) field. Quoted strings are decoded to their original representation. An empty string is returned if TypeOf(f)&(Atom|QuotedString|LiteralString) == 0 or the string is invalid.
func FetchFilter ¶
FetchFilter accepts FETCH and STORE command responses by matching message sequence numbers or UIDs, depending on the command type. UID matches are more exact because there is no risk of mistaking unilateral server data (e.g. an unsolicited flags update) for command data.
func NameFilter ¶
NameFilter accepts the response if rsp.Label matches the command name.
func Quote ¶
Quote returns the input as a quoted string for use in a command. An empty string is returned if the input cannot be quoted and must be sent as a literal. Setting utf8quoted to true indicates server support for utf8-quoted string format, as described in RFC 5738. The utf8-quoted form will be used only if the input contains non-ASCII characters.
func QuoteBytes ¶
QuoteBytes returns the input as a quoted byte slice. Nil is returned if the input cannot be quoted and must be sent as a literal.
func Quoted ¶
Quoted returns true if a string or []byte appears to contain a quoted string, based on the presence of surrounding double quotes. The string contents are not checked, so it may still contain illegal characters or escape sequences. The string may be encoded in utf8-quoted format, as described in RFC 5738.
func QuotedUTF8 ¶
QuotedUTF8 returns true if a string or []byte appears to contain a quoted string encoded in utf8-quoted format.
func UTF7Decode ¶
UTF7Decode converts a string from modified UTF-7 encoding to UTF-8.
func UTF7DecodeBytes ¶
UTF7DecodeBytes converts a byte slice from modified UTF-7 encoding to UTF-8.
func UTF7Encode ¶
UTF7Encode converts a string from UTF-8 encoding to modified UTF-7. This encoding is used by the Mailbox International Naming Convention (RFC 3501 section 5.1.3). Invalid UTF-8 byte sequences are replaced by the Unicode replacement code point (U+FFFD).
func UTF7EncodeBytes ¶
UTF7EncodeBytes converts a byte slice from UTF-8 encoding to modified UTF-7.
func Unquote ¶
Unquote is the reverse of Quote. An empty string is returned and ok is set to false if the input is not a valid quoted string. RFC 3501 specifications are relaxed to accept all valid UTF-8 encoded strings with or without the use of utf8-quoted format (RFC 5738). Rules disallowing the use of NUL, CR, and LF characters still apply. All (and only) double quote and backslash characters must be escaped with a backslash.
func UnquoteBytes ¶
UnquoteBytes is the reverse of QuoteBytes.
Types ¶
type Client ¶
type Client struct { // FIFO queue for unilateral server data. The first response is the server // greeting. Subsequent responses are those that were rejected by all active // command filters. Commands documented as expecting "no specific responses" // (e.g. NOOP) use nil filters by default, which reject all responses. Data []*Response // Set of current server capabilities. It is updated automatically anytime // new capabilities are received, which could be in a data response or a // status response code. Caps map[string]bool // Status of the selected mailbox. It is set to nil unless the Client is in // the Selected state. The fields are updated automatically as the server // sends solicited and unsolicited status updates. Mailbox *MailboxStatus // Execution parameters of known commands. Client.Send will return an error // if an attempt is made to execute a command whose name does not appear in // this map. The server may not support all commands known to the client. CommandConfig map[string]*CommandConfig // contains filtered or unexported fields }
Client manages a single connection to an IMAP server.
Example ¶
package main import ( "bytes" "fmt" "net/mail" "time" "github.com/mxk/go-imap/imap" ) func main() { // // Note: most of error handling code is omitted for brevity // var ( c *imap.Client cmd *imap.Command rsp *imap.Response ) // Connect to the server c, _ = imap.Dial("imap.example.com") // Remember to log out and close the connection when finished defer c.Logout(30 * time.Second) // Print server greeting (first response in the unilateral server data queue) fmt.Println("Server says hello:", c.Data[0].Info) c.Data = nil // Enable encryption, if supported by the server if c.Caps["STARTTLS"] { c.StartTLS(nil) } // Authenticate if c.State() == imap.Login { c.Login("user@example.com", "mysupersecretpassword") } // List all top-level mailboxes, wait for the command to finish cmd, _ = imap.Wait(c.List("", "%")) // Print mailbox information fmt.Println("\nTop-level mailboxes:") for _, rsp = range cmd.Data { fmt.Println("|--", rsp.MailboxInfo()) } // Check for new unilateral server data responses for _, rsp = range c.Data { fmt.Println("Server data:", rsp) } c.Data = nil // Open a mailbox (synchronous command - no need for imap.Wait) c.Select("INBOX", true) fmt.Print("\nMailbox status:\n", c.Mailbox) // Fetch the headers of the 10 most recent messages set, _ := imap.NewSeqSet("") if c.Mailbox.Messages >= 10 { set.AddRange(c.Mailbox.Messages-9, c.Mailbox.Messages) } else { set.Add("1:*") } cmd, _ = c.Fetch(set, "RFC822.HEADER") // Process responses while the command is running fmt.Println("\nMost recent messages:") for cmd.InProgress() { // Wait for the next response (no timeout) c.Recv(-1) // Process command data for _, rsp = range cmd.Data { header := imap.AsBytes(rsp.MessageInfo().Attrs["RFC822.HEADER"]) if msg, _ := mail.ReadMessage(bytes.NewReader(header)); msg != nil { fmt.Println("|--", msg.Header.Get("Subject")) } } cmd.Data = nil // Process unilateral server data for _, rsp = range c.Data { fmt.Println("Server data:", rsp) } c.Data = nil } // Check command completion status if rsp, err := cmd.Result(imap.OK); err != nil { if err == imap.ErrAborted { fmt.Println("Fetch command aborted") } else { fmt.Println("Fetch error:", rsp.Info) } } }
Output:
func DialTLS ¶
DialTLS returns a new Client connected to an IMAP server at addr using the specified config for encryption.
func NewClient ¶
NewClient returns a new Client instance connected to an IMAP server via conn. The function waits for the server to send a greeting message, and then requests server capabilities if they weren't included in the greeting. An error is returned if either operation fails or does not complete before the timeout, which must be positive to have any effect. If an error is returned, it is the caller's responsibility to close the connection.
func (*Client) Append ¶
func (c *Client) Append(mbox string, flags FlagSet, idate *time.Time, msg Literal) (cmd *Command, err error)
Append appends the literal argument as a new message to the end of the specified destination mailbox. Flags and internal date arguments are optional and may be set to nil.
func (*Client) Auth ¶
Auth performs SASL challenge-response authentication. The client automatically requests new capabilities if authentication is successful.
This command is synchronous.
func (*Client) Capability ¶
Capability requests a listing of capabilities supported by the server. The client automatically requests capabilities when the connection is first established, after a successful STARTTLS command, and after user authentication, making it unnecessary to call this method directly in most cases. The current capabilities are available in c.Caps.
This command is synchronous.
func (*Client) Check ¶
Check requests a checkpoint of the currently selected mailbox. A checkpoint is an implementation detail of the server and may be equivalent to a NOOP.
func (*Client) Close ¶
Close closes the currently selected mailbox, returning the client to the authenticated state. If expunge is true, all messages marked for deletion are permanently removed from the mailbox.
If expunge is false and UNSELECT capability is not advertised, the client issues the EXAMINE command with a non-existent mailbox name. This closes the current mailbox without expunging it, but the "successful" command completion status will be NO instead of OK.
This command is synchronous.
func (*Client) CompressDeflate ¶
CompressDeflate enables data compression using the DEFLATE algorithm. The compression level must be between -1 and 9 (see compress/flate). See RFC 4978 for additional information.
This command is synchronous.
func (*Client) Copy ¶
Copy copies the specified message(s) to the end of the specified destination mailbox.
func (*Client) Delete ¶
Delete permanently removes a mailbox and all of its contents from the server.
func (*Client) Enable ¶
Enable takes a list of capability names and requests the server to enable the named extensions. See RFC 5161 for additional information.
This command is synchronous.
func (*Client) Expunge ¶
Expunge permanently removes all messages that have the \Deleted flag set from the currently selected mailbox. If UIDPLUS capability is advertised, the operation can be restricted to messages with specific UIDs by specifying a non-nil uids argument.
func (*Client) Fetch ¶
Fetch retrieves data associated with the specified message(s) in the mailbox. See RFC 3501 section 6.4.5 for a list of all valid message data items and macros.
func (*Client) GetQuota ¶
GetQuota returns the quota root's resource usage and limits. See RFC 2087 for additional information.
func (*Client) GetQuotaRoot ¶
GetQuotaRoot returns the list of quota roots for the specified mailbox, and the resource usage and limits for each quota root. See RFC 2087 for additional information.
func (*Client) ID ¶
ID provides client identification information to the server. See RFC 2971 for additional information.
func (*Client) Idle ¶
Idle places the client into an idle state where the server is free to send unsolicited mailbox update messages. No other commands are allowed to run while the client is idling. Use c.IdleTerm to terminate the command. See RFC 2177 for additional information.
func (*Client) IdleTerm ¶
IdleTerm terminates the IDLE command. It returns the same Command instance as the original Idle call.
func (*Client) LSub ¶
LSub returns a subset of mailbox names from the set of names that the user has declared as being "active" or "subscribed".
func (*Client) List ¶
List returns a subset of mailbox names from the complete set of all names available to the client.
See RFC 3501 sections 6.3.8 and 7.2.2, and RFC 2683 for detailed information about the LIST and LSUB commands.
func (Client) Log ¶
func (d Client) Log(mask LogMask, v ...interface{})
Log formats its arguments using default formatting, analogous to Print(), and records the text in the debug log if logging is enabled for the specified mask.
func (Client) Logf ¶
Logf formats its arguments according to the format, analogous to Printf(), and records the text in the debug log if logging is enabled for the specified mask.
func (*Client) Login ¶
Login performs plaintext username/password authentication. This command is disabled when the server advertises LOGINDISABLED capability. The client automatically requests new capabilities if authentication is successful.
This command is synchronous.
func (Client) Logln ¶
func (d Client) Logln(mask LogMask, v ...interface{})
Logln formats its arguments using default formatting, analogous to Println(), and records the text in the debug log if logging is enabled for the specified mask.
func (*Client) Logout ¶
Logout informs the server that the client is done with the connection. This method must be called to close the connection and free all client resources.
A negative timeout allows the client to wait indefinitely for the normal logout sequence to complete. A timeout of 0 causes the connection to be closed immediately without actually sending the LOGOUT command. A positive timeout behaves as expected, returning ErrTimeout if the normal logout sequence is not completed in the allocated time. The connection is always closed when this method returns.
This command is synchronous.
func (*Client) Noop ¶
Noop does nothing, but it allows the server to send status updates, which are delivered to the unilateral server data queue (c.Data). It can also be used to reset any inactivity autologout timer on the server.
func (*Client) Quote ¶
Quote attempts to represent v, which must be string, []byte, or fmt.Stringer, as a quoted string for use with Client.Send. A literal string representation is used if v cannot be quoted.
func (*Client) Recv ¶
Recv receives at most one response from the server, updates the client state, and delivers the response to its final destination (c.Data or one of the commands in progress). io.EOF is returned once all responses have been received and the connection is closed.
If the timeout is negative, Recv blocks indefinitely until a response is received or an error is encountered. If the timeout is zero, Recv polls for buffered responses, returning ErrTimeout immediately if none are available. Otherwise, Recv blocks until a response is received or the timeout expires.
func (*Client) Search ¶
Search searches the mailbox for messages that match the given searching criteria. See RFC 3501 section 6.4.4 for a list of all valid search keys. It is the caller's responsibility to quote strings when necessary. All strings must use UTF-8 encoding.
func (*Client) Select ¶
Select opens a mailbox on the server for read-write or read-only access. The EXAMINE command is used when readonly is set to true. However, even when readonly is false, the server may decide not to give read-write access. The server may also change access while the mailbox is open. The current mailbox status is available from c.Mailbox while the client is in the Selected state.
This command is synchronous.
func (*Client) Send ¶
Send issues a new command, returning as soon as the last line is flushed from the send buffer. This may involve waiting for continuation requests if non-synchronizing literals (RFC 2088) are not supported by the server.
This is the raw command interface that does not encode or perform any validation of the supplied fields. It should only be used for implementing new commands that do not change the connection state. For commands already supported by this package, use the provided wrapper methods instead.
func (*Client) SetLiteralReader ¶
func (c *Client) SetLiteralReader(lr LiteralReader) LiteralReader
SetLiteralReader installs a custom LiteralReader implementation into the response receiver pipeline. It returns the previously installed LiteralReader instance.
func (Client) SetLogMask ¶
SetLogMask enables/disables debug message categories and returns the previous mask.
func (Client) SetLogger ¶
SetLogger sets the destination of debug messages and returns the previous logger.
func (*Client) SetQuota ¶
SetQuota changes the resource limits of the specified quota root. See RFC 2087 for additional information.
func (*Client) StartTLS ¶
StartTLS enables session privacy protection and integrity checking. The server must advertise STARTTLS capability for this command to be available. The client automatically requests new capabilities if the TLS handshake is successful.
This command is synchronous.
func (*Client) State ¶
State returns the current connection state (Login, Auth, Selected, Logout, or Closed). See RFC 3501 page 15 for a state diagram. The caller must continue receiving responses until this method returns Closed (same as c.Recv returning io.EOF). Failure to do so may result in memory leaks.
func (*Client) Status ¶
Status requests the status of the indicated mailbox. The currently defined status data items that can be requested are: MESSAGES, RECENT, UIDNEXT, UIDVALIDITY, and UNSEEN. All data items are requested by default.
func (*Client) Subscribe ¶
Subscribe adds the specified mailbox name to the server's set of "active" or "subscribed" mailboxes as returned by the LSUB command.
func (*Client) UIDCopy ¶
UIDCopy is identical to Copy, but the seq argument is interpreted as containing unique identifiers instead of message sequence numbers.
func (*Client) UIDFetch ¶
UIDFetch is identical to Fetch, but the seq argument is interpreted as containing unique identifiers instead of message sequence numbers.
func (*Client) UIDSearch ¶
UIDSearch is identical to Search, but the numbers returned in the response are unique identifiers instead of message sequence numbers.
type Command ¶
type Command struct { // FIFO queue for command data. These are the responses that were accepted // by this command's filter. New responses are appended to the end as they // are received. Data []*Response // contains filtered or unexported fields }
Command represents a single command sent to the server.
func Wait ¶
Wait is a convenience function for transforming asynchronous commands into synchronous ones. The error is nil if and only if the command is completed with OK status condition. Usage example:
cmd, err := imap.Wait(c.Fetch(...))
func (*Command) InProgress ¶
InProgress returns true until the command completion result is available. No new responses will be appended to cmd.Data after this method returns false.
func (*Command) Name ¶
Name returns the command name. If full == true, the UID prefix is included for UID commands.
func (*Command) Result ¶
func (cmd *Command) Result(expect RespStatus) (rsp *Response, err error)
Result returns the command completion result. The call blocks until the command is no longer in progress. If expect != 0, an error is returned if the completion status is other than expected. ErrAborted is returned if the command execution was interrupted prior to receiving a completion response.
type CommandConfig ¶
type CommandConfig struct { States ConnState // Mask of states in which this command may be issued Filter ResponseFilter // Filter for identifying command responses Exclusive bool // Exclusive Client access flag }
CommandConfig specifies command execution parameters.
type ConnState ¶
type ConnState uint8
ConnState represents client connection states. See RFC 3501 page 15 for a state diagram.
type Field ¶
type Field interface{}
Field represents a single data item in a command or response. Fields are separated from one another by a single space. Field slices represent parenthesized lists.
type FieldMap ¶
FieldMap represents key-value pairs of data items, such as those returned in a FETCH response. Key names are atoms converted to upper case.
func AsFieldMap ¶
AsFieldMap returns a map of key-value pairs extracted from a parenthesized list. Nil is returned if TypeOf(f) != List, the number of fields in the list is not even, or one of the keys is not an Atom.
type FieldType ¶
type FieldType uint8
FieldType describes the data type of a single response field.
type FlagSet ¶
FlagSet represents the flags enabled for a single mailbox or message. The map values are always set to true; a flag must be deleted from the map to indicate that it is not enabled.
func AsFlagSet ¶
AsFlags returns a set of flags extracted from a parenthesized list. The function does not check every atom for the leading backslash, because it is not permitted in user-defined flags (keywords). Nil is returned if TypeOf(f) != List or one of the fields is not an atom.
func NewFlagSet ¶
NewFlagSet returns a new flag set with the specified flags enabled.
type Literal ¶
type Literal interface { // WriteTo writes Info().Length bytes to the Writer w. For the default // Literal implementation, use AsString or AsBytes field functions to access // the incoming data directly without copying everything through a Writer. io.WriterTo // Info returns information about the contained literal. Info() LiteralInfo }
Literal represents a single incoming or outgoing literal string, as described in RFC 3501 section 4.3. Incoming literals are constructed by a LiteralReader. The default implementation saves all literals to memory. A custom LiteralReader implementation can save literals directly to files. This could be advantageous when the client is receiving message bodies containing attachments several MB in size. Likewise, a custom Literal implementation can transmit outgoing literals by reading directly from files or other data sources.
func NewLiteral ¶
NewLiteral creates a new literal string from a byte slice. The Literal will point to the same underlying array as the original slice, so it is not safe to modify the array data until the literal has been sent in a command. It is the caller's responsibility to create a copy of the data, if needed.
func NewLiteral8 ¶
NewLiteral8 creates a new binary literal string from a byte slice. This literal is sent using the literal8 syntax, as described in RFC 3516. The server must advertise "BINARY" capability for such literals to be accepted.
type LiteralInfo ¶
type LiteralInfo struct { Len uint32 // Literal octet count Bin bool // RFC 3516 literal8 binary format flag }
LiteralInfo describes the attributes of an incoming or outgoing literal string.
type LiteralReader ¶
type LiteralReader interface {
ReadLiteral(r io.Reader, i LiteralInfo) (Literal, error)
}
LiteralReader is the interface for receiving literal strings from the server.
ReadLiteral reads exactly i.Length bytes from r into a new literal. It must return a Literal instance even when i.Length == 0 (empty string). A return value of (nil, nil) is invalid.
type LogMask ¶
type LogMask uint8
LogMask represents the categories of debug messages that can be logged by the Client.
type MailboxInfo ¶
type MailboxInfo struct { Attrs FlagSet // Mailbox attributes (e.g. `\Noinferiors`, `\Noselect`) Delim string // Hierarchy delimiter (empty string == NIL, i.e. flat name) Name string // Mailbox name decoded to UTF-8 }
MailboxInfo represents the mailbox attributes returned in a LIST or LSUB response.
type MailboxStatus ¶
type MailboxStatus struct { Name string // Mailbox name ReadOnly bool // Mailbox read/write access (client-only) Flags FlagSet // Defined flags in the mailbox (client-only) PermFlags FlagSet // Flags that the client can change permanently (client-only) Messages uint32 // Number of messages in the mailbox Recent uint32 // Number of messages with the \Recent flag set Unseen uint32 // Sequence number of the first unseen message UIDNext uint32 // The next unique identifier value UIDValidity uint32 // The unique identifier validity value UIDNotSticky bool // UIDPLUS extension (client-only) }
MailboxStatus represents the mailbox status information returned in a STATUS response. It is also used by the Client to keep an updated view of the currently selected mailbox. Fields that are only set by the Client are marked as client-only.
func (*MailboxStatus) String ¶
func (m *MailboxStatus) String() string
type MemoryReader ¶
type MemoryReader struct{}
MemoryReader implements the LiteralReader interface by saving all incoming literals to memory.
func (MemoryReader) ReadLiteral ¶
func (MemoryReader) ReadLiteral(r io.Reader, i LiteralInfo) (Literal, error)
type MessageInfo ¶
type MessageInfo struct { Attrs FieldMap // All returned attributes Seq uint32 // Message sequence number UID uint32 // Unique identifier (optional in non-UID FETCH) Flags FlagSet // Flags that are set for this message (optional) InternalDate time.Time // Internal to the server message timestamp (optional) Size uint32 // Message size in bytes (optional) }
MessageInfo represents the message attributes returned in a FETCH response. The values of attributes marked optional are valid only if that attribute also appears in Attrs (e.g. UID is valid if and only if Attrs["UID"] != nil). These attributes are extracted from Attrs purely for convenience.
type MockServer ¶
type MockServer interface { Compressed() bool Encrypted() bool Closed() bool ReadLine() (line []byte, err error) WriteLine(line []byte) error Read(p []byte) (n int, err error) Write(p []byte) (n int, err error) Flush() error EnableDeflate(level int) error EnableTLS(config *tls.Config) error Close(flush bool) error }
MockServer is an internal type exposed for use by the mock package.
func NewMockServer ¶
func NewMockServer(conn net.Conn) MockServer
NewMockServer is an internal function exposed for use by the mock package.
type NotAvailableError ¶
type NotAvailableError string
NotAvailableError is returned when the requested command, feature, or capability is not supported by the client and/or server. The error may be temporary. For example, servers should disable the LOGIN command by advertising LOGINDISABLED capability while the connection is unencrypted. Enabling encryption via STARTTLS should allow the use of LOGIN.
func (NotAvailableError) Error ¶
func (err NotAvailableError) Error() string
type ParserError ¶
type ParserError struct { Info string // Short message explaining the problem Line []byte // Full or partial response line, starting with the tag Offset int // Parser offset, starting at 0 }
ParserError indicates a problem with the server response format. This could be the result of an unsupported extension or nonstandard server behavior.
func (*ParserError) Error ¶
func (err *ParserError) Error() string
type ProtocolError ¶
type ProtocolError struct { Info string // Short message explaining the problem Line []byte // Full or partial command/response line }
ProtocolError indicates a low-level problem with the data being sent by the client or server.
func (*ProtocolError) Error ¶
func (err *ProtocolError) Error() string
type Quota ¶
type Quota struct { Resource string // Resource name (e.g. STORAGE, MESSAGE) Usage uint32 // Current usage (in units of 1024 octets for STORAGE) Limit uint32 // Current limit }
Quota represents a single resource limit on a mailbox quota root returned in a QUOTA response, as described in RFC 2087.
type RespStatus ¶
type RespStatus uint8
RespStatus is the code sent in status messages to indicate success, failure, or changes in the connection state.
func (RespStatus) GoString ¶
func (v RespStatus) GoString() string
func (RespStatus) String ¶
func (v RespStatus) String() string
type RespType ¶
type RespType uint8
RespType indicates the type of information contained in the response.
type Response ¶
type Response struct { // Order in which this response was received, starting at 1 for the server // greeting. Order int64 // Original response line from which this Response object was constructed. // Literal strings and CRLFs are omitted. Raw []byte // All literal strings in the order they were received. Do not assume that a // FETCH request for BODY[], for example, will return exactly one literal // with the requested data. Use the decoder methods, or navigate Fields // according to the response format, to get the desired information. Literals []Literal // Response tag ("*", "+", or command tag). Tag string // Response type (Status, Data, Continue, or Done). Type RespType // Status condition if Type is Status or Done (OK, NO, BAD, PREAUTH, or // BYE). Only OK, NO, and BAD may be used in tagged (Done) responses. Status RespStatus // Human-readable text portion of a Status, Continue, or Done response, or // the original Base64 text of a challenge-response authentication request. Info string // First atom in Fields (usually index 0 or 1) converted to upper case. This // determines the format of Fields, as described in RFC 3501 section 7. A // Continue response containing Base64 data is labeled "BASE64". Label string // Data or response code fields extracted by the parser. For a Data // response, this is everything after the "*" tag. For a Status or Done // response, this is the response code (if there is one). For a Continue // response with a "BASE64" Label, Fields[0] is the decoded byte slice. Fields []Field // Cached decoder output. This is used by the decoder methods to avoid // traversing Fields multiple times. User code should not modify or access // this field except when writing a custom decoder (see response.go for // examples). Decoded interface{} }
Response represents a single status, data, or command continuation response. All response types are parsed into the same general format, which can then be decoded to more specific representations either by calling the provided decoder methods, or by manually navigating Fields and other attributes. Here are a few examples of the parser output:
S: * CAPABILITY IMAP4rev1 STARTTLS AUTH=GSSAPI S: * OK [UNSEEN 12] Message 12 is first unseen S: A142 OK [read-write] SELECT completed Response objects: &imap.Response{ Raw: []byte("* CAPABILITY IMAP4rev1 STARTTLS AUTH=GSSAPI"), Tag: "*", Type: imap.Data, Label: "CAPABILITY", Fields: []Field{"CAPABILITY", "IMAP4rev1", "STARTTLS", "AUTH=GSSAPI"}, } &imap.Response{ Raw: []byte("* OK [UNSEEN 12] Message 12 is first unseen"), Tag: "*", Type: imap.Status, Status: imap.OK, Info: "Message 12 is first unseen", Label: "UNSEEN", Fields: []Field{"UNSEEN", uint32(12)}, } &imap.Response{ Raw: []byte("A142 OK [read-write] SELECT completed"), Tag: "A142", Type: imap.Done, Status: imap.OK, Info: "SELECT completed", Label: "READ-WRITE", Fields: []Field{"read-write"}, }
func (*Response) Challenge ¶
Challenge returns the decoded Base64 data from a continuation request sent during challenge-response authentication.
func (*Response) MailboxFlags ¶
MailboxFlags returns a FlagSet extracted from a FLAGS or PERMANENTFLAGS response. Note that FLAGS is a Data response, while PERMANENTFLAGS is Status.
func (*Response) MailboxInfo ¶
func (rsp *Response) MailboxInfo() *MailboxInfo
MailboxInfo returns the mailbox attributes extracted from a LIST or LSUB response.
func (*Response) MailboxStatus ¶
func (rsp *Response) MailboxStatus() *MailboxStatus
MailboxStatus returns the mailbox status information extracted from a STATUS response.
func (*Response) MessageInfo ¶
func (rsp *Response) MessageInfo() *MessageInfo
MessageInfo returns the message attributes extracted from a FETCH response.
func (*Response) QuotaRoot ¶
QuotaRoot returns the mailbox name and associated quota roots from a QUOTAROOT response.
func (*Response) SearchResults ¶
SearchResults returns a slice of message sequence numbers or UIDs extracted from a SEARCH response.
type ResponseError ¶
ResponseError wraps a Response pointer for use in an error context, such as when a command fails with a NO or BAD status condition. For Status and Done response types, the value of Response.Info may be presented to the user. Reason provides additional information about the cause of the error.
func (ResponseError) Error ¶
func (rsp ResponseError) Error() string
type ResponseFilter ¶
ResponseFilter defines the signature of functions that determine response ownership. The function returns true if rsp belongs to cmd. A nil filter rejects all responses. A response that is rejected by all active filters is considered to be unilateral server data.
func LabelFilter ¶
func LabelFilter(labels ...string) ResponseFilter
LabelFilter returns a new filter configured to accept responses with the specified labels.
type SASL ¶
type SASL interface { // Start begins SASL authentication with the server. It returns the // authentication mechanism name and "initial response" data (if required by // the selected mechanism). A non-nil error causes the client to abort the // authentication attempt. // // A nil ir value is different from a zero-length value. The nil value // indicates that the selected mechanism does not use an initial response, // while a zero-length value indicates an empty initial response, which must // be sent to the server. Start(s *ServerInfo) (mech string, ir []byte, err error) // Next continues challenge-response authentication. A non-nil error causes // the client to abort the authentication attempt. Next(challenge []byte) (response []byte, err error) }
SASL is the interface for performing challenge-response authentication.
func ExternalAuth ¶
ExternalAuth returns an implementation of the EXTERNAL authentication mechanism, as described in RFC 4422. Authorization identity may be left blank to indicate that the client is requesting to act as the identity associated with the authentication credentials.
type SeqSet ¶
type SeqSet struct {
// contains filtered or unexported fields
}
SeqSet is used to represent a set of message sequence numbers or UIDs (see sequence-set ABNF rule). The zero value is an empty set.
func (*SeqSet) Add ¶
Add inserts new sequence values into the set. The string format is described by RFC 3501 sequence-set ABNF rule. If an error is encountered, all values inserted successfully prior to the error remain in the set.
func (*SeqSet) AddNum ¶
AddNum inserts new sequence numbers into the set. The value 0 represents "*".
func (SeqSet) Contains ¶
Contains returns true if the non-zero sequence number or UID q is contained in the set. The dynamic range "n:*" contains all q >= n. It is the caller's responsibility to handle the special case where q is the maximum UID in the mailbox and q < n (i.e. the set cannot match UIDs against "*:n" or "*" since it doesn't know what the maximum value is).
type SeqSetError ¶
type SeqSetError string
SeqSetError is used to report problems with the format of a sequence set value.
func (SeqSetError) Error ¶
func (err SeqSetError) Error() string
type ServerInfo ¶
type ServerInfo struct { Name string // Server name TLS bool // Encryption status Auth []string // Supported authentication mechanisms }
ServerInfo contains information about the IMAP server with which SASL authentication is about to be attempted.