You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现socat同时转发输入至TCP连接与PHP脚本(Postfix场景)?

实现Postfix内容过滤器:socat双向转发+单向输入到PHP脚本

要实现你需要的功能,核心是让socat把接收到的输入(从Postfix来的邮件数据)复制一份给PHP脚本,同时保持原有与10025端口的双向通信。我们可以通过shell的tee命令结合进程替换,配合socat的SYSTEM选项来实现,具体方案如下:

最终命令

socat tcp-listen:10026,reuseaddr,fork SYSTEM:"bash -c 'tee >(php /absolute/path/to/your/filter-script.php) | socat - tcp:localhost:10025,copyaddr'"

命令拆解与工作流程

让我一步步解释这个命令的逻辑:

  1. 外层socat:监听10026端口,reuseaddr允许端口快速复用,fork为每个新连接创建独立进程处理,避免阻塞。
  2. SYSTEM选项:把每个连接的输入传递给bash命令处理,同时把bash命令的输出回传给客户端(Postfix)。
  3. tee + 进程替换:
    • tee会把接收到的邮件数据复制成两份:一份通过>(...)进程替换传递给你的PHP脚本;另一份通过管道传给内层socat。
    • 进程替换>(php ...)需要bash支持,所以我们显式指定bash -c来执行命令。
  4. 内层socat:把收到的数据转发到10025端口,同时把10025返回的响应(比如SMTP状态码)回传,这样就完整保留了原有的双向通信能力。
  5. copyaddr选项:让内层socat保留客户端的源地址,对Postfix的日志和后续处理更友好。

PHP脚本示例

你的PHP脚本需要读取标准输入(也就是socat转发过来的邮件内容),这里给一个简单的日志记录示例:

<?php
// 读取完整的邮件内容
$email = file_get_contents('php://stdin');

// 这里添加你的过滤/处理逻辑:比如检查邮件主题、内容,调用API,记录审计日志等
$logEntry = sprintf("[%s] Received email:\n%s\n\n", date('Y-m-d H:i:s'), $email);
file_put_contents('/var/log/postfix-content-filter.log', $logEntry, FILE_APPEND);

// 脚本的输出会被自动丢弃,不需要返回内容给socat
?>

关键注意事项

  • 权限问题:确保运行socat的用户(通常是postfix或root)有执行PHP脚本、写入日志文件的权限。
  • 性能考量:如果PHP脚本处理耗时较长,可能会影响邮件投递速度。如果需要处理大量邮件,建议把输入写入异步队列(比如Redis),用单独的进程处理,避免阻塞转发流程。
  • 测试验证:可以用telnet localhost 10026发送测试SMTP数据,检查10025端口是否收到数据,同时查看PHP脚本的日志是否有记录,并且能正常收到10025的响应。
  • 容错性:即使PHP脚本崩溃或异常,tee依然会把数据转发给内层socat,不会影响Postfix与10025的正常通信,保证核心转发功能不受影响。

内容的提问来源于stack exchange,提问作者jchook

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:55:36