imap

package module
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 27, 2020 License: MIT Imports: 15 Imported by: 0

README

go-imap

GoDoc Build Status Codecov Go Report Card Unstable Gitter chat

An IMAP4rev1 library written in Go. It can be used to build a client and/or a server.

go get github.com/mailgun/go-imap/...

Why?

Other IMAP implementations in Go:

  • Require to make many type assertions or conversions
  • Are not idiomatic or are ugly
  • Are not pleasant to use
  • Implement a server xor a client, not both
  • Don't implement unilateral updates (i.e. the server can't notify clients for new messages)
  • Do not have a good test coverage
  • Don't handle encoding and charset automatically

Usage

Client GoDoc
package main

import (
	"log"

	"github.com/mailgun/go-imap/client"
	"github.com/mailgun/go-imap"
)

func main() {
	log.Println("Connecting to server...")

	// Connect to server
	c, err := client.DialTLS("mail.example.org:993", nil)
	if err != nil {
		log.Fatal(err)
	}
	log.Println("Connected")

	// Don't forget to logout
	defer c.Logout()

	// Login
	if err := c.Login("username", "password"); err != nil {
		log.Fatal(err)
	}
	log.Println("Logged in")

	// List mailboxes
	mailboxes := make(chan *imap.MailboxInfo, 10)
	done := make(chan error, 1)
	go func () {
		done <- c.List("", "*", mailboxes)
	}()

	log.Println("Mailboxes:")
	for m := range mailboxes {
		log.Println("* " + m.Name)
	}

	if err := <-done; err != nil {
		log.Fatal(err)
	}

	// Select INBOX
	mbox, err := c.Select("INBOX", false)
	if err != nil {
		log.Fatal(err)
	}
	log.Println("Flags for INBOX:", mbox.Flags)

	// Get the last 4 messages
	from := uint32(1)
	to := mbox.Messages
	if mbox.Messages > 3 {
		// We're using unsigned integers here, only substract if the result is > 0
		from = mbox.Messages - 3
	}
	seqset := new(imap.SeqSet)
	seqset.AddRange(from, to)

	messages := make(chan *imap.Message, 10)
	done = make(chan error, 1)
	go func() {
		done <- c.Fetch(seqset, []string{imap.EnvelopeMsgAttr}, messages)
	}()

	log.Println("Last 4 messages:")
	for msg := range messages {
		log.Println("* " + msg.Envelope.Subject)
	}

	if err := <-done; err != nil {
		log.Fatal(err)
	}

	log.Println("Done!")
}
Server GoDoc
package main

import (
	"log"

	"github.com/mailgun/go-imap/server"
	"github.com/mailgun/go-imap/backend/memory"
)

func main() {
	// Create a memory backend
	be := memory.New()

	// Create a new server
	s := server.New(be)
	s.Addr = ":1143"
	// Since we will use this server for testing only, we can allow plain text
	// authentication over unencrypted connections
	s.AllowInsecureAuth = true

	log.Println("Starting IMAP server at localhost:1143")
	if err := s.ListenAndServe(); err != nil {
		log.Fatal(err)
	}
}

You can now use telnet localhost 1143 to manually connect to the server.

Extending go-imap

Extensions

Commands defined in IMAP extensions are available in other packages. See the wiki to learn how to use them.

Server backends
  • go-message - parsing and formatting MIME and mail messages
  • go-pgpmail - decrypting and encrypting mails with OpenPGP
  • go-sasl - sending and receiving SASL authentications
  • go-smtp - building SMTP clients and servers
  • go-dkim - creating and verifying DKIM signatures

License

MIT

Documentation

Overview

Package imap implements IMAP4rev1 (RFC 3501).

Index

Constants

View Source
const (
	Capability string = "CAPABILITY"
	Noop              = "NOOP"
	Logout            = "LOGOUT"
	StartTLS          = "STARTTLS"

	Authenticate = "AUTHENTICATE"
	Login        = "LOGIN"

	Select      = "SELECT"
	Examine     = "EXAMINE"
	Create      = "CREATE"
	Delete      = "DELETE"
	Rename      = "RENAME"
	Subscribe   = "SUBSCRIBE"
	Unsubscribe = "UNSUBSCRIBE"
	List        = "LIST"
	Lsub        = "LSUB"
	Status      = "STATUS"
	Append      = "APPEND"

	Check   = "CHECK"
	Close   = "CLOSE"
	Expunge = "EXPUNGE"
	Search  = "SEARCH"
	Fetch   = "FETCH"
	Store   = "STORE"
	Copy    = "COPY"
	Uid     = "UID"
)

IMAP4rev1 commands.

View Source
const (
	// In the connecting state, the server has not yet sent a greeting and no
	// command can be issued.
	ConnectingState = 0

	// In the not authenticated state, the client MUST supply
	// authentication credentials before most commands will be
	// permitted.  This state is entered when a connection starts
	// unless the connection has been pre-authenticated.
	NotAuthenticatedState ConnState = 1 << 0

	// In the authenticated state, the client is authenticated and MUST
	// select a mailbox to access before commands that affect messages
	// will be permitted.  This state is entered when a
	// pre-authenticated connection starts, when acceptable
	// authentication credentials have been provided, after an error in
	// selecting a mailbox, or after a successful CLOSE command.
	AuthenticatedState = 1 << 1

	// In a selected state, a mailbox has been selected to access.
	// This state is entered when a mailbox has been successfully
	// selected.
	SelectedState = AuthenticatedState + 1<<2

	// In the logout state, the connection is being terminated. This
	// state can be entered as a result of a client request (via the
	// LOGOUT command) or by unilateral action on the part of either
	// the client or server.
	LogoutState = 1 << 3

	// ConnectedState is either NotAuthenticatedState, AuthenticatedState or
	// SelectedState.
	ConnectedState = NotAuthenticatedState | AuthenticatedState | SelectedState
)
View Source
const (
	// Defined in RFC 3501 as date-text on page 83.
	DateLayout = "_2-Jan-2006"
	// Defined in RFC 3501 as date-time on page 83.
	DateTimeLayout = "_2-Jan-2006 15:04:05 -0700"
)

Date and time layouts. Dovecot adds a leading zero to dates:

https://github.com/dovecot/core/blob/4fbd5c5e113078e72f29465ccc96d44955ceadc2/src/lib-imap/imap-date.c#L166

Cyrus adds a leading space to dates:

https://github.com/cyrusimap/cyrus-imapd/blob/1cb805a3bffbdf829df0964f3b802cdc917e76db/lib/times.c#L543

GMail doesn't support leading spaces in dates used in SEARCH commands.

View Source
const (
	// SetFlags replaces existing flags by new ones.
	SetFlags FlagsOp = "FLAGS"
	// AddFlags adds new flags.
	AddFlags = "+FLAGS"
	// RemoveFlags removes existing flags.
	RemoveFlags = "-FLAGS"
)
View Source
const (
	// It is not possible for any child levels of hierarchy to exist under this\
	// name; no child levels exist now and none can be created in the future.
	NoInferiorsAttr = "\\Noinferiors"
	// It is not possible to use this name as a selectable mailbox.
	NoSelectAttr = "\\Noselect"
	// The mailbox has been marked "interesting" by the server; the mailbox
	// probably contains messages that have been added since the last time the
	// mailbox was selected.
	MarkedAttr = "\\Marked"
	// The mailbox does not contain any additional messages since the last time
	// the mailbox was selected.
	UnmarkedAttr = "\\Unmarked"
)

Mailbox attributes definied in RFC 3501 section 7.2.2.

View Source
const (
	MailboxFlags          = "FLAGS"
	MailboxPermanentFlags = "PERMANENTFLAGS"

	// Defined in RFC 3501 section 6.3.10.
	MailboxMessages    = "MESSAGES"
	MailboxRecent      = "RECENT"
	MailboxUnseen      = "UNSEEN"
	MailboxUidNext     = "UIDNEXT"
	MailboxUidValidity = "UIDVALIDITY"
)

Mailbox status items.

View Source
const (
	SeenFlag     = "\\Seen"
	AnsweredFlag = "\\Answered"
	FlaggedFlag  = "\\Flagged"
	DeletedFlag  = "\\Deleted"
	DraftFlag    = "\\Draft"
	RecentFlag   = "\\Recent"
)

Message flags, defined in RFC 3501 section 2.3.2.

View Source
const (
	// Non-extensible form of BODYSTRUCTURE.
	BodyMsgAttr = "BODY"
	// MIME body structure of the message.
	BodyStructureMsgAttr = "BODYSTRUCTURE"
	// The envelope structure of the message.
	EnvelopeMsgAttr = "ENVELOPE"
	// The flags that are set for the message.
	FlagsMsgAttr = "FLAGS"
	// The internal date of the message.
	InternalDateMsgAttr = "INTERNALDATE"
	// The RFC 822 size of the message.
	SizeMsgAttr = "RFC822.SIZE"
	// The unique identifier for the message.
	UidMsgAttr = "UID"
)

Message attributes that can be fetched, defined in RFC 3501 section 6.4.5. Attributes that fetches the message contents are defined with BodySectionName.

View Source
const (
	// Refers to the entire part, including headers.
	EntireSpecifier = ""
	// Refers to the header of the part. Must include the final CRLF delimiting
	// the header and the body.
	HeaderSpecifier = "HEADER"
	// Refers to the text body of the part, omitting the header.
	TextSpecifier = "TEXT"
	// Refers to the MIME Internet Message Body header.  Must include the final
	// CRLF delimiting the header and the body.
	MimeSpecifier = "MIME"
)

Part specifiers described in RFC 3501 page 55.

View Source
const (
	// The OK response indicates an information message from the server.  When
	// tagged, it indicates successful completion of the associated command.
	// The untagged form indicates an information-only message.
	StatusOk StatusRespType = "OK"

	// The NO response indicates an operational error message from the
	// server.  When tagged, it indicates unsuccessful completion of the
	// associated command.  The untagged form indicates a warning; the
	// command can still complete successfully.
	StatusNo = "NO"

	// The BAD response indicates an error message from the server.  When
	// tagged, it reports a protocol-level error in the client's command;
	// the tag indicates the command that caused the error.  The untagged
	// form indicates a protocol-level error for which the associated
	// command can not be determined; it can also indicate an internal
	// server failure.
	StatusBad = "BAD"

	// The PREAUTH response is always untagged, and is one of three
	// possible greetings at connection startup.  It indicates that the
	// connection has already been authenticated by external means; thus
	// no LOGIN command is needed.
	StatusPreauth = "PREAUTH"

	// The BYE response is always untagged, and indicates that the server
	// is about to close the connection.
	StatusBye = "BYE"
)

Status response types defined in RFC 3501 section 7.1.

View Source
const (
	CodeAlert          = "ALERT"
	CodeBadCharset     = "BADCHARSET"
	CodeCapability     = "CAPABILITY"
	CodeParse          = "PARSE"
	CodePermanentFlags = "PERMANENTFLAGS"
	CodeReadOnly       = "READ-ONLY"
	CodeReadWrite      = "READ-WRITE"
	CodeTryCreate      = "TRYCREATE"
	CodeUidNext        = "UIDNEXT"
	CodeUidValidity    = "UIDVALIDITY"
	CodeUnseen         = "UNSEEN"
)

Status response codes defined in RFC 3501 section 7.1.

View Source
const InboxName = "INBOX"

The primary mailbox, as defined in RFC 3501 section 5.1.

View Source
const SilentOp = ".SILENT"

SilentOp can be appended to a FlagsOp to prevent the operation from triggering unilateral message updates.

Variables

View Source
var CharsetReader func(charset string, r io.Reader) (io.Reader, error)

CharsetReader, if non-nil, defines a function to generate charset-conversion readers, converting from the provided charset into UTF-8. Charsets are always lower-case. utf-8 and us-ascii charsets are handled by default. One of the the CharsetReader's result values must be non-nil.

Functions

func CanonicalFlag

func CanonicalFlag(flag string) string

Returns the canonical form of a flag. Flags are case-insensitive.

If the flag is defined in RFC 3501, it returns the flag with the case of the RFC. Otherwise, it returns the lowercase version of the flag.

func CanonicalMailboxName

func CanonicalMailboxName(name string) string

Returns the canonical form of a mailbox name. Mailbox names can be case-sensitive or case-insensitive depending on the backend implementation. The special INBOX mailbox is case-insensitive.

func FormatAddressList

func FormatAddressList(addrs []*Address) (fields []interface{})

Format an address list to fields.

func FormatParamList

func FormatParamList(params map[string]string) []interface{}

func FormatStringList

func FormatStringList(list []string) (fields []interface{})

Convert a string list to a field list.

func IsParseError

func IsParseError(err error) bool

IsParseError returns true if the provided error is a parse error produced by Reader.

func NewDebugWriter

func NewDebugWriter(local, remote io.Writer) io.Writer

NewDebugWriter creates a new io.Writer that will write local network activity to local and remote network activity to remote.

func ParseNumber

func ParseNumber(f interface{}) (uint32, error)

Convert a field to a number.

func ParseParamList

func ParseParamList(fields []interface{}) (map[string]string, error)

func ParseStringList

func ParseStringList(f interface{}) ([]string, error)

Convert a field list to a string list.

func ReadResp

func ReadResp(r *Reader) (out interface{}, err error)

Read a single response from a Reader. Returns either a continuation request, a status response or a raw response.

Types

type Address

type Address struct {
	// The personal name.
	PersonalName string
	// The SMTP at-domain-list (source route).
	AtDomainList string
	// The mailbox name.
	MailboxName string
	// The host name.
	HostName string
}

An address.

func ParseAddressList

func ParseAddressList(fields []interface{}) (addrs []*Address)

Parse an address list from fields.

func (*Address) Format

func (addr *Address) Format() []interface{}

Format an address to fields.

func (*Address) Parse

func (addr *Address) Parse(fields []interface{}) error

Parse an address from fields.

type BodyPartName

type BodyPartName struct {
	// The specifier of the requested part.
	Specifier string
	// The part path. Parts indexes start at 1.
	Path []int
	// If Specifier is HEADER, contains header fields that will/won't be returned,
	// depending of the value of NotFields.
	Fields []string
	// If set to true, Fields is a blacklist of fields instead of a whitelist.
	NotFields bool
}

A body part name.

func (*BodyPartName) String

func (part *BodyPartName) String() (s string)

type BodySectionName

type BodySectionName struct {
	*BodyPartName

	// If set to true, do not implicitly set the \Seen flag.
	Peek bool
	// The substring of the section requested. The first value is the position of
	// the first desired octet and the second value is the maximum number of
	// octets desired.
	Partial []int
	// contains filtered or unexported fields
}

A body section name. See RFC 3501 page 55.

func NewBodySectionName

func NewBodySectionName(s string) (section *BodySectionName, err error)

Parse a body section name.

func (*BodySectionName) ExtractPartial

func (section *BodySectionName) ExtractPartial(b []byte) []byte

Returns a subset of the specified bytes matching the partial requested in the section name.

func (*BodySectionName) String

func (section *BodySectionName) String() (s string)

type BodyStructure

type BodyStructure struct {

	// The MIME type.
	MimeType string
	// The MIME subtype.
	MimeSubType string
	// The MIME parameters.
	Params map[string]string

	// The Content-Id header.
	Id string
	// The Content-Description header.
	Description string
	// The Content-Encoding header.
	Encoding string
	// The Content-Length header.
	Size uint32

	// The children parts, if multipart.
	Parts []*BodyStructure
	// The envelope, if message/rfc822.
	Envelope *Envelope
	// The body structure, if message/rfc822.
	BodyStructure *BodyStructure
	// The number of lines, if text or message/rfc822.
	Lines uint32

	// True if the body structure contains extension data.
	Extended bool

	// The Content-Disposition header field value.
	Disposition string
	// The Content-Disposition header field parameters.
	DispositionParams map[string]string
	// The Content-Language header field, if multipart.
	Language []string
	// The content URI, if multipart.
	Location []string

	// The MD5 checksum.
	Md5 string
}

A body structure. See RFC 3501 page 74.

func (*BodyStructure) Format

func (bs *BodyStructure) Format() (fields []interface{})

func (*BodyStructure) Parse

func (bs *BodyStructure) Parse(fields []interface{}) error

type Command

type Command struct {
	// The command tag. It acts as a unique identifier for this command. If empty,
	// the command is untagged.
	Tag string
	// The command name.
	Name string
	// The command arguments.
	Arguments []interface{}
}

A command.

func (*Command) Command

func (cmd *Command) Command() *Command

Implements the Commander interface.

func (*Command) Parse

func (cmd *Command) Parse(fields []interface{}) error

Parse a command from fields.

func (*Command) WriteTo

func (cmd *Command) WriteTo(w *Writer) error

type Commander

type Commander interface {
	Command() *Command
}

A value that can be converted to a command.

type Conn

type Conn struct {
	net.Conn
	*Reader
	*Writer
	// contains filtered or unexported fields
}

An IMAP connection.

func NewConn

func NewConn(conn net.Conn, r *Reader, w *Writer) *Conn

NewConn creates a new IMAP connection.

func (*Conn) Flush

func (c *Conn) Flush() error

Flush writes any buffered data to the underlying connection.

func (*Conn) SetDebug

func (c *Conn) SetDebug(w io.Writer)

SetDebug defines an io.Writer to which all network activity will be logged. If nil is provided, network activity will not be logged.

func (*Conn) Upgrade

func (c *Conn) Upgrade(upgrader ConnUpgrader) error

Upgrade a connection, e.g. wrap an unencrypted connection with an encrypted tunnel.

func (*Conn) Wait

func (c *Conn) Wait()

Wait waits for the connection to be ready for reads and writes.

func (*Conn) Write

func (c *Conn) Write(b []byte) (n int, err error)

Write implements io.Writer.

type ConnState

type ConnState int

A connection state. See RFC 3501 section 3.

type ConnUpgrader

type ConnUpgrader func(conn net.Conn) (net.Conn, error)

A function that upgrades a connection.

This should only be used by libraries implementing an IMAP extension (e.g. COMPRESS).

type ContinuationResp

type ContinuationResp struct {
	// The info message sent with the continuation request.
	Info string
}

A continuation request.

func (*ContinuationResp) WriteTo

func (r *ContinuationResp) WriteTo(w *Writer) error

type Date

type Date time.Time

time.Time with a specific layout.

type DateTime

type DateTime time.Time

time.Time with a specific layout.

type Envelope

type Envelope struct {
	// The message date.
	Date time.Time
	// The message subject.
	Subject string
	// The From header addresses.
	From []*Address
	// The message senders.
	Sender []*Address
	// The Reply-To header addresses.
	ReplyTo []*Address
	// The To header addresses.
	To []*Address
	// The Cc header addresses.
	Cc []*Address
	// The Bcc header addresses.
	Bcc []*Address
	// The In-Reply-To header. Contains the parent Message-Id.
	InReplyTo string
	// The Message-Id header.
	MessageId string
}

A message envelope, ie. message metadata from its headers. See RFC 3501 page 77.

func (*Envelope) Format

func (e *Envelope) Format() (fields []interface{})

Format an envelope to fields.

func (*Envelope) Parse

func (e *Envelope) Parse(fields []interface{}) error

Parse an envelope from fields.

type ErrBadSeqSet

type ErrBadSeqSet string

ErrBadSeqSet is used to report problems with the format of a sequence set value.

func (ErrBadSeqSet) Error

func (err ErrBadSeqSet) Error() string

type FlagsOp

type FlagsOp string

FlagsOp is an operation that will be applied on message flags.

type Literal

type Literal interface {
	io.Reader

	// Len returns the number of bytes of the literal.
	Len() int
}

A literal, as defined in RFC 3501 section 4.3.

type Logger

type Logger interface {
	Printf(format string, v ...interface{})
	Println(v ...interface{})
}

Logger is the behaviour used by server/client to report errors for accepting connections and unexpected behavior from handlers.

type MailboxInfo

type MailboxInfo struct {
	// The mailbox attributes.
	Attributes []string
	// The server's path separator.
	Delimiter string
	// The mailbox name.
	Name string
}

Basic mailbox info.

func (*MailboxInfo) Format

func (info *MailboxInfo) Format() []interface{}

Format mailbox info to fields.

func (*MailboxInfo) Match

func (info *MailboxInfo) Match(reference, pattern string) bool

Match checks if a reference and a pattern matches this mailbox name, as defined in RFC 3501 section 6.3.8.

func (*MailboxInfo) Parse

func (info *MailboxInfo) Parse(fields []interface{}) error

Parse mailbox info from fields.

type MailboxStatus

type MailboxStatus struct {
	// The mailbox name.
	Name string
	// True if the mailbox is open in read-only mode.
	ReadOnly bool
	// The mailbox items that are currently filled in. This map's values
	// should not be used directly, they must only be used by libraries
	// implementing extensions of the IMAP protocol.
	Items map[string]interface{}

	// The Items map may be accessed in different goroutines. Protect
	// concurrent writes.
	ItemsLocker sync.Mutex

	// The mailbox flags.
	Flags []string
	// The mailbox permanent flags.
	PermanentFlags []string

	// The number of messages in this mailbox.
	Messages uint32
	// The number of messages not seen since the last time the mailbox was opened.
	Recent uint32
	// The number of unread messages.
	Unseen uint32
	// The next UID.
	UidNext uint32
	// Together with a UID, it is a unique identifier for a message.
	// Must be greater than or equal to 1.
	UidValidity uint32
}

A mailbox status.

func NewMailboxStatus

func NewMailboxStatus(name string, items []string) *MailboxStatus

Create a new mailbox status that will contain the specified items.

func (*MailboxStatus) Format

func (status *MailboxStatus) Format() []interface{}

func (*MailboxStatus) Parse

func (status *MailboxStatus) Parse(fields []interface{}) error

type Message

type Message struct {
	// The message sequence number. It must be greater than or equal to 1.
	SeqNum uint32
	// The mailbox items that are currently filled in. This map's values
	// should not be used directly, they must only be used by libraries
	// implementing extensions of the IMAP protocol.
	Items map[string]interface{}

	// The message envelope.
	Envelope *Envelope
	// The message body structure (either BODYSTRUCTURE or BODY).
	BodyStructure *BodyStructure
	// The message flags.
	Flags []string
	// The date the message was received by the server.
	InternalDate time.Time
	// The message size.
	Size uint32
	// The message unique identifier. It must be greater than or equal to 1.
	Uid uint32
	// The message body sections.
	Body map[*BodySectionName]Literal
	// contains filtered or unexported fields
}

A message.

func NewMessage

func NewMessage(seqNum uint32, items []string) *Message

Create a new empty message that will contain the specified items.

func (*Message) Format

func (m *Message) Format() []interface{}

func (*Message) GetBody

func (m *Message) GetBody(s string) Literal

Get the body section with the specified name. Returns nil if it's not found.

func (*Message) Parse

func (m *Message) Parse(fields []interface{}) error

Parse a message from fields.

type MultiRespHandler

type MultiRespHandler struct {
	// contains filtered or unexported fields
}

A RespHandlerFrom that forwards responses to multiple RespHandler.

func NewMultiRespHandler

func NewMultiRespHandler() *MultiRespHandler

func (*MultiRespHandler) Add

func (mh *MultiRespHandler) Add(hdlr RespHandler)

func (*MultiRespHandler) Del

func (mh *MultiRespHandler) Del(hdlr RespHandler)

func (*MultiRespHandler) HandleFrom

func (mh *MultiRespHandler) HandleFrom(ch RespHandler) error

type Parser

type Parser interface {
	Parse(fields []interface{}) error
}

type Quoted

type Quoted string

A string that will be quoted.

type Reader

type Reader struct {
	MaxLiteralSize uint32 // The maximum literal size.
	// contains filtered or unexported fields
}

An IMAP reader.

func NewReader

func NewReader(r reader) *Reader

func NewServerReader

func NewServerReader(r reader, continues chan<- bool) *Reader

func (*Reader) ReadAtom

func (r *Reader) ReadAtom() (interface{}, error)

func (*Reader) ReadCrlf

func (r *Reader) ReadCrlf() (err error)

func (*Reader) ReadFields

func (r *Reader) ReadFields() (fields []interface{}, err error)

func (*Reader) ReadInfo

func (r *Reader) ReadInfo() (info string, err error)

func (*Reader) ReadLine

func (r *Reader) ReadLine() (fields []interface{}, err error)

func (*Reader) ReadList

func (r *Reader) ReadList() (fields []interface{}, err error)

func (*Reader) ReadLiteral

func (r *Reader) ReadLiteral() (Literal, error)

func (*Reader) ReadQuotedString

func (r *Reader) ReadQuotedString() (string, error)

func (*Reader) ReadRespCode

func (r *Reader) ReadRespCode() (code string, fields []interface{}, err error)

func (*Reader) ReadSp

func (r *Reader) ReadSp() error

type Resp

type Resp struct {
	// The response tag. Can be either "" for untagged responses, "+" for continuation
	// requests or a previous command's tag.
	Tag string
	// The parsed response fields.
	Fields []interface{}
}

A response. See RFC 3501 section 2.2.2

func NewUntaggedResp

func NewUntaggedResp(fields []interface{}) *Resp

Create a new untagged response.

func (*Resp) WriteTo

func (r *Resp) WriteTo(w *Writer) error

type RespHandle

type RespHandle struct {
	Resp    interface{}
	Accepts chan bool
}

A response that can be either accepted or rejected by a handler.

func (*RespHandle) Accept

func (h *RespHandle) Accept()

Accept this response. This means that the handler will process it.

func (*RespHandle) AcceptNamedResp

func (h *RespHandle) AcceptNamedResp(name string) (fields []interface{}, accepted bool)

Accept this response if it has the specified name. If not, reject it.

func (*RespHandle) Reject

func (h *RespHandle) Reject()

Reject this response. The handler cannot process it.

type RespHandler

type RespHandler chan *RespHandle

Delivers responses to handlers.

type RespHandlerFrom

type RespHandlerFrom interface {
	HandleFrom(hdlr RespHandler) error
}

Handles responses from a handler.

type Responser

type Responser interface {
	Response() *Resp
}

A value that can be converted to a Resp.

type SearchCriteria

type SearchCriteria struct {
	SeqNum *SeqSet // Sequence number is in sequence set
	Uid    *SeqSet // UID is in sequence set

	// Time and timezone are ignored
	Since      time.Time // Internal date is since this date
	Before     time.Time // Internal date is before this date
	SentSince  time.Time // Date header field is since this date
	SentBefore time.Time // Date header field is before this date

	Header textproto.MIMEHeader // Each header field value is present
	Body   []string             // Each string is in the body
	Text   []string             // Each string is in the text (header + body)

	WithFlags    []string // Each flag is present
	WithoutFlags []string // Each flag is not present

	Larger  uint32 // Size is larger than this number
	Smaller uint32 // Size is smaller than this number

	Not []*SearchCriteria    // Each criteria doesn't match
	Or  [][2]*SearchCriteria // Each criteria pair has at least one match of two
}

SearchCriteria is a search criteria. A message matches the criteria if and only if it matches each one of its fields.

func NewSearchCriteria

func NewSearchCriteria() *SearchCriteria

NewSearchCriteria creates a new search criteria.

func (*SearchCriteria) Format

func (c *SearchCriteria) Format() []interface{}

Format formats search criteria to fields. UTF-8 is used.

func (*SearchCriteria) ParseWithCharset

func (c *SearchCriteria) ParseWithCharset(fields []interface{}, charsetReader func(io.Reader) io.Reader) error

ParseWithCharset parses a search criteria from the provided fields. charsetReader is an optional function that converts from the fields charset to UTF-8.

type Seq

type Seq struct {
	Start, Stop uint32
}

Seq represents a single seq-number or seq-range value (RFC 3501 ABNF). Values may be static (e.g. "1", "2:4") or dynamic (e.g. "*", "1:*"). A seq-number is represented by setting Start = Stop. Zero is used to represent "*", which is safe because seq-number uses nz-number rule. The order of values is always Start <= Stop, except when representing "n:*", where Start = n and Stop = 0.

func (Seq) Contains

func (s Seq) Contains(q uint32) bool

Contains returns true if the seq-number q is contained in sequence value s. The dynamic value "*" contains only other "*" values, the dynamic range "n:*" contains "*" and all numbers >= n.

func (Seq) Less

func (s Seq) Less(q uint32) bool

Less returns true if s precedes and does not contain seq-number q.

func (Seq) Merge

func (s Seq) Merge(t Seq) (union Seq, ok bool)

Merge combines sequence values s and t into a single union if the two intersect or one is a superset of the other. The order of s and t does not matter. If the values cannot be merged, s is returned unmodified and ok is set to false.

func (Seq) String

func (s Seq) String() string

String returns sequence value s as a seq-number or seq-range string.

type SeqSet

type SeqSet struct {
	Set []Seq
}

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 NewSeqSet

func NewSeqSet(set string) (s *SeqSet, err error)

NewSeqSet returns a new SeqSet instance after parsing the set string.

func (*SeqSet) Add

func (s *SeqSet) Add(set string) error

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

func (s *SeqSet) AddNum(q ...uint32)

AddNum inserts new sequence numbers into the set. The value 0 represents "*".

func (*SeqSet) AddRange

func (s *SeqSet) AddRange(Start, Stop uint32)

AddRange inserts a new sequence range into the set.

func (*SeqSet) AddSet

func (s *SeqSet) AddSet(t *SeqSet)

AddSet inserts all values from t into s.

func (*SeqSet) Clear

func (s *SeqSet) Clear()

Clear removes all values from the set.

func (SeqSet) Contains

func (s SeqSet) Contains(q uint32) bool

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

func (SeqSet) Dynamic

func (s SeqSet) Dynamic() bool

Dynamic returns true if the set contains "*" or "n:*" values.

func (SeqSet) Empty

func (s SeqSet) Empty() bool

Empty returns true if the sequence set does not contain any values.

func (SeqSet) String

func (s SeqSet) String() string

String returns a sorted representation of all contained sequence values.

type StatusResp

type StatusResp struct {
	// The response tag. If empty, it defaults to *.
	Tag string

	// The status type.
	Type StatusRespType

	// The status code.
	// See https://www.iana.org/assignments/imap-response-codes/imap-response-codes.xhtml
	Code string

	// Arguments provided with the status code.
	Arguments []interface{}

	// The status info.
	Info string
}

A status response. See RFC 3501 section 7.1

func (*StatusResp) Err

func (r *StatusResp) Err() error

If this status is NO or BAD, returns an error with the status info. Otherwise, returns nil.

func (*StatusResp) WriteTo

func (r *StatusResp) WriteTo(w *Writer) error

type StatusRespType

type StatusRespType string

A status response type.

type StringReader

type StringReader interface {
	// ReadString reads until the first occurrence of delim in the input,
	// returning a string containing the data up to and including the delimiter.
	// See https://golang.org/pkg/bufio/#Reader.ReadString
	ReadString(delim byte) (line string, err error)
}

A string reader.

type Writer

type Writer struct {
	io.Writer
	// contains filtered or unexported fields
}

An IMAP writer.

func NewClientWriter

func NewClientWriter(w io.Writer, continues <-chan bool) *Writer

func NewWriter

func NewWriter(w io.Writer) *Writer

func (*Writer) Flush

func (w *Writer) Flush() error

type WriterTo

type WriterTo interface {
	WriteTo(w *Writer) error
}

Directories

Path Synopsis
Package backend defines an IMAP server backend interface.
Package backend defines an IMAP server backend interface.
backendutil
Package backendutil provides utility functions to implement IMAP backends.
Package backendutil provides utility functions to implement IMAP backends.
memory
A memory backend.
A memory backend.
Package client provides an IMAP client.
Package client provides an IMAP client.
Package commands implements IMAP commands defined in RFC 3501.
Package commands implements IMAP commands defined in RFC 3501.
IMAP responses defined in RFC 3501.
IMAP responses defined in RFC 3501.
Package server provides an IMAP server.
Package server provides an IMAP server.
Modified UTF-7 encoding defined in RFC 3501 section 5.1.3
Modified UTF-7 encoding defined in RFC 3501 section 5.1.3

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL