AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 718817
Accepted
Peter Walker
Peter Walker
Asked: 2022-09-27 14:47:55 +0800 CST2022-09-27 14:47:55 +0800 CST 2022-09-27 14:47:55 +0800 CST

使用 Postfix 过滤器在传输过程中修改特定 SMTP 邮件

  • 772

我正在寻找一个简单的 Postfix 服务器,它可以修改某些特定 SMTP 消息的内容和收件人。
到目前为止,我对自己的方法并不是很有信心,并且觉得我缺少一些关于 Postfix 如何做事的基础知识,所以我希望能得到一些指导。


语境

我工作的组织的设置最初对像我这样从未真正使用过 Postfix 的人来说有点令人生畏,所以希望我的解释是有道理的。

我能够了解到的是,DMZ 网络中的一台 Linux 机器{1}正在运行一个 Postfix 服务器,并且是所有传入电子邮件都集中到的地方。
然后,服务器在其文件中定义了一些规则,这些规则根据域(例如, )/etc/postfix/transport确定要将消息中继到哪些其他邮件服务器。如果域只是基本名称(例如),则消息将传递到员工登录的主电子邮件服务器并检查他们的邮件等。{3..N}@domain1.company.org@domain2.company.org@company.org{2}

INTERNET   |     DMZ    |   INTERNAL 
   SMTP ---|---> {1} ---|---> {2} 
                        \---> {3..N}

我提到的“特定 SMTP 消息”是来自一些工程师正在设置的一些简单设备的集合。这些设备在可以发送的内容上有些限制。

工程师:我无法更改主题的内容或电子邮件正文的某些区域。

当这些设备发送消息时,我的理解是网络会将消息汇集到{1},然后将消息中继到适当的电子邮件服务器。

要求的解决方案

工程师:我们是否可以要求当来自特定地址的电子邮件具有可预测的简单主题和主体时,在转发给收件人之前由我们的系统拦截和修改?例如在主题和正文中,将发送“泄漏”一词,我们可以在转发消息之前将其更改为“冷冻机”吗?

因此,我基本上需要在将邮件转发到任何其他电子邮件服务器之前修改邮件的内容。在消息到达之前{1}或附近需要发生一些事情。{1}{2..N}

到目前为止我的方法

鉴于一切顺利{1},并且我不想对邮件通过这台机器的方式进行任何重大更改,我想我会启动另一台 Linux 机器来运行另一台 Postfix 服务器(我将调用它mailmunger,如图所示作为{1a})。
然后,工程师将配置设备并指定它将发送的消息的收件人,例如[email protected].

最后,我将添加另一条规则(/etc/postfix/transport我认为是在 中),{1}以便将邮件*@mailmunger.company.org转发到我的新 Linux 机器。

然后{1a},我会使用诸如队列后内容过滤器之类的东西来处理消息,根据请求修改内容,从收件人地址中删除mailmunger.,然后将消息传递回{1}.
这是因为 Postfix server 的relay_host属性{1a}会被配置为 server 的名字{1}。

INTERNET   |     DMZ    |   INTERNAL 
   SMTP ---|---> {1} ---|---> {2} 
                 / ^    \---> {3..N}
                |  |
                v  /
                {1a}

我认为这种方法尽可能安全,因为它会限制编写错误的过滤器的影响。但是,也许我在这个设计中犯了一个我没有注意到的错误。
我希望所有正常的邮件流都应该按预期继续,并且只有邮件[email protected]会卡在我的新mailmunger机器上。


问题

  1. 我是否在使用“队列后内容过滤器”的正确轨道上?或者我应该看一个不同的机制,比如队列前内容过滤器?
  2. {1a}服务器真的需要transport配置它的文件吗?还是我误解了该属性的使用?
  3. 这些简单的设备如何知道将 SMTP 消息发送到哪个服务器?
  4. 有什么我应该注意的问题吗?
linux postfix
  • 1 1 个回答
  • 33 Views

1 个回答

  • Voted
  1. Best Answer
    Peter Walker
    2022-10-14T09:01:31+08:002022-10-14T09:01:31+08:00

    经过一番挣扎和仔细测试,我有一个解决方案!

    它的短处是:

    • mailmunger我误解了 MX 记录,不得不为我的服务器创建一些新记录。
    • 不,mailmunger服务器不需要/etc/postfix/transport修改其文件。只有/etc/postfix/main.cf和/etc/postfix/master.cf需要的修改。
    • 没有太多的陷阱,只是当消息无法到达其预期目的地时进行一些令人沮丧的调试。

    更详细的解决方案

    所以第一步是修改/etc/postfix/transport服务器{1}。我需要在传输映射中添加一行,以便将消息[email protected]定向到我的mailmunger服务器。

    /mailmunger.company.org/  relay:[mailmunger.company.org]
    

    我的运输地图文件是一个正则表达式表,所以main.cf文件上{1}有一行:

    transport_maps = regexp:/etc/postfix/transport
    

    下一点是配置mailmunger。

    mailmunger的main.cf

    在main.cf文件中,我需要两个关键部分。

    relayhost = {1}.company.org
    
    local_recipient_maps =
    

    定义relayhost变量是告诉服务器“如果您不是应该接收消息的人,请将其传递给这个人”。
    这是一个关键部分,因为在我修改了消息之后,我将它放回了队列中并使用了不同的收件人。

    该local_recipient_maps变量需要一个空值,否则服务器将在我的过滤器脚本处理邮件之前找不到指定收件人的邮箱时拒绝邮件。
    我不在乎收件人是否是在服务器上没有帐户的人,因为我的目的是修改邮件内容和收件人地址。
    如果我的脚本失败,消息将被退回给发件人。

    mailmunger的master.cf

    我在此处所做的更改基本上正是After-Queue Content Filter指南指定的内容。

    smtp      inet  n       -       y       -       -       smtpd
      -o content_filter=filter:dummy
    ...
    
    filter    unix  -       n       n       -       10      pipe
      flags=Rq  user=postfix-filter  null_sender=
      argv=/opt/postfix-filters/start-filter -f ${sender} -- ${recipient}
    

    该smtp服务添加了一个额外的选项,将消息定向到filter管道服务。
    该filter服务以我创建的特殊用户身份运行我的脚本postfix-filter,并根据脚本的退出代码将消息放回队列或将其退回给发件人。

    上的其他东西mailmunger

    正如您在服务配置中可能注意到的那样filter,还有一些其他的东西需要创建/配置。

    1. 第一步是创建一个新目录,/opt/postfix-filters/. 我只是喜欢那个位置。
    2. 接下来是创建postfix-filter用户。我使用 shell 指定了该用户/usr/sbin/nologin,并将其主目录指定为/opt/postfix-filter.
    3. 然后我使用以下逻辑 start-filter在我的目录中创建了该文件:/opt/postfix-filters/
      #!/bin/bash
      
      ##############################################################################
      #
      # Based on documented example here:
      #  http://www.postfix.org/FILTER_README.html
      #
      # Example Execution:
      #  /path/to/script -f sender -- recipient... <message-file
      #
      ##############################################################################
      
      shopt -s extglob
      
      ## Making of copy of the positional arguments
      _ARGS=("$@")
      
      ## Defining paths to directories that we will be using
      _BASE_DIR="/opt/postfix-filters"
      
      _TMP_DIR="${_BASE_DIR}/tmp"
      [ -d ${_TMP_DIR} ] || {
          echo "${_TMP_DIR} does not exist"; exit $EX_TEMPFAIL; }
      _TMP_FILE="${_TMP_DIR}/in.$$"
      
      _LOG_FILE="${_BASE_DIR}/log"
      
      _FILTERS_DIR="${_BASE_DIR}/filters"
      SENDMAIL="/usr/sbin/sendmail -G -i " # NEVER NEVER NEVER use "-t" here.
      
      
      ## Exit codes from <sysexits.h>
      EX_TEMPFAIL=75
      EX_UNAVAILABLE=69
      
      ## Clean up when done or when aborting.
      function _cleanup() {
        #echo ${_ARGS[@]}
        #cat ${_TMP_FILE}
        rm -f ${_TMP_FILE}
      }
      trap "_cleanup" 0 1 2 3 15
      
      
      ## Creating a temp file (in the INSPECT_DIR directory) with a name that uses
      ## the current Process ID ($$).
      ## This script assumes that the message content is coming in via stdin.
      cat >${_TMP_FILE} || {
          echo "Cannot save mail to file"; exit $EX_TEMPFAIL; }
      
      ## Pass the file and args to each script in the directory containing
      ## filter scripts. If any of them fails with exit code 1, then exit
      ## this parent script. Assume 0 and all other error codes mean
      ## continue.
      for _SCRIPT in ${_FILTERS_DIR}/!(README*) ; do
          ## A quick test that the path is a file and is executable
          ( [ -f "${_SCRIPT}" ] && [ -x "${_SCRIPT}" ] ) || continue
          ## Now we run the script
          echo "running: ${_SCRIPT} -- ${_TMP_FILE} ${_ARGS[@]}" >> "${_LOG_FILE}"
          _NEWARGS=$( ${_SCRIPT} "${_TMP_FILE}" ${_ARGS[@]} )
          if [ "$?" -eq 0 ]
          then
              _ARGS=("${_NEWARGS}")
              echo "newargs? ${_ARGS[@]}" >> "${_LOG_FILE}"
          elif [ "$?" -eq 2 ]
          then
              echo "args not modified" >> "${_LOG_FILE}"
          else
              ## If the script exits with any exit code other than 0 or 2, then we
              ## will "reject" the message based on the content. To do the rejection,
              ## we exit this script with the EX_UNAVAILABLE exit code.
              echo "Message content rejected"
              exit $EX_UNAVAILABLE
          fi
      done
      
      ## Putting the mail back in the queue using the args given to this
      ## script by Postfix.
      $SENDMAIL ${_ARGS[@]} <"${_TMP_FILE}"
      
      ## Exiting with the return status of sending the mail
      exit $?
      
    4. 还有一些其他目录要在 中创建/opt/postfix-filters/,例如filters/和tmp/。
    5. 然后,剩下的就是在filters/目录中创建一个或多个用户可执行的脚本postfix-filter。我会让你弄清楚如何做到这一点,但我会留下一个建议,即所述脚本可以修改传入的参数(最终传递给sendmail命令)并且应该返回以下任一退出代码:
      • 0(成功并且修改了sendmail参数)
      • 2(成功,但未修改参数)
      • 其他任何事情(有什么烦人的,退出并退回消息)。

    开始做事

    剩下的就是确保 Postfix onmailmunger以我的新配置启动。

    [root@mailmunger /etc/postfix]# postfix reload
    
    • 0

相关问题

  • 有没有办法让 ls 只显示某些目录的隐藏文件?

  • 使用键盘快捷键启动/停止 systemd 服务 [关闭]

  • 需要一些系统调用

  • astyle 不会更改源文件格式

  • 通过标签将根文件系统传递给linux内核

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve