So, you want to know how to get emails from GMail to manipulate in your Rails app right?
First let’s create our app and generate our main class:
$ rails app $ cd app $ script/generate scaffold task name:string description:text $ rake db:migrate $ rm -rf public/index.html
Map the tasks index action to be the root of the app:
#config/routes.rb ActionController::Routing::Routes.draw do |map| map.resources :tasks map.root :tasks end
At this point we have a working very simple app to manage our tasks list. Let’s start our server:
$ script/serverYou can go to http://localhost:3000 and see our app running.
Now, create the mailer that will check gmail for us:
$ script/generate mailer MailReaderEdit the generated mailer to look like the above:
# app/models/mail_reader.rb require 'net/pop' class MailReader < ActionMailer::Base def receive(email) task = Task.new :name => email.subject, :description => email.body if email.has_attachments? email.attachments.each do |attachment| task.assets.create :data => attachment end end end def self.check_mail logger = RAILS_DEFAULT_LOGGER logger.info "Checking for emails..." Net::POP3.enable_ssl(OpenSSL::SSL::VERIFY_NONE) #This line raises error if ruby version < 1.8.7 Net::POP3.start("pop.gmail.com", 995, "your-email@gmail.com", "your-password") do |pop| if pop.mails.empty? logger.info "No emails found." else pop.mails.each do |email| begin logger.info "Retrieving mail..." MailReader.receive(email.pop) email.delete rescue Exception => e logger.error "[" + Time.now.to_s + "] " + e.message end end end end logger.info "Done." end end
Note that your ruby version need to be 1.8.7 or higher.
Now we need to create our model that will keep the attachments and install the paperclip plugin:
$ script/plugin install git://github.com/thoughtbot/paperclip.git $ script/generate model asset
Put this in the migration file:
# db/migrate/20090303181609_create_assets.rb class CreateAssets < ActiveRecord::Migration def self.up create_table :assets do |t| t.string :data_file_name t.string :data_content_type t.integer :data_file_size t.datetime :data_updated_at t.references :task t.timestamps end end def self.down drop_table :assets end end
Run the migration:
$ rake db:migrate
Create the associations in the models:
# app/models/asset.rb class Asset < ActiveRecord::Base belongs_to :task has_attached_file :data end
# app/models/task.rb class Task < ActiveRecord::Base has_many :assets end
…and finally, modify the task show template to show the attachments:
<!-- app/views/tasks/show.html.erb --> <b>Name:</b> <%=h @task.name %> <b>Description:</b> <%=h @task.description %> <% unless @task.assets.blank? -%> <b>Attachments:</b> <% @task.assets.each do |asset| -%> <%= link_to "Download \"#{asset.data_file_name}\"", asset.data.url %> <% end -%> <% end -%> <%= link_to 'Edit', edit_task_path(@task) %> | <%= link_to 'Back', tasks_path %>
You can set up a cron job to check if there are new emails every two minutes by putting this your crontab file:
##__email_checker__ */2 * * * * RAILS_ENV=production /usr/local/bin/ruby /home/mauricio/pdn-posts/how-to-pull-emails-from-gmail-to-rachments/app/script/runner MailReader.check_mail
And last but not least, the source code used for this post is hosted on github.