README

opensmtpd

OpenSMTPD-extras in Go

WARNING

This is very much Work In Progress. Don't use this for production installations. Much of the filter API in OpenSMTPD is not yet stable, so this package is also subject to change.

We have implemented Filter API version 52, because that's compatible with the most recent portable OpenSMTPD version (6.0.3p1).

Expand ▾ Collapse ▴

Documentation

Overview

Package opensmtpd implements OpenSMTPD APIs

APIs in OpenSMTPD

The APIs in OpenSMTPD are not stable and subject to change. The filter versions implemented by this package are tested against OpenSMTPD-portable version 6.0.3.

Filters

Hooks for the various SMTP transaction stages. If a filter function is registered for a callback, the OpenSMTPD process expects a reply via the Session.Accept() or Session.Reject() calls. Failing to do so may result in a locked up mail server, you have been warned!

Index

Examples

Constants

const (
	FilterOK = iota
	FilterFail
	FilterClose
)

const (
	// FilterVersion is the supported filter API version
	FilterVersion = 52

	// QueueVersion is the supported queue API version
	QueueVersion = 2

	// TableVersion is the supported table API version
	TableVersion = 2
)

const (
	ServiceNone        = 0x000
	ServiceAlias       = 0x001
	ServiceDomain      = 0x002
	ServiceCredentials = 0x004
	ServiceNetaddr     = 0x008
	ServiceUserinfo    = 0x010
	ServiceSource      = 0x020
	ServiceMailaddr    = 0x040
	ServiceAddrname    = 0x080
	ServiceMailaddrMap = 0x100
	ServiceRelayHost   = 0x200
	ServiceString      = 0x400
	ServiceAny         = 0xfff
)

Services


Variables

var (
	// Debug flag
	Debug bool
)

Functions

This section is empty.

Types

type ConnectQuery

type ConnectQuery struct {
	Local, Remote net.Addr
	Hostname      string
}

ConnectQuery are the QUERY_CONNECT arguments

func (ConnectQuery) String

func (q ConnectQuery) String() string

type Dict

type Dict map[string]interface{}

Dict is a key-value mapping

type Filter

type Filter struct {
	// Connect callback
	Connect func(*Session, *ConnectQuery) error

	// HELO callback
	HELO func(*Session, string) error

	// MAIL FROM callback
	MAIL func(*Session, string, string) error

	// RCPT TO callback
	RCPT func(*Session, string, string) error

	// DATA callback
	DATA func(*Session) error

	// DataLine callback
	DataLine func(*Session, string) error

	// EOM (end of message) callback
	EOM func(*Session, uint32) error

	// Reset callback
	Reset func(*Session) error

	// Disconnect callback
	Disconnect func(*Session) error

	// Commit callback
	Commit func(*Session) error

	Name    string
	Version uint32
	// contains filtered or unexported fields
}

Filter implements the OpenSMTPD filter API

Example

Code:

// Build our filter
filter := &Filter{
	HELO: func(session *Session, helo string) error {
		if helo == "test" {
			return session.Reject(FilterOK, 0)
		}
		return session.Accept()
	},
}

// Add another hook
filter.MAIL = func(session *Session, user, domain string) error {
	if strings.ToLower(domain) == "example.org" {
		return session.Reject(FilterOK, 0)
	}
	return session.Accept()
}

// Register our filter with smtpd. This step is optional and will
// be performed by Serve() if omitted.
if err := filter.Register(); err != nil {
	panic(err)
}

// And keep serving until smtpd stops
filter.Serve()

func (*Filter) Register

func (f *Filter) Register() error

Register our filter with OpenSMTPD

func (*Filter) Serve

func (f *Filter) Serve() error

Serve communicates with OpenSMTPD in a loop, until either one of the parties closes stdin.

type Session

type Session struct {
	ID uint64
	// contains filtered or unexported fields
}

func NewSession

func NewSession(f *Filter, id uint64) *Session

func (*Session) Accept

func (s *Session) Accept() error

func (*Session) AcceptCode

func (s *Session) AcceptCode(code int, line string) error

func (*Session) Reject

func (s *Session) Reject(status, code int) error

func (*Session) RejectCode

func (s *Session) RejectCode(status, code int, line string) error

type Sockaddr

type Sockaddr []byte

Sockaddr emulates the mess that is struct sockaddr

func (Sockaddr) IP

func (sa Sockaddr) IP() net.IP

func (Sockaddr) Network

func (sa Sockaddr) Network() string

func (Sockaddr) Port

func (sa Sockaddr) Port() uint16

func (Sockaddr) String

func (sa Sockaddr) String() string

type Table

type Table struct {
	// Update callback
	Update func() (int, error)

	// Check callback
	Check func(service int, params Dict, key string) (int, error)

	// Lookup callback
	Lookup func(service int, params Dict, key string) (string, error)

	// Fetch callback
	Fetch func(service int, params Dict) (string, error)

	// Close callback, called at stop
	Close func() error
	// contains filtered or unexported fields
}

Table implements the OpenSMTPD table API

Example

Code:

// In smtpd.conf:
//
//   table aliases <name-of-filter>:
//   accept for local alias <aliases> ...

aliases := map[string]string{
	"root": "user@example.org",
}

table := &Table{
	Lookup: func(service int, params Dict, key string) (string, error) {
		// We are only valid for aliases
		if service&ServiceAlias != 0 {
			return aliases[key], nil
		}
		return "", nil
	},
}
table.Serve()

func (*Table) Serve

func (t *Table) Serve() error

Directories

Path Synopsis
cmd/table-dummy
cmd/table-rbl