我正在尝试设置我的RoR 3应用程序来接收电子邮件,然后处理这些电子邮件并将其插入数据库。
在我的应用程序中,我有一个“作业”控制器。用户可以创建工作。我也有一个“评论”控制器。用户可以创建有关作业的评论。
以下是我在评论控制器中的部分内容:
def new
@job = Job.find(params[:job_id])
@comment = @job.comments.build
end
def create
@job = Job.find(params[:job_id])
@comment = @job.comments.build(params[:comment])
@comment.user_id = current_user.id
@comment.commenter = current_user.login
if @comment.save
redirect_to @job
else
render :action => "new"
end
end
当用户添加评论时,管理员会收到一封电子邮件。 当管理员添加评论时,用户会收到一封电子邮件。 (这已经在运作了。)
我正在使用Cloudmailin来帮助我接收收到的邮件。我已将Cloudmailin地址设置为指向http://myapp.com/incoming_mails。
class IncomingMailsController < ApplicationController
require 'mail'
skip_before_filter :verify_authenticity_token
def create
another_comment = Comment.create(:title =>
params[:subject], :body => params[:plain])
render :text => 'success', :status => 200 #status of 404 rejects mail
end
end
查看上面的注释控制器,看起来我需要job_id,current_user.id和current_user.login。
这是我在排序时遇到的问题:我的“incoming_mails”控制器中有什么内容?当用户通过电子邮件响应“incoming_mails”中的控制器能够找到job_id和current_user.id(或user_id)然后将该信息插入数据库时,如何确保?
我想我需要抓住用户的电子邮件地址,然后在主题行中也有job_id ......嗯......
有没有人有在Rails 3中设置传入邮件处理的经验?
答案 0 :(得分:3)
有几种方法可以做到这一点。一种常见的技术是将from / reply_to设置为自定义电子邮件地址,以允许您查找原始对象。类似的东西:
class Comment < ActiveRecord::Base
belongs_to :commentable
has_many :comments, :as => :commentable
before_validation :generate_token, :on => :create
validates :token, :presence => true, :uniqueness => true
attr_accessible :token
private
def generate_token
...
end
end
电子邮件发送时带有来自/ reply_to的地址,如[token] @ msg.yoursite.com (如果您愿意,也可以使用评论+ [token_or_id] @ msg.yoursite.com - 请参阅:cloudmailin提供的:一次性param)
class IncomingMailsController < ApplicationController
def create
@comment = Comment.find_by_token(params[:to].split('@')[0])
@comment.comments.create(:body => params[:plain])
render :text => 'success', :status => 200
end
end
如果您使用[token] @ msg.yoursite.com,则必须按照here所述正确设置您的DNS记录。
另一种选择是将内容存储在电子邮件的标题中。也许你的标题看起来像这样:
X-YOURAPP-OBJECT-ID = 44
X-YOURAPP-OBJECT-TYPE = Job
X-YOURAPP-TARGET-ASSOC = comments
X-YOURAPP-TARGET-ATTR = body
然后你的控制器会更像这样:
class IncomingMailsController < ApplicationController
def create
headers = Mail::Header.new(params[:message])
object= headers[:x_yourapp_object_type].constantize.find(headers[:x_yourapp_object_id])
object.send(headers[:x_yourapp_target_assoc]).create(headers[:x_yourapp_target_attr] => params[:plain])
render :text => 'success', :status => 200
end
end
这样做的好处是它完全通用。您可以对工作,评论评论或其他任何内容发表评论。如果您创建另一个模型,您还希望允许电子邮件回复...只需更新标题即可进行设置。唯一的问题是你必须小心邮件客户端剥离这些标题。有关详细信息,请查看this thread。
我目前正在使用第一种技术并且它运行良好。但是,我将在本周末重构并尝试第二种技术。
答案 1 :(得分:1)
我不确定这是一个完整的答案,但是让我快速给出它,当我有更多的时间时我可以更新它。
首先,我首先要将这项工作作为解决方案的一部分。使用comment+1@domain.com,表示这是第一个作业。这个部分在加之后被称为是CloudMailin中的一次性部分(params [:disposable]。然后可以使用params [:from]或Mail.new(params [:message])从邮件正文中获取用户的电子邮件地址。 ).from(有时提供给SMTP服务器的地址与标题中的地址不同)
接下来你有评论本身,它可以简单地作为普通的参数。
这给出了如下内容:
def create
@job = Job.find(params[:disposable])
if comment = @job.comments.create(:text => params[:plain], :commenter => User.find_by_email(params[:from])
render :text => 'Success', :status => 401
else
render :text => comment.errors.inspect, :status => 422, :content_type => 'text/plain'
end
我希望有所帮助。这有点粗糙,但希望它给出了正确的想法。