Email Forwarding like Craigslist - Rails

柔情痞子 提交于 2019-11-30 02:25:56

You'll need an email address using a domain with a MX server your sysadmin has control of. This could be a subdomain of your primary domain. Then what you do, is you configure the MTA software (Exim, Postfix... hopefully not qMail!) to pipe that email to Rails:

http://guides.rubyonrails.org/action_mailer_basics.html#receiving-emails

If the MTA is not installed on the same server as the rails application itself, you'll have to pipe the email to a little ad-hoc forwarder script that does something along the line of POSTing the email to your app, where you then manually pass that to your mailer.

In your mailer, you have access to all the headers, body, attachments etc. Provided you put some unique identifiers in the subject, or the Reply-To address, you can make the decision about which Mailer to instantiate to forward the mail onto its intended recipient.

We haven't done this yet, but we're going to be doing it for the same reasons. It may be a little over your head if you're not familiar with configuring an MTA however. Do you have a sysadmin you can land this task on?

At the code level, I'd be doing this:

  1. User A (id = 1234) sends an email to User B (id = 5678)
  2. Send the e-mail from any address you want, which you own, but set the Reply-To: to something like Reply-To: <mail-1234-5678-abcdefabcd1234567890abcdefabcdef@usermessages.your-domain.com>

    This is absolutely key to this working. It includes the ID of the sender, the ID of the recipient, and a checksum to prevent forgery. The checksum can be generated from a salt unique to each user, and is simply:

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

  3. Now when you receive a reply via the MX you have configured for your "usermessages.your-domain.com" domain, the first thing you do is identify the sender and the recipient by parsing the To: field. You can easily identify who the sender and recipient are by split'ing out the parts. You can then generate a checksum and make sure it matches, to ensure somebody isn't trying to maliciously send mail as if it's from another user.

  4. Once you have figured out the users involved, go ahead and send another e-mail, with one of these special Reply-To: headers (with the ID's reversed and the digest done using a different salt, obviously).

This is a very rudimentary, but perfectly functional example. You can put this digest anywhere you want, provided it will be preserved when the reply comes back (which makes the Reply-To: header a good fit. Some services use the subject line instead.

I would avoid making the salt something user-controlled, such as the user's password hash, since if the user changes that information (changes their password), the checksum will no longer validate.

If your app is going to scale, especailly across multiple servers then I wouldn't recomend the default Rails way of receiving email. Take a look at a blog post I wrote here about some options.

The basic premise is that you want to receive mail on a catch all domain. You can either forward/collect using imap/pop3 from a server like gmail or use a service like CloudMailin to take care of delivering the message to your app. You can give each user a unique to address or even just use the disposable part of the message such as normal+disposable@domain.com.

Then it's just a case of using the mail gem to inspect the message and add any headers that you need to and send the message on again. Again you can use your own email server to do this delivery or rely on a service like Amazon's Simple Email Service if you want to improve your deliverability.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!