There is always a well working, prepared, documented and good way to solve a problem. The problem with that is that in the most cases we end up with a rat tail of components, we cannot install, maintain or want.

The real solution can be found here:

https://dokuwiki.nausch.org/doku.php/centos:mail_c7:spam_11 https://github.com/roehling/postsrsd/

It sounds very simple to implement working srs with Postfix. There is a tool set to perform this task. My only problem was that it was over engeneered to my understanding of the problem I found and liked to solve.

Make things easier for me and not for others, was my goal. So simple Python hack was my choice.

Postfix has a simple communication protocol to have TCP backed maps in place.

# Postfix asks for it
< get localpart@domain.com
# You reply with the new address
> 200 new-localpart@domain.com

There might also be the case, that you cannot lookup or have an error.

# Postfix asks for it
< get localpart@domain.com
# You reply with an error code and the original address
> 400 localpart@domain.com

This is simple to implement and with utilizing some other modules like the hashlib to generate a salted hash it's robust.

"""Server to provide address encoding for simplified SRS"""
import SocketServer
import hashlib, base64

MY_DOMAIN='example.com'
SECRET='Who does know me?'

class MyTCPHandler(SocketServer.BaseRequestHandler):
  def handle(self):
    self.data = self.request.recv(1024).strip()
    self.data=self.data.replace('get ','')
    if self.data.endswith(MY_DOMAIN):
        return self.request.send('200 {0}\n'.format(self.data))
    if self.data.strip() == '""':
        return self.request.send('200 {0}\n'.format(self.data))
    if '@' not in self.data:
        return self.request.send('400 {0}\n'.format(self.data))
    d=hashlib.md5(b"{0}{1}".format(SECRET, self.data)).digest(); d=base64.b64encode(d); 
    return self.request.send('200 {0}#{1}@{2}\n'.format(self.data.replace('@','-at-'), d, MY_DOMAIN))

if __name__ == "__main__":
  HOST, PORT = "localhost", 9999
  SocketServer.TCPServer.allow_reuse_address = True
  server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
  server.serve_forever()

And to convert everything back the following was the way to go.

"""Server to provide address decoding for simplified SRS"""
import SocketServer
import hashlib, base64

MY_DOMAIN='example.com'
SECRET='Who does know me?'

class MyTCPHandler(SocketServer.BaseRequestHandler):
  def handle(self):
    self.data = self.request.recv(1024).strip()
    self.data=self.data.replace('get ','')
    if self.data.endswith('@{0}'.format(MY_DOMAIN)):
      if '#' in self.data and '-at-' in self.data:
        orig=self.data.split('#',1)[0].replace('-at-','@')
        orighash=self.data.split('#',1)[1].split('@',1)[0]
        d=hashlib.md5(b"{0}{1}".format(SECRET, orig)).digest(); d=base64.b64encode(d);
        if d == orighash:
          return self.request.send('200 {0}\n'.format(orig))
        return self.request.send('200 {0}\n'.format(self.data))
    return self.request.send('200 {0}\n'.format(self.data))

if __name__ == "__main__":
  HOST, PORT = "localhost", 9998
  SocketServer.TCPServer.allow_reuse_address = True
  server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
  server.serve_forever()

In order to make it play nice with Postfix you need to enable the lookup via TCP socket there.

# main.cf
recipient_canonical_maps = tcp:127.0.0.1:9998
recipient_canonical_classes = envelope_recipient
sender_canonical_maps = tcp:127.0.0.1:9999
sender_canonical_classes = envelope_sender

# master.cf
smtp      inet  n       -       -       -       -       smtpd
  -o sender_canonical_maps=tcp:127.0.0.1:9999
  -o sender_canonical_classes=envelope_sender

With that the emails are encoded and decoded in and out.