On Tue, 21 Jan 2020, Martijn van Duren wrote:
I've already written filter-dnsbl, which is in OpenBSD-ports.
Source can be found here. I also made filter-dkimsign.
Your filters look great and would great be material for inclusion in OS
package distributions. My filter is just an example about one can go about
writing a simple filter in python3, using asyncio.
One of the advantages of the new filter API is that it makes such filters,
written in any language, much easier to write.
I made libopensmtpd compile on Ubuntu, so I don't expect much problems
with NetBSD. The filters themselves haven't been made portable yet.
Could you help me set these filters up for NetBSD?
Please, contact the maintainer of the opensmtpd package for netbsd. The
opensmtpd package version there is still 5.7.3p2.
On 1/21/20 1:27 AM, Andi Vajda wrote:
I've been a happy opensmtpd user on netbsd for many years.
I've now upgraded to version 6.6.1p1 and wrote a dnsbl filter in python3 using
asyncio that talks to zen.spamhaus.org. I've included the source code at the
bottom of this message.
This is my first time using asyncio.
I know that the filter feature of 6.6.1 is not (completely) documented and is
bound to change so I used the github smtpd-filters.7 man page for reference and
little bit of debugging to figure it out.
I implemented this as a 'register|filter|smtp-in|connect' filter.
The strangest thing was that I had to swap parts 5 and 6 of a filter line
(the unique session identifier and the opaque token) when returning them with a
filter-result line. Other than that, this new filter interface is super nice
and readable and a pleasure to use.
Thank you for making it happen !
----- filter.py -----
import asyncio, socket, sys
def emit(line, out=sys.stdout):
print(line, file=out, flush=True)
async def input(loop):
reader = asyncio.StreamReader()
protocol = asyncio.StreamReaderProtocol(reader)
await loop.connect_read_pipe(lambda: protocol, sys.stdin)
yield await reader.readline()
async def filter():
loop = asyncio.get_running_loop()
async for line in input(loop):
line = line.strip().decode()
args = line.split('|')
if args == 'filter':
dnsbl = args.split(':').split('.')
response = None
await loop.getaddrinfo('.'.join(dnsbl), None)
except socket.gaierror as e:
if e.args == socket.EAI_NODATA:
response = '|'.join(['filter-result', args, args, 'proceed'])
except Exception as e:
if response is None:
response = '|'.join(['filter-result', args, args, 'disconnect',
'421 Temporary failure'])
for line in sys.stdin:
line = line.strip()
if line == 'config|ready':