Documentation ¶
Overview ¶
Package pop3 implements parts of the POP3 protocol (cf. RFC 1939) relevant to clients.
[TODO rewrite] Package pop3 does not assume the presence of CAPA (https://datatracker.ietf.org/doc/html/rfc2449#section-5)
Package pop3 is designed to be used in a TLS >=1.2 environment. Cf. 8314, cf. 8997.
POP3 defines three states: AUTHORIZATION, TRANSACTION and UPDATE. This module is written in a way that connection acquisition means having passed AUTHORIZATION, connection utilisation happens in TRANSACTION and (*Conn).Close means sending QUIT, going into UPDATE and ending the connection.
[2023-09-14, jfrech] TODO I am not quite sure if "+OK text" leads to a head of " text" or " text". How else should one handle "+OKtext" or "+OK text"?
For registered POP3 extensions cf. https://www.iana.org/assignments/pop3-extension-mechanism/pop3-extension-mechanism.xml
Written by Jonathan Frech, 2022--2023.
Index ¶
- Constants
- Variables
- func IsASCIIWord(raw string) bool
- func Lines(resp []byte) ([]string, error)
- func ParseNonNegativeInt(raw string) (int, bool)
- func ParsePositiveInt(raw string) (int, bool)
- type Client
- func (client *Client) Close() error
- func (client *Client) CommandMultiLine(keyword Keyword, arguments ...string) (string, []byte, error)deprecated
- func (client *Client) CommandSTAT() (nmsgs, totalsize int, err error)deprecated
- func (client *Client) CommandSingleLine(keyword Keyword, arguments ...string) (string, error)deprecated
- func (client *Client) Pop() ([]Message, error)
- type Credentials
- type ERR
- type Framed
- func (framed *Framed) Close() error
- func (framed *Framed) Command(keyword Keyword, arguments ...string) error
- func (framed *Framed) CommandDELE(idx int) error
- func (framed *Framed) CommandLIST() ([]LISTLine, error)
- func (framed *Framed) CommandMultiLine(keyword Keyword, arguments ...string) (string, []byte, error)
- func (framed *Framed) CommandNOOP() error
- func (framed *Framed) CommandQUIT() error
- func (framed *Framed) CommandRETR(idx int) ([]byte, error)
- func (framed *Framed) CommandSTAT() (nmsgs, totalsize int, err error)
- func (framed *Framed) CommandSTLS() error
- func (framed *Framed) CommandSingleLine(keyword Keyword, arguments ...string) (string, error)
- func (framed *Framed) CommandUIDL() (map[int]string, error)
- func (framed *Framed) CommandUSERPASS(creds *Credentials) error
- func (framed *Framed) MultiLine() (string, []byte, error)
- func (framed *Framed) SingleLine() (string, error)
- type Keyword
- type LISTLine
- type Message
Constants ¶
const ( // POP3 uses CRLF-terminated lines CRLF = "\r\n" // POP3's multi-line responses are byte-stuffed and dot-terminated DOT = '.' // POP3 does not use tabs SP = ' ' )
const ( // Cf. RFC 1939 STAT = Keyword("STAT") LIST = Keyword("LIST") // TODO not yet implemented RETR = Keyword("RETR") // retrieve DELE = Keyword("DELE") // delete NOOP = Keyword("NOOP") // no-operation RSET = Keyword("RSET") // TODO not yet implemented // Cf. RFC 1939 QUIT = Keyword("QUIT") // Cf. RFC 1939 TOP = Keyword("TOP") // TODO not yet implemented UIDL = Keyword("UIDL") USER = Keyword("USER") PASS = Keyword("PASS") // password // Cf. RFC 2449 CAPA = Keyword("CAPA") // capabilities // Cf. RFC 2595 4. STLS = Keyword("STLS") // start TLS )
POP3 keywords
const ( PlusOK = "+OK" MinusERR = "-ERR" )
POP3 status indicators
const MaximumPhysicalLineLength = 512
MaximumPhysicalLineLength includes in its count both status indicators ("+OK" or "-ERR"), byte-stuffing (dot-encoding: ".dot." for "dot.") and trailing CRLF.
Currently, this limit is not enforced but merely used as an initial buffer capacity.
RFC 1939 3. specifies the maximum response length to be 512 bytes. RFC 822 3.4.8. very cautiously discourages mail message header lines longer than around a hundred bytes. RFC 2822 2.1.1. recommends mail message lines be no longer than 80 bytes and forbids lines longer than 1000 bytes. RFC 5322 2.1.1. repeats the above.
Variables ¶
var ( // Package pop3 will never transmit credentials in the clear. ErrNoTLS = errors.New("no TLS") // E.g. maximum line length violated or unknown status indicator sent. ErrProtocol = errors.New("pop3: protocol not followed") // E.g. "+OK 5 oktets" instead of "+OK 5 octets". ErrSyntax = errors.New("pop3: wrong syntax") // POP3 semantics were not followed, e.g. message numbers are duplicated. ErrSemantics = errors.New("pop3: semantically incoherent") )
Functions ¶
func Lines ¶
[2023-09-14, jfrech] XXX Maybe be more lenient and allow only "\n"?
Types ¶
type Client ¶
type Client struct { // NOTE: When using STARTTLS, due to the POP3 protocol, Greeting cannot be // trusted and is thus always empty. Greeting string // Capabilities are requested in a TLS-secured TRANSACTION state. // Capabilities == nil iff dialing failed or the mail drop does not support // the "CAPA" capability. // When the mail drop supports the CAPA command, it should also report the // "CAPA" capability, making Capabilities non-zero. Capabilities []string // contains filtered or unexported fields }
Client represents a live POP3 connection to a remote mail drop. After use, (*Client).Close is expected to be called.
func Dial ¶
Dial dials a remote POP3 server and transitions into a TLS-secured TRANSACTION state. The resulting *Client must be closed iff a nil error got returned. addr's hostname is used to authenticate the server's TLS certificate.
func DialSTARTTLS ¶
Dial dials over raw TCP, issues POP3's STARTTLS command and enables TLS. (*Client).Greeting will always be empty since the greeting is transmitted over unsecured raw TCP. If available, use of Dial is recommended. addr's hostname is used to authenticate the server's TLS certificate.
func (*Client) Close ¶
Live POP3 servers have been observed to close the network connection prematurely, not answering the QUIT command. Thus, Close only propagates an explicit -ERR answer and not net.ErrClosed or io.EOF. XXX One could argue the above should be disabled with framed.Strict.
type Credentials ¶
type Credentials struct { Username string // contains filtered or unexported fields }
func USERPASSCredentials ¶
func USERPASSCredentials(username string, password []byte) *Credentials
type Framed ¶
type Framed struct { // TODO remove? Strict bool // contains filtered or unexported fields }
Framed represents a byte stream framed according to POP3 semantics. Framed is expected to be called synchronously.
func Frame ¶
func Frame(transport io.ReadWriteCloser) *Framed
func (*Framed) Close ¶
NOTE: (*Framed).Close does NOT send a QUIT command.
func (*Framed) Command ¶
Command only writes; it does not read a reply.
func (*Framed) CommandDELE ¶
idx is 1-indexed; ses CommandSTAT
func (*Framed) CommandMultiLine ¶
func (*Framed) CommandRETR ¶
NOTE: RFC 1939 does NOT explicitly state the mail drop had to return a parsable "+OK 1939 octets". idx is 1-indexed
func (*Framed) CommandSTAT ¶
STAT returns statistics for all non-DELEted messages in the mail drop.
func (*Framed) CommandSingleLine ¶
func (*Framed) CommandUIDL ¶
TODO implement the argument version
func (*Framed) CommandUSERPASS ¶
func (framed *Framed) CommandUSERPASS(creds *Credentials) error
CommandUSERPASS only sends credentials over a TLS transport.