【问题标题】:Postfix - How to process outgoing emails?Postfix - 如何处理外发电子邮件?
【发布时间】:2013-04-27 09:56:12
【问题描述】:

我正在尝试实现一个帮助台应用程序,为此我需要编写一个 PHP 脚本来处理所有传入和传出的电子邮件。将 Postfix 视为 MTA,我发现这篇文章解释了如何对传入的电子邮件执行此操作:Postfix - How to process incoming emails?。它建议使用 Postfix 的 mailbox_command 配置,它就像一个魅力。我想知道外发电子邮件是否存在类似的情况?

【问题讨论】:

  • 1) 你所说的“过程”是什么意思? 1a) 查看/阅读 1b) 重写 1c) ... 2) 您是否对“不仅用于后缀”解决方案感兴趣?
  • 与此同时,我一直在阅读 Postfix 文档,我发现 filters 是最接近我想要的功能。为了阐明我的需求,我想为 Postfix 设置一个 PHP 脚本,以便每次发送电子邮件时,都会将该电子邮件的副本发送到我的脚本。 Postfix 中的过滤器可以做到这一点,但它们的问题是它们是 Postfix 交付过程的一部分。这意味着如果我的脚本无法转发电子邮件(出于任何原因),则电子邮件将永远不会送达。这是我不想要的(太多的责任)。
  • 对不起,我忘了你的其他问题。我宁愿只坚持 Postfix。

标签: postfix-mta


【解决方案1】:

要将所有外发邮件的副本发送到您的脚本,您需要:

  • 一个研磨器
  • 内容过滤器
  • recipient_bcc_maps

最后一个选项是最简单的(您将邮件密送到服务器上的邮箱,脚本可以在其中处理邮件)。

但是:如果您的脚本已经生成了电子邮件,为什么还要将它们再次输入到您的脚本中? Postfix 并没有做太多的事情,只是添加了一个 message-id 标头和其他一些无聊的标头...

【讨论】:

    【解决方案2】:

    您可以在收到的邮件上指定内容过滤器 - 这样做您需要通过以下方式修改您的 master.cf 文件:

    ...
    submission inet n - n - - smtpd
      ...
      -o content_filter=yourfilter:
    ...
    yourfilter unix - n n - - pipe
      user=[user on which the script will be executed]
      argv=php /path/to/your/script.php --sender='${sender}' --recipient='${recipient}'
    

    接下来,您需要编写 script.php,以便正确使用已提供的参数(--sender=... 和--recipient=...)和邮件正文将由标准输入提供。

    这是一个如何从标准输入获取电子邮件的示例(我使用这个,稍后使用 Zend\Mail\Message::fromString() 创建 Message 对象):

        /**
         * Retrieves raw message from standard input
         * @throws \RuntimeException if calling controller was not executed on console
         * @return string raw email message retrieved from standard input
         */
         protected function retrieveMessageFromStdin() { 
            $request = $this->getRequest();
            if (!$request instanceof ConsoleRequest)
                throw new \RuntimeException('Action can be used only as console action !');
    
            $stdin = fopen('php://stdin', 'r');
            $mail_contents = "";
            while (!feof($stdin)) {
                $line = fread($stdin, 1024);
                $mail_contents .= $line;
            }
            fclose($stdin);
            $mail_contents = preg_replace('~\R~u', "\r\n", $mail_contents);
            return $mail_contents;
        }
    

    根据参数 - 我使用 ZF2,因此您应该阅读如何在那里编写控制台应用程序或使用不同的技术,更符合您的框架。

    非常重要的是,如果您希望在邮箱中接收邮件 - 您还需要将电子邮件“重新注入”回 postfix。我的做法如下:

        /**
         * Reinjects message to sendmail queue
         *
         * @param array $senders            array of senders to be split into several sender addresses passed to sendmail (in most cases it is only 1 address)
         * @param array $recipients         array of recipients to be split into several recipient addresses passed to sendmail
         * @param string $sendmaiLocation   sendmailLocation string full path for sendmail (should be taken from config file)
         * @return number                   return value for sendmail
         */
         public function reinject(array $senders, array $recipients, string $sendmaiLocation) {
            foreach ($senders as $addresses)
                $senderAddress .= " " . $addresses;
            foreach ($recipients as $addresses)
                $recipientAddress .= " " . $addresses;
            $sendmail = $sendmaiLocation . " -G -i -f '" . $senderAddress . "' -- '" . $recipientAddress . "'";
            $handle = popen($sendmail, 'w');
            fwrite($handle, $this->toString());
            return pclose($handle);
        }
    

    基本上你可以使用上面的功能,根据你的需要自定义。然后您可以稍后使用我之前提到的命令行参数中的参数执行它。

    希望这会有所帮助:)

    【讨论】:

    • 请您解释一下 $this 是什么?谢谢!
    • $this 这里指的是 Zend\Mime\Message 对象(因为上面的代码是扩展 Zne\Mime\Message 的类的一部分...基本上不是 $this->toString() 你可以简单地添加一个包含要重新注入到后缀中的 Mime 消息的变量
    • 这仅处理传入的电子邮件,OP 询问传出的电子邮件和您的帖子如何处理根本
    • 确实 - 我的错误 - 我已经修改了响应,因此过滤器针对外发电子邮件执行
    • 这个答案的第一行说“您可以在收到的邮件上指定内容过滤器”,但答案本身是指外发。
    猜你喜欢
    • 2011-07-15
    • 2011-04-29
    • 2011-03-09
    • 1970-01-01
    • 1970-01-01
    • 2011-04-08
    • 1970-01-01
    • 1970-01-01
    • 2015-08-19
    相关资源
    最近更新 更多