配置所有转发到php脚本的唯一每用户电子邮件地址的正确方法是什么?

时间:2012-09-06 02:19:17

标签: php email sendmail

我有一个约有的网络应用程序。 30k用户并且增长迅速。我们希望通过电子邮件启用某些功能,这意味着为每个用户分配一个唯一的电子邮件地址(出于安全原因)。发送到这些唯一地址的电子邮件应转发到PHP脚本。 PHP脚本需要访问电子邮件的所有部分 - 标题,正文和任何附件。我不确定以什么方式设置它。我们目前正在使用sendmail,并且更愿意坚持使用(这是Linux,如果重要的话)。我已经能够获得一个单独的电子邮件转发到脚本,但它不可扩展(在我看来)创建30k别名,然后每次新用户注册时创建一个新别名。我会对某种基于catch-all / RegEx的解决方案感到更高兴,该解决方案只告诉PHP脚本作为收件人的唯一电子邮件地址,这样我们就可以查看用户。

3 个答案:

答案 0 :(得分:7)

30k帐户不会向我们提供您希望处理的流量的任何信息。但是,让我们假设这是另一个问题。

您可以创建catch all类型的帐户,只需接受您创建用户的域中的任何电子邮件即可。地址(基本上*@domain)。然后,您可以在每个传入邮件上启动处理脚本(通常可以从stdin流(在PHP中通过php://stdin访问)获取整个邮件正文,并根据需要进行处理。但是这样如果你想使用PHP(或几乎任何脚本语言),这是很糟糕的,因为每个邮件都需要生成新的PHP进程,初始化所有扩展等等。这一切都需要时间和资源,还有一个更大的垃圾邮件洪流和你的盒子几乎是烤了。

或者,您可以像在任何其他邮件中一样在邮箱中收集邮件,然后让您的脚本从那里获取邮件(直接,通过挖掘maildir或通过IMAP或POP等邮件协议)。从管理角度来看,这看起来更好,只要您的邮件服务器可以接受传入的邮件,您的整个系统仍然有效。你甚至可以尝试分区"您的系统通过设置一些过滤规则(在MTA级别上)并将传入的邮件传递给单个邮箱但更多。然后你可以并行处理这些邮件,而不用麻烦(不需要为处理多个实例的同一邮件而烦恼)。 "分区"架构可以是任何东西,即取决于您的完整地址命名方案,如果基于它的信件是a*@b*@[a-d]*@](取决于流量)的单独邮箱,并不重要。

或者,您可以尝试将传入邮件的主体放入数据库,然后按上述方法进行处理,而无需进行POP / IMAP处理。

无论您选择什么,我都建议将任何表单的处理脚本直接放在邮件接收流程链中。延迟1分钟通常不是问题(所以你可以运行任何类型的守护进程并获取处理邮件,cronjob等),用户可以等待那么多w / o抱怨 - 看起来即时处理很可能不是在你的情况下也是强制性的。但如果确实如此,那么PHP 可能不是我担心的最佳工具选择。

编辑:(回答评论问题而非点击评论大小限制)

我不熟悉Sendmail足以在这里给你精确的配置指令(我在定制的qmail上),但我希望有一些一般的提示。首先,我相信Sendmail支持虚拟用户(这意味着/etc/passwd中没有用户的邮箱)。如果是这样,那么MTA通常应该让您查询数据库(以查明目标电子邮件地址是否有效以及该用户的主页目录在哪里放入邮件)与一些内置提供程序。或者(甚至更好)调用外部程序来做到这一点。后者在这里是一个赢家,因为没有用户真的,所以你可以编写小脚本或(再次,更好的性能)C应用程序,可以做到这一点。因为你所需要的只是"分开"根据一些简单的预定义规则将邮件传入多个物理邮箱,几个if() s + substr() s就完成了。几行,没有DB需要,非常快。或者,甚至更好,你甚至可以在这里尝试最愚蠢的roundrobin方法 - 如果邮件点击accountAaccountB,只要50%的邮件以{结尾}结束,这实际上是无关紧要的{1}}以及A中的其他50%(如果您使用4个目标帐户等,则为25%),这是我认为应该关注的唯一条件。您可以尝试使用B,但我认为这是毫无意义的,并不是最佳的表现。

至于将邮件放入数据库。这取决于MTA - 默认情况下没有人这么做,因为它比将邮件放入maildirs要慢(因为DB通常是其他主机),但仍然有几个解决方案。要么为Sendmail寻找第三方补丁,要么添加另一个脚本/应用程序,以便复制"邮件从物理邮箱发送到DB。你可能会说 - 但它会慢一些。当然,但是再次 - 我不知道非实时处理在你的情况下是否真的很重要(我的盲目猜测 - 它没有),所以为什么真的很烦。如果你在这里节省几毫秒但是在整个解决方案的进一步维护上花费了很多时间,那么选择是非常明显的。

BTW:以防万一 - 每当我写procmail时,我绝对是指用户邮件的容器, mailbox文件格式。至于文件格式mailbox(或某些东西)是更好的选择。

答案 1 :(得分:1)

你真的想为每封传入的电子邮件分叉PHP吗?如果你正在处理体面的邮件量,这可能会变得昂贵。为什么不在邮件服务器中有一个自定义回调来处理传入邮件并插入数据库,然后有一个工作脚本不断轮询新邮件进行处理?

邮件到数据库部分的重量应该比执行所有处理要轻得多,这样就可以获得一个空闲队列,这样如果你几乎同时收到大量请求,那么你的系统就不会这样做了。试图一次性处理所有这些。

答案 2 :(得分:1)

做了类似的实现,虽然规模较小......但应该扩展以满足您的目的。

两个单独的问题

(1)邮件 - 所有提及的解决方案是一个很好的解决方案,但你必须处理垃圾邮件和格式错误的电子邮件地址(这可能是一件好事还是一件坏事)。如果您拥有该服务器,只需将“虚构”帐户别名并指示邮件服务器将它们全部放在同一个中央邮箱中即可完成任务,因为您不需要单独的实际帐户,并且标题信息将保持不变。详细信息取决于您的邮件解决方案,但任何邮件服务器应该不仅能够处理此任务和卷,您应该能够编写别名创建脚本...否则返回到全部

(2)PHP解析和处理 - PHP的内置pop3函数可以轻松处理(现在)单个电子邮件帐户的检查和处理消息;我过去常常遇到的一些函数示例是

function pop3_login($host,$port,$user,$pass,$folder="INBOX",$ssl=false){
        $ssl=($ssl==false)?"/novalidate-cert":"";
        return (imap_open("{"."$host:$port/pop3$ssl"."}$folder",$user,$pass,OP_SILENT));
}
function pop3_stat($connection){
        $check = imap_mailboxmsginfo($connection); # changed from $imap
        return ((array)$check);
}
function pop3_retr($connection,$message,$section='1'){
        return(quoted_printable_decode(imap_fetchbody($connection,$message,$section)));
}
function pop3_dele($connection,$message){
        return(imap_delete($connection,$message));
}
function pop3_close($connection){
        return(imap_close($connection,CL_EXPUNGE));
}

所有非常通用,如果你不需要控件,那里可能有类。最重要的是,PHP拥有快速解析和处理邮件消息所需的一切。