pop3

package
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Mar 28, 2024 License: MIT Imports: 11 Imported by: 0

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

View Source
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 = ' '
)
View Source
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

View Source
const (
	PlusOK   = "+OK"
	MinusERR = "-ERR"
)

POP3 status indicators

View Source
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

View Source
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 IsASCIIWord

func IsASCIIWord(raw string) bool

func Lines

func Lines(resp []byte) ([]string, error)

[2023-09-14, jfrech] XXX Maybe be more lenient and allow only "\n"?

func ParseNonNegativeInt

func ParseNonNegativeInt(raw string) (int, bool)

func ParsePositiveInt

func ParsePositiveInt(raw string) (int, bool)

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

func Dial(ctx context.Context, addr string, creds *Credentials) (*Client, error)

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

func DialSTARTTLS(ctx context.Context, addr string, creds *Credentials) (*Client, error)

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

func (client *Client) Close() error

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.

func (*Client) CommandMultiLine deprecated

func (client *Client) CommandMultiLine(keyword Keyword, arguments ...string) (string, []byte, error)

Deprecated: TODO

func (*Client) CommandSTAT deprecated

func (client *Client) CommandSTAT() (nmsgs, totalsize int, err error)

Deprecated: TODO

func (*Client) CommandSingleLine deprecated

func (client *Client) CommandSingleLine(keyword Keyword, arguments ...string) (string, error)

Deprecated: TODO

func (*Client) Pop

func (client *Client) Pop() ([]Message, error)

type Credentials

type Credentials struct {
	Username string
	// contains filtered or unexported fields
}

func USERPASSCredentials

func USERPASSCredentials(username string, password []byte) *Credentials

type ERR

type ERR struct{ Diagnostics string }

ERR encapsulates a "-ERR" POP3 response line.

func (*ERR) Error

func (err *ERR) Error() string

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

func (framed *Framed) Close() error

NOTE: (*Framed).Close does NOT send a QUIT command.

func (*Framed) Command

func (framed *Framed) Command(keyword Keyword, arguments ...string) error

Command only writes; it does not read a reply.

func (*Framed) CommandDELE

func (framed *Framed) CommandDELE(idx int) error

idx is 1-indexed; ses CommandSTAT

func (*Framed) CommandLIST

func (framed *Framed) CommandLIST() ([]LISTLine, error)

func (*Framed) CommandMultiLine

func (framed *Framed) CommandMultiLine(keyword Keyword, arguments ...string) (string, []byte, error)

func (*Framed) CommandNOOP

func (framed *Framed) CommandNOOP() error

func (*Framed) CommandQUIT

func (framed *Framed) CommandQUIT() error

func (*Framed) CommandRETR

func (framed *Framed) CommandRETR(idx int) ([]byte, error)

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

func (framed *Framed) CommandSTAT() (nmsgs, totalsize int, err error)

STAT returns statistics for all non-DELEted messages in the mail drop.

func (*Framed) CommandSTLS

func (framed *Framed) CommandSTLS() error

Cf. RFC 2595 4.

func (*Framed) CommandSingleLine

func (framed *Framed) CommandSingleLine(keyword Keyword, arguments ...string) (string, error)

func (*Framed) CommandUIDL

func (framed *Framed) CommandUIDL() (map[int]string, error)

TODO implement the argument version

func (*Framed) CommandUSERPASS

func (framed *Framed) CommandUSERPASS(creds *Credentials) error

CommandUSERPASS only sends credentials over a TLS transport.

func (*Framed) MultiLine

func (framed *Framed) MultiLine() (string, []byte, error)

func (*Framed) SingleLine

func (framed *Framed) SingleLine() (string, error)

type Keyword

type Keyword string

A keyword should be uppercase, three or four characters and only consist of ASCII printables (character code ' ' < . <= '~'). Cf. RFC 1939 3.

type LISTLine

type LISTLine struct {
	MessageNumber int
	Size          int
	Extra         string
}

type Message

type Message interface {
	Message() ([]byte, error)
	Delete() error
}

Jump to

Keyboard shortcuts

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