Назад | Перейти на главную страницу

Postfix Relay: отправлять сообщения, исходящие в Интернет, только по определенному критерию, ретранслировать на другое реле, если критерий не соблюден.

Это будет звучать немного запутанно и сложно, но у нас есть очень злую установку в настоящее время для электронной почты в одной из сред моих клиентов.

От самой внутренней системы к внешней мы имеем:

Exchange Server -> Sendmail Server -> McAfee Email Gateway -> OUTSIDE

Это небольшое зло, потому что электронные письма об отсутствии на работе (от кого-то внутри системы к внешнему) не работают, они, по-видимому, перехватываются на шлюзе электронной почты McAfee и не передаются наружу.

Я пытаюсь настроить сервер Postfix в качестве реле И SMTP-сервера, и в зависимости от того, что получено, либо:

  1. Отправка электронной почты напрямую (с использованием SMTP, только для ответов об отсутствии на работе)
  2. Ретранслировать почту на сервер Sendmail для выполнения остальных его функций по ретрансляции, как это обычно происходит.

Тогда это будет выглядеть примерно так:

Exchange Server -> Postfix Relay --- Out of Office messages only ---> OUTSIDE
                         |
                   All other mail
                         |
                         ---> Sendmail Server/Relay ---> McAfee Email Gateway ---> OUTSIDE

Я немного зациклился на том, как настроить Postfix на выборочную ретрансляцию. Есть ли кто-нибудь, кто может дать некоторое представление о том, как этого добиться?

Я придумал очень хакерский подход к этому.

По сути, я помещаю настроенный SMTP-сервер, написанный на Python, между сервером Postfix и сервером Exchange, который фактически обрабатывает настоящий маршрутизация реле. Он написан на Python и работает как суперпользователь на порту 25 (из-за ограничений привязки порта).

Затем этот скрипт Python обрабатывает сообщение, как обычно, просматривая электронное письмо из синтаксического анализатора строк, затем читает строку темы, чтобы определить, куда его отправить, а затем отправляет исходное сообщение без изменений либо на локальный SMTP-сервер Postfix ( для прямой исходящей передачи) или на другой ретранслятор в сети. Пока это кажется работать.

Вот код, который я использую для этого на стороне Python:

#!/usr/bin/env python3

# Libraries
import smtplib
import smtpd
import asyncore
import email
import sys
from datetime import datetime

print('Starting custom mail handling server...')

# CONFIGURATION VARIABLES - We are expecting to relay, so... let's relay.
SMTP_RELAY = 'SMTP_RELAY_HOSTNAME_OR_IP'
SMTP_DIRECT = 'localhost'

#############
#############
# SMTP SERVER
#############
#############


# noinspection PyMissingTypeHints,PyBroadException
class AutoReplyHandlerSMTP(smtpd.SMTPServer):

    def process_message(self, peer, mailfrom, rcpttos, data, **kwargs):
        print('MESSAGE RECEIVED - [%s]' % datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
        print('Receiving message from:', peer)
        print('Message addressed from:', mailfrom)
        print('Message addressed to  :', rcpttos)
        print('Message length        :', len(data))
        print(data)

        # Flush the output buffered (handy with the nohup launch)
        sys.stdout.flush()

        # Analyze and extract data headers
        msg = email.message_from_string(data)
        subject = ''
        try:
            subject = msg['Subject']
            subject = subject.lower()
        except:
            print("Subject error:", sys.exc_info()[0])
        print('Message subject       :', msg['Subject'])

        # Determine whether we are directly sending outbound, or if we're relaying to another server.
        if "automatic reply" in subject:
            print("Automatic reply received, sending directly.")
            # Local postfix SMTPd is on tcp/6625.
            conn = smtplib.SMTP(host=SMTP_DIRECT, port=6625, timeout=60)
            conn.sendmail(mailfrom, rcpttos, msg.as_string())
            conn.quit()
        else:
            print("Standard message detected, sending to relay.")
            # Other relay server is on tcp/25 (standard smtp)
            conn = smtplib.SMTP(host=SMTP_RELAY, timeout=60)
            conn.sendmail(mailfrom, rcpttos, msg.as_string())

        # Flush the output buffered (handy with the nohup launch)
        print("\n\n")
        sys.stdout.flush()
        return


# Listen to port 25 ( 0.0.0.0 can be replaced by the ip of your server but that will work with 0.0.0.0 )
server = AutoReplyHandlerSMTP(('0.0.0.0', 25), None)

# Wait for incoming emails
asyncore.loop()

Я настроил Postfix для прослушивания SMTP на другом порту. По сути, именно это и было сделано в /etc/postfix/master.cf на моем сервере Ubuntu для этого, и в конечном итоге это две строки и то, как я настроил SMTPd в Postfix - обратите внимание, что вы можете использовать любой порт с высоким номером для любого другого порта для Postfix SMTPd, но я выбрал что-то простое:

#smtp      inet  n       -       y       -       -       smtpd
6625      inet  n       -       y       -       -       smtpd

Затем скрипт Python пересылает данные в порт 6625, и запущенный там SMTPd Postfix; После этого мы специально позволяем Python определять, какой SMTP-сервер или ретранслятор является «следующим переходом». Это как бы нарушает стандартные заголовки «Получено», но якобы отлично работает с сообщениями.

У меня не было проблем с моим решением, и оно кажется работать. Необходимы дополнительные тесты, но это «решение», похоже, решает проблему маршрутизации сообщений (прямой SMTP-выход или через остальные реле), на самом деле не вмешиваясь в конфигурацию Postfix.