Что мне понадобится в контроллере Rails 3 для обработки входящих писем и их вставки в базу данных? - PullRequest
0 голосов
/ 21 марта 2011

Я пытаюсь настроить приложение 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.

Вот что у меня проблемы с сортировкой: что происходит в моем контроллере "input_mails"? Как я могу убедиться, что когда пользователь отвечает по электронной почте, что контроллер в "прибывающих письмах" может найти job_id и current_user.id (или user_id), а затем вставить эту информацию в базу данных?

Я думаю, что мне нужно захватить адрес электронной почты пользователя, а затем также указать job_id в строке темы ... хммм ....

У кого-нибудь есть опыт настройки обработки входящей почты в Rails 3?

Ответы [ 2 ]

3 голосов
/ 21 марта 2011

Есть несколько способов сделать это. Обычная техника - установить 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

Электронная почта отправляется с адресом from / reply_to, например [token] @ msg.yoursite.com (Вы также можете использовать комментарии + [token_or_id] @ msg.yoursite.com, если хотите, - см. Параметр одноразового использования, предоставляемый cloudmailin) ​​

 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, вам необходимо правильно настроить записи 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

Преимущество такого способа состоит в том, что он полностью универсален. Вы можете оставлять комментарии к вакансиям, комментарии к комментариям или что угодно. Если вы создаете другую модель, для которой вы также хотите разрешить ответ по электронной почте ... просто обновите заголовки, и все готово. Единственная проблема заключается в том, что вы должны быть осторожны с удалением этих заголовков почтовыми клиентами. Посмотрите эту тему для получения дополнительной информации об этом.

В настоящее время я использую первую технику, и она работает очень хорошо. Тем не менее, я буду рефакторинг и попробую второй метод в конце этой недели.

1 голос
/ 21 марта 2011

Я не уверен, что это полный ответ, но позвольте мне дать ему краткий обзор, и я смогу обновить его, когда у меня будет немного больше времени.

Во-первых, я бы начал с работы, возможно, какчасть по адресу.Используйте comment+1@domain.com с 1, обозначающим, что это задание номер один.Эта часть после плюса называется одноразовой частью в CloudMailin (params [: одноразовый]. Адрес электронной почты пользователя можно затем извлечь из тела сообщения, используя 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

Я надеюсь, что это помогает. Это немного грубо, но, надеюсь, это дает правильное представление.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...