类似Craigslist的电子邮件转发 - Rails

8
我正在尝试实现类似craigslist匿名邮件的功能,但要用Rails实现,并且要尽可能低成本。对我来说,能够添加邮件头非常重要,这就是为什么基本的邮件转发无法满足需求的原因。
我想到的一种方法是使用SMTP服务器,每当我通过POP / IMAP读取电子邮件时,我会向真正的收件人发送一封电子邮件,带有正确的FROM地址并添加邮件头。这种方法可以实现,但SMTP服务器相对昂贵。
另一种方式是在电子邮件转发/重定向时,在中间添加邮件头。不过,我找不到任何服务或宝石可以实现这个功能。
请不要只说“Email Piping”,因为这实际上只是将电子邮件提供给您的Rails程序,那么在您拥有电子邮件之后,您该怎么做? 如何实际进行转发。
有什么建议吗?
2个回答

13
你需要有一个MX服务器由你的系统管理员控制的带有域名的电子邮件地址。这可以是你主要域名的子域名。然后,你需要配置MTA软件(Exim、Postfix……但不是qMail!)将该电子邮件传输到Rails中:http://guides.rubyonrails.org/action_mailer_basics.html#receiving-emails。如果MTA未安装在Rails应用程序本身所在的服务器上,则需要将电子邮件传输到一个小的特别转发脚本,该脚本执行一些操作,例如将电子邮件POST到你的应用程序,然后你手动将其传递到你的邮件程序中。
在你的邮件程序中,你可以访问所有标题、正文、附件等。只要在主题或答复地址中放置一些唯一的标识符,就可以决定实例化哪个Mailer以将邮件转发给其预期的收件人。
我们还没有这样做,但出于同样的原因,我们将要这样做。如果你不熟悉配置MTA,这可能有点超出你的范围。你可以把这个任务交给你的系统管理员吗?
在代码层面上,我会这样做:
1. 用户A(ID=1234)向用户B(ID=5678)发送一封电子邮件。 2. 从你拥有的任何地址发送电子邮件,但将答复地址设置为类似于的内容。 这是绝对关键的。它包括发件人和收件人的ID以及一个用于防止伪造的校验和。可以从每个用户的唯一盐生成校验和,其计算方法如下:

checksum = Digest::MD5.hexdigest("#{sender.id}-#{recipient.id}-#{sender.mailer_salt}")

当你通过配置了“usermessages.your-domain.com”域名的MX接收回复时,首先要做的是通过解析To:字段来识别发件人和收件人。使用split方法轻松地分离出各部分,然后生成一个校验和以确保校验和匹配,以确保没有人试图恶意发送邮件,让其似乎来自另一个用户。
一旦确定了涉及到的用户,就可以发送另一封电子邮件,并使用其中一种特殊的Reply-To:头部(反转ID并使用不同的盐进行摘要,显然)。这只是一个非常基本但完全可用的示例,你可以将此摘要放在任何位置,只要在回复时能够保留它即可,这使得Reply-To:头部最适合。有些服务使用主题行代替。
我建议避免使用用户可控的盐,例如用户的密码哈希值,因为如果用户更改该信息(更改密码),校验和将无法验证。

谢谢您的回复!我对管道部分很熟悉。我想我不理解的是“将电子邮件转发给预期收件人”的部分。我希望我的发件人地址是发送电子邮件的人。然而,据我所知,如果您拥有自己的邮件服务并更改发件人地址,这是非常不好的做法,并且经常会被过滤掉。这是真的吗? - Thariq Shihipar
没错,你绝不能使用一个你不拥有的地址来发送电子邮件……这很可能会被卡在垃圾邮件过滤器中。我还以为你想匿名呢?我会更新我的答案,并更深入地讨论我如何设计它。 - d11wtq
请查看我修改后的答案,了解在Rails层面上该怎么做的技术讨论。请记住,我还没有实际操作过,只是一直在思考,因为我们也将要做这个。 - d11wtq
请注意Steve的答案,关于避免在已经运行HTTP环境并可以直接使用时将邮件直接发送到Rails。 - d11wtq
嗯,我想更改发件人地址的原因是因为这实际上是craigslist的做法。它会将电子邮件转发给他们,使其看起来像是我发送的。我认为可靠地实现这一点的唯一方法是通过像sendgrid这样的服务? - Thariq Shihipar
你可以更改 From:,只要你将 Sender:Return-Path: 设置为你拥有的地址,但我个人不建议这样做。Sendgrid 在邮件头方面无法比你做得更好 ;) - d11wtq

4
如果您的应用程序需要扩展,特别是跨多个服务器,则我不建议使用默认的Rails接收电子邮件方式。请查看我写的一篇博客文章这里,了解一些选项。
基本原则是您希望在一个通用域上接收邮件。您可以从像Gmail这样的服务器转发/收集,也可以使用CloudMailin等服务来处理将消息传递给您的应用程序。您可以为每个用户提供唯一的地址,甚至只使用消息的一次性部分,例如normal+disposable@domain.com。
然后,只需使用邮件宝石检查消息并添加任何所需的标题,然后再次发送消息即可。同样,您可以使用自己的电子邮件服务器进行此交付,或者依赖Amazon的简单电子邮件服务等服务来提高交付能力。

谢谢回复。我之前没有看到亚马逊的简单电子邮件服务。那么,它会让我控制发件人头部吗?这样看起来就像是由最初发送电子邮件的人发送的? - Thariq Shihipar
1
我同意你在博客文章中提到的内容... Rails文档建议使用管道的方式来实现它(这将导致惊人的环境初始化开销),这不是最理想的方法。你肯定想要将其POST到你的应用程序中。 - d11wtq
1
很好的问题,Thariq。我还没有使用过Amazon的SES服务(尽管有打算),但我记得它确实允许你选择发送方的地址。(设置发件人的头部是容易的一部分 - 难点在于DKIM等技术,你需要防止客户端误以为你的邮件是钓鱼邮件或伪造的发件人地址)。问题在于你必须手动验证每个发送者......如果你控制发送方的地址,这不是问题,但如果你想让任何一个应用用户都能通过Amazon SES成为发送方,那就是个问题了。 - Tyler Rick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接