Search code examples
ruby-on-railsemail-parsing

Rails Email Parsing


I want to have the ability in my rails application to receive incoming emails and parse them in a particular way.

incoming_controller.rb

class IncomingController < ApplicationController
  skip_before_action :verify_authenticity_token, only: [:create]
  skip_before_action :authenticate_user!, only: [:create]
  def create
    # Find the user
     user = User.find_by(email: params[:sender])

     # Find the topic
     topic = Topic.find_by(title: params[:subject])

     # Assign the url to a variable after retreiving it from
     url = params["body-plain"]

     # If the user is nil, create and save a new user
     if user.nil?
       user = User.new(email: params[:sender], password: "password")
       user.save!
     end

     # If the topic is nil, create and save a new topic
      if topic.nil?
        topic = Topic.new(title: params[:subject], user: user)

        topic.save!
      end

      bookmark = topic.bookmarks.build(user: user, url: url, description: "bookmark for #{url}")

      bookmark.save!

    # Assuming all went well.
    head 200
  end
end

Using this controller I can only extract 3 values = user :sender, topic :subject and url "body-plain".

How can I add a 4th value in the email to parse a :description?


Solution

  • A params[:description] implementation should theoretically work the same as the other params items used in your method, you just need to make sure that that whatever calls your IncomingController#create action is sending a :description param.

    Or, if you cannot add parameters to whatever is calling the controller action, maybe you could add it to the params['body-plain'] that you're currently using for the url? You could store multiple fields in the email body by using a serialized text format, for example (using YAML):

    url: http://example.com
    description: I'm a description
    

    Then in your controller, you'd parse that field like this:

    class IncomingController < ApplicationController
      require 'yaml'
      def create
        # ...
        body_params = YAML.load(params['body-plain'])
        url = body_params[:url]
        description = body_params[:description]
        # ...
      end
    end