Re: Skip recipient verification and forward everything to a LMTP socket

2020-01-20 Thread Éloi Rivard
> But no matter what, any action in smtpd.conf is a command that is going
> to get executed and a process has to have a owner, so there is going to
> be a system user involved.

Thank you for the explanations, this is clearer.

What about RFC 1891? Is there an option to disable use of additional parameters
such as ORCPT [1] to ensure compatibility with smtp tools that does not support
this standard?

[1] https://tools.ietf.org/html/rfc1891#section-5.2




Re: Skip recipient verification and forward everything to a LMTP socket

2020-01-20 Thread gilles
ORCPT is only emitted if peer advertises support for it:


if (s->ext & MTA_EXT_DSN) { 

  
mta_send(s, "RCPT TO:<%s>%s%s%s%s", 

  
e->dest,

  
e->dsn_notify ? " NOTIFY=" : "",

  
e->dsn_notify ? dsn_strnotify(e->dsn_notify) : "",  

  
e->dsn_orcpt ? " ORCPT=" : "",  

  
e->dsn_orcpt ? e->dsn_orcpt : "");  

  
} else  

  
mta_send(s, "RCPT TO:<%s>", e->dest);



January 20, 2020 11:33 AM, "Éloi Rivard"  wrote:

>> But no matter what, any action in smtpd.conf is a command that is going
>> to get executed and a process has to have a owner, so there is going to
>> be a system user involved.
> 
> Thank you for the explanations, this is clearer.
> 
> What about RFC 1891? Is there an option to disable use of additional 
> parameters
> such as ORCPT [1] to ensure compatibility with smtp tools that does not 
> support
> this standard?
> 
> [1] https://tools.ietf.org/html/rfc1891#section-5.2



python dnsbl filter with 6.6.1p1 on netbsd

2020-01-20 Thread Andi Vajda



 Hi list,

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 !

Andi..

- 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)

  while True:
yield await reader.readline()


async def filter():
  loop = asyncio.get_running_loop()
  async for line in input(loop):
line = line.strip().decode()
emit(line, sys.stderr)

args = line.split('|')
if args[0] == 'filter':
  dnsbl = args[8].split(':')[0].split('.')
  dnsbl.reverse()
  dnsbl.append('zen.spamhaus.org')

  response = None
  try:
await loop.getaddrinfo('.'.join(dnsbl), None)
  except socket.gaierror as e:
if e.args[0] == socket.EAI_NODATA:
  response = '|'.join(['filter-result', args[6], args[5], 'proceed'])
else:
  emit(str(e), std.stderr)
  except Exception as e:
emit(str(e), std.stderr)
pass

  if response is None:
response = '|'.join(['filter-result', args[6], args[5], 'disconnect',
 '421 Temporary failure'])

  emit(response, sys.stderr)
  emit(response)


for line in sys.stdin:
  line = line.strip()
  emit(line, sys.stderr)
  if line == 'config|ready':
break

emit('register|filter|smtp-in|connect')
emit('register|ready')

asyncio.run(filter())