popart

package module
v0.0.0-...-f601a19 Latest Latest
Warning

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

Go to latest
Published: Feb 16, 2016 License: MIT Imports: 10 Imported by: 1

README

popart GoDoc codebeat badge

POP3 server library for Go

Artwork

Philosophy

This library is designed to only take care of handling POP3 specifics on top of the excellent standard library net/textproto package. It makes a few opinionated choices:

  • it uses interfaces and dependency injection to allow the user integrate their own logic with the protocol handler, much the same way the stock net/http library does. The use of interfaces was thought to encourage better design and stronger guarantees than providing functional callback hooks;
  • it does not do any logging of its own and leaves all of that to the user. A hook called HandleSessionError is provided in the Handler interface for handling non-reportable errors that may happen during a POP3 session in case custom logging was desirable. Thanks to popart being completely silent the user is free to choose any logging mechanism they like and have the application behave in a consistent fashion;
  • it does not support STARTTLS. Since it's optional you can't really decide whether the client will end up using it or not. And if they decide not to use it their email will go throught the interpipes in plaintext. This would be perfectly fine if it did not involve other folks' data. So in order to avoid such mishaps this package is designed to take a net.Listener which for any sort of production use should be a TLS socket from the crypto/tls standard library package.

Installation

go get github.com/slowmail-io/popart

Example

The example directory contains an example implementation which takes a path to a directory containing email messages (using --maildir flag) and serves them through POP3 protocol. It runs on port 1100 by default (can be changed with --port flag) and without SSL so you can connect to it directly using telnet:

$ telnet localhost 1100

Then you can have a nice POP3 chat. The example implementation will actually not delete your messages so that you can play around with the same set of files without having to continuously to feed the directory new mail to delete ;)

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewReportableError

func NewReportableError(format string, args ...interface{}) error

NewReportableError provides a helper function for creating instances of ReportableError.

Types

type Handler

type Handler interface {
	// AuthenticatePASS is generally the first method called on a Handler
	// and should authentication fail it will return an error. It is
	// expected though that if the authentication is successful the handler
	// will be able to associate all subsequent operations with this
	// particular user without an explicit need to pass username to each and
	// every method.
	AuthenticatePASS(username, password string) error

	// AuthenticateAPOP provides an alternative method of POP3
	// authentication where instead of a username/password combination the
	// client generates an md5 hexdigest based on a shared secret and the
	// banner displayed by the server at the beginning of the connection.
	// As per RFC1939 a server MUST support at least one authentication
	// mechanism but does not need to support any particular one.
	AuthenticateAPOP(username, hexdigest string) error

	// DeleteMessage takes a list of ordinal number of messages in a user's
	// maildrop and deletes them. If this method fails it is expected that
	// *none* of the messages will be deleted.
	// Note: you can not assume that message IDs will come in any particular
	// order.
	DeleteMessages(numbers []uint64) error

	// GetMessageReader takes an ordinal number of a message in a user's
	// maildrop and returns an io.ReadCloser allowing the content of the
	// message to be read. The server will take care of closing the data
	// source.
	GetMessageReader(number uint64) (io.ReadCloser, error)

	// GetMessageCount returns a number of messages waiting in the user's
	// maildrop.
	GetMessageCount() (uint64, error)

	// GetMessageCount takes and ordinal number of a message in a user's
	// maildrop and returns it's locally (per-maildrop) unique ID that is
	// persistent between sessions.
	GetMessageID(number uint64) (string, error)

	// GetMessageCount takes an ordinal number of a message in a users's
	// maildrop and returns its size in bytes. This may differ from what is
	// eventually returned to the client because of line ending replacements
	// and dot escapes but it should be reasonably close nevertheless.
	GetMessageSize(number uint64) (uint64, error)

	// HandleSessionError would be invoked if the code *outside* of the
	// handler errors produces an error. The session itself will terminate
	// but this is a chance to log an error the way
	HandleSessionError(err error)

	// LockMaildrop puts a global lock on the user's maildrop so that
	// any concurrent sessions that attempt to communicate with the server
	// should fail until the current session calls UnlockMaildrop. This
	// method should return an error if it is not possible to lock the
	// maildrop.
	LockMaildrop() error

	// SetBanner is called by APOP-enabled servers at the beginning of the
	// session. It is expected that the banner is stored somewhere since it
	// is expected that it will be available for proper handling of the
	// AuthenticateAPOP call.
	SetBanner(banner string) error

	// UnlockMaildrop releases global maildrop lock so that other clients
	// can connect and initiate their sessions. It is generally the very
	// last thing that will be called on a connection under normal
	// circumstances.
	UnlockMaildrop() error
}

Handler is an object capable of serving a POP3 connection.

type ReportableError

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

ReportableError is a trivial implementation of 'error' interface but it is useful for deciding which errors can be reported to the POP3 client and which are internal-only.

func (*ReportableError) Error

func (r *ReportableError) Error() string

type Server

type Server struct {
	// Hostname defines how the server should introduce itself. It is only
	// really important if the server is supposed to support APOP
	// authentication method.
	Hostname string

	// OnNewConnection is a callback capable of producing Handler objects
	// to handle incoming connections.
	OnNewConnection func(peer net.Addr) Handler

	// Timeout allows setting an inactivity autologout timer. According to
	// rfc1939 such a timer MUST be of at least 10 minutes' duration.
	Timeout time.Duration

	// Implementation allows the server to provide custom implementation
	// name to the POP3 client. The default one is "popart".
	Implementation string

	// Expire allows the server to provide message expiration advice to the
	// client. The default one is "NEVER".
	Expire string

	// APOP determines whether the server should implement the APOP
	// authentication method.
	APOP bool
	// contains filtered or unexported fields
}

Server listens for incoming POP3 connections and handles them with the help of Handler objects passed via dependency injection.

func (*Server) Serve

func (s *Server) Serve(listener net.Listener) error

Serve takes a net.Listener and starts processing incoming requests. Please note that Server does not implement STARTTLS so unless your Listener implements TLS (see package crypto/tls in the standard library) all communications happen in plaintext. You have been warned.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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