(Generated by  groff(1))

S-postgray manual

This plain  groff(1) HTML output has only been fixed slightly — i am sorry for false list indentions etc.!

S-postgray [v0.6.0, 2022-04-01] — postfix protocol policy (RFC 6647 graylisting) server


s-postgray [options]
[options] −−shutdown
[options] −−test-mode [options]



S-postgray is a postfix(1) RFC 6647 graylisting policy server, following the recommendet practice noted in the standard document. It supports client allow (white) and block (black) lists (blocking should be done earlier in the processing chain, though) of domain names (exact and wildcard) as well as IPv4 and IPv6 addresses (exact or in CIDR notation). It aims in being fast and secure: all the data is stored in main memory, synchronization with backing store is only performed when the server process is started or stopped, and the graylist database which needs to handle network data uses a cryptographically secure hash function.

S-postgray clients are intented to be started via the postfix(1) spawn(8) daemon, they will automatically start the server as necessary. The server lifetime is configurable, by (compile-time) default it will terminate itself after some time without any client connection. Sending the server a ‘SIGHUP’ signal will re-evaluate its configuration (which may result in program panic if a file disappeared or memory failures occur), sending it ‘SIGUSR2’ will save the graylist database, whereas sending ‘SIGUSR1’ will write some statistics to the log file. A synchronized server −−shutdown[28] can be enforced, or an asynchronous termination by sending the server a ‘SIGTERM’ signal. An excessively lengthy but minimal configuration example:

#@ /etc/postfix/master.cf:

postgray unix - n n - - spawn
argv=/usr/libexec/s-postgray -vvR /etc/postgray.rc -c 0


#@ /etc/postfix/main.cf:

default_privs = ANON-USR

# Clients connection checks
smtpd_client_restrictions =
#RELAY permit_tls_clientcerts,
#[RELAY] permit_sasl_authenticated,

smtpd_data_restrictions =

smtpd_helo_restrictions =
#RELAY permit_tls_clientcerts,
#[RELAY] permit_sasl_authenticated,

# MAIL FROM Checks
smtpd_sender_restrictions =
#RELAY permit_tls_clientcerts,
#[RELAY] permit_sasl_authenticated,
# Total no-goes database, eg: qq.com reject
# check_sender_access lmdb:/etc/postfix/sender_restrict,

smtpd_relay_before_recipient_restrictions = yes

# RCPT TO checks, relay policy
# Local+auth clients may specify any destination domain
smtpd_relay_restrictions =
#RELAY permit_tls_clientcerts,
#[RELAY] permit_sasl_authenticated,

# RCPT TO checks, spam blocking policy
smtpd_recipient_restrictions =
#RELAY permit_tls_clientcerts,
#[RELAY] permit_sasl_authenticated,
check_policy_service unix:private/postgray


Options may be given in short or long form. Resource files only support the long option form, and only a (logical) subset of the following options. The minute limit is 32767 (15-bit), the maximum duration is thus 22 days. Other numbers have a limit of 31-bit (2147483647). −−test-mode[29] performs a dry-run configuration syntax test, and virtualizes it. In the following DB means database, and GC garbage collection.

−−4-mask mask, −4 mask

IPv4 mask to strip off addresses before match. For example 24 masks all addresses in between and This is desirable since in practice MX farms are used, and/or IP addresses are selected from a pool.

−−6-mask mask, −6 mask

IPv6 mask to strip off addresses before match. Using a mask of 64 seems to be good practice (see −−4-mask[8] ).

−−allow-file path, −A path

Load a file of whitelist entries in the syntax described for −−allow[11] . Each line forms an entry, leading and trailing whitespace is removed. If the first non-whitespace character is the number-sign ‘#’ the line is a comment and discarded. Empty lines are ignored.

−−allow spec, −a spec

Add a domain name or an IPv4 or IPv6 internet address, optionally in RFC 1519 CIDR notation with network mask, to the list of allowed clients (whitelist). Domain names are matched exactly unless the first character is a period ‘.’, in which case the given domain and all its subdomains will match. For IP addresses the global masks −−4-mask[8] and −−6-mask[9] normalize the given address (range) if applicable. All constructs are matched via dictionary, except for CIDR ranges with masks smaller than the global ones, they are matched in the given order.


# This matches d.a.s but also a.b.c.d.a.s

# with --4-mask=24 this really is!

# with --6-mask=64 really 2a03:2880:20:6f06::/64
# instead of 2a03:2880:20:6f06:c000::/66!

# with --6-mask=64 nonetheless 2a03:2880:20:4f00::/56
# This will _not_ be matched by dictionary but in order

If whitelisting is really performed that late in the processing chain it should include all big players and all normally expected endpoints; it may be useful to run for a few days with the special 0 −−count[14] and inspect the log in order to create a whitelist. Some MTAs are picky, so driving for a while with a low count and in −−verbose[30] mode to collect more data before increasing count etc. is worthwhile.

It should be noted that only the two VERP (variable envelope return path addresses) delimiters plus sign ‘+’ and equal sign ‘=’ are understood — mailing list software which chooses the hyphen-minus ‘-’ as a VERP delimiter (ezmlm instances are known which do) make a particularly bad choice because many mailing-lists have a hyphen-minus as a regular part of their name, so no automatic differentiation in between the customized address part and the regular address is possible: such addresses can only be placed in the whitelist, otherwise each and every received message will be graylisted.

−−block-file path, −B path

Load a file of blacklist entries in the syntax described for −−allow-file[10] .

−−block spec, −b spec

Add a blacklist entry, syntax identical to −−allow[11] .

−−count no, −c no

Number of SMTP message delivery retries before it is accepted. The special value 0 will accept messages immediately, and change the behaviour of some other settings, like −−limit-delay[21] ; it may be useful when setting up the configuration and the whitelist. (Once regular usage begins that DB should possibly be removed.)

−−delay-max mins, −D mins

Duration until a message ‘‘is no longer a retry’’, but interpreted as a new one with a reset −−count[14] .

−−delay-min mins, −d mins

Duration until a message ‘‘is a retry’’. Those which come sooner do not increment −−count[14] .

−−delay-progressive , −p

If set each counted retry doubles −−delay-min[16] for the next one until −−count[14] is reached.

−−gc-rebalance no, −G no

Number of DB GC runs before rebalancing occurs. Value 0 turns rebalancing off. Rebalancing only affects shrinking of the dictionary table, it is grown automatically as necessary, so a carefully chosen −−limit[20] may render rebalancing undesired.

−−gc-timeout mins, −g mins

Duration until a DB entry is seen as unused and removed. Each time an entry is used the timeout is reset. This timeout is also an indication for how often a GC shall be performed, but GC happens due to circumstances, too.

−−limit no, −L no

Number of DB entries until new ones are not handled, effectively turning them into whitelist members. Data is stored compact, and the size depends on email message data, but accounting say 128 bytes per entry might be a guideline. In addition the dictionary table resides in one large contiguous memory chunk, accounting 1 MB per 10000000 entries may be proper.

−−limit-delay no, −l no

Smaller than −−limit[20] , this number describes a limit after which creation of a new (yet unknown) entry is delayed by a one second sleep for throttling purposes. The value 0 disables this feature. By choosing the right settings for −−limit[20] , −−limit-delay[21] and −−gc-timeout[19] , it should be impossible to reach the graylist bypass limit. Note this is not honoured if −−count[14] is 0.

−−server-queue no, −q no

The number of concurrent clients a server can handle before accept(2)ing new ones is suspended. This setting cannot be changed at runtime.

−−server-timeout mins, −t mins

Duration until a S-postgray server which does not serve any clients terminates. The value 0 disables auto-termination. The statistics dumped on the signal ‘SIGUSR1’ are not saved in the DB, they only reflect the current server lifetime.

−−resource-file path, −R path

A configuration file with long options (without double hyphen-minus ‘−−’). Each line forms an entry, leading and trailing whitespace is removed. If the first non-whitespace character is the number-sign ‘#’ the line is a comment and discarded. Empty lines are ignored. The server parses the configuration a second time, and from within −−store-path[25] !

−−store-path path, −s path

An accessible path to which S-postgray will change, and where the DB and the server/client communication socket will be created. This setting cannot be changed at runtime.

−−defer-msg msg, −m msg

The message in access(5) format that postfix(1) expects for not yet accepted messages. This setting cannot be changed at runtime. The default is ‘DEFER_IF_PERMIT 4.2.0 Service temporarily faded to Gray’, of which only ‘DEFER_IF_PERMIT’ is not optional; it uses an RFC 3463 extended status code:

# [4.2.0]
4.X.X Persistent Transient Failure
x.2.X Mailbox Status
X.2.0 Other or undefined mailbox status
# [4.7.1 (seen in wild; less friendly and portable!)]
x.7.X Security or Policy Status
x.7.0 Other or undefined security status
x.7.1 Delivery not authorized, message refused
This is useful only as a permanent error.

If postfix(1) address verification is used in addition, it may be better to use graylisting (maybe second-last and) before it, and return ‘DEFER 4.2.0’ instead, so that the more expensive address verification is performed only when graylisting permits continuation.

−−once , −o

If given the client part will only process one message. The server process functions as usual.

−−shutdown , −.

Force a running server process to exit. The client synchronizes on the server exit before its terminating. It exits EX_TEMPFAIL (75) when no server is running.

−−test-mode , −#

Enable test mode: all options are evaluated, including −−allow-file[10] , −−allow[11] , −−block-file[12] and −−block[13] which are normally processed by only the server. Once the command line is worked the content of all white- and blacklists is shown, as well as the final settings of above variables. The exit status indicates error. It is highly recommendet to use this for configuration checks.

−−verbose , −v

Increase log verbosity (two levels). This might be of interest to improve the configuration, for example data suitable for −−allow[11] and −−block[13] is logged, as is the time necessary to save and load the DB.

−−long-help , −H

A long help listing.

−−help , −h

A short help listing; not really useful for this software.


postfix(1), spawn(8)


Steffen Nurpmeso <steffen@sdaoden.eu>.

Copyright (c) 1997 - 2021, Steffen Nurpmeso <steffen@sdaoden.eu>
@(#)code-postgray.html-w42 1.4 2022-04-04T21:32:02+0000