Monday, January 14, 2013

Actionmailer, rake task & Scheduler

Please follow the below steps to implement an actionmailer in your app, create a rake task to call the mailer function and schedule that particular task to run on a specific time.


1. To Implement action mailer in rails~3:

Action mailer feature of rails allows to send emails. A mailer model and a view is required for  the same.
In this tutorial, we would send the email using gmail service.


Step 1:  Create a demo project.
               rails new mail_project

Step 2:  Create a User model.
              rails generate scaffold  User name:string email:string

Step 3:  Create a mailer model
              rails generate mailer UserMailer                  
              create  app/mailers/user_mailer.rb             
              invoke  erb                                             
              create    app/views/user_mailer                 
              invoke  test_unit                                      
              create    test/functional/user_mailer_test.rb 
               
              
Step 4: Now, we  need to configure the SMTP mail settings in development.rb.

          in config\environments\development.rb

          config.action_mailer.default_url_options = { :host => 'localhost:3000.com' }
          config.action_mailer.smtp_settings =  {
          :enable_starttls_auto => true,
          :address        => 'smtp.gmail.com',
          :port           => 587,                                   # default port for gmail.
          :domain         => 'your.domain.com',
          :authentication => :login,
          :content_type   => "text/html",
          :user_name      => 'youremail@gmail.com',
          :password       => 'password'
                                                                  }

Note:  To deploy the app on heroku, edit the settings in production.rb 

Step 5: Edit the mailer and create your mail method.
             
            in app/mailers/user_mailer.rb , lets define a method demo_mail

            def demo_mail(user)
            mail(:from => "Testmail@demo.com",
                     :to => user.email
                     :subject => "Greet User")
            end
             
Note: To add pictures as inline attachment/logo in rails 3, use as:
 attachments.inline['rails.png']=File.read('app/assets/images/rails.png')   

Step 6: Create a view template to render the view, create the view with the same method name which we used in our user_mailer.rb.
i.e views/user_mailer/demo_mail.html.erb

  <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">
  <html lang="en">
  <head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <style type="text/css" media="screen" class = "content">
   h3 { color: #f00; }
   ul { list-style: none; }
  </style>
  </head>
  <body>
  <strong><p class="text-warning">Dear <%= @user %>,</p></strong>
  <p class="text-success">Hello, How are you ?</p>
  <%= image_tag attachments['rails.png'].url % >  
  </body>
  </html> 
Note :  We have use attachments.url in image_tag to display the inline attachment. 

Step 7: Add a line to call the method demo_mail of UserMailer.
        -  this could be done from a task or from some method of User controller.
           
           UserMailer.demo_mail(user).deliver!

Points to ponder:

1. While uploading your app on heroku, make sure that you have done smtp mail setting in file production.rb
2. Inline attachment might be block from your office network. So you can check them on gmail network.
3. Apart from that there might be few more problem on restricted network.


2. How to Create a rake task:

Step 1: Introduction to rake

rake is a task which is created at /lib/tasks with .rake extension. Doing this, rails picks it up  automatically and make it available to you.
ex: demo.rake

- you can see your task listed by doing rake -T

- to run your task:
  rake demo

Step 2: Writing a task on mailer created above

          in lib/tasks/demo.rake
          
      namespace :demo do
     desc "This is to send an email to users"
     task(:mail_users => :environment) do
     UserMailer.demo_mail(user).deliver!    # as we saw in Step7 above                        
     end
     end

Similarly, many tasks can be created in this file and they all would be listed with description.

Step 3: To run/schedule task

this task can be run as rake demo:mail_users
or else we can schedule our task to run later.(Covered in section 3 of this blog)


3. How to schedule a rake task:

To schedule a task demo of 'rufus-scheduler' is done here.
Otherwise there are so many ways to schedule a task. ex clockwork and so many.

Step 1: Introduction to rake

rufus-scheduler is a Ruby gem for scheduling pieces of code (jobs). It understands running a job AT a certain time.

Step 2:  Add Gem and install it

add gem 'rufus-scheduler' to your gemfile and run bundle install.
gem install rufus-scheduler

Step 3: Create a task_scheduler.rb file in /config/initializers

Schedule the task like:

require 'rubygems'
require 'rake'
require 'rufus/scheduler'
scheduler = Rufus::Scheduler.start_new
scheduler.every '15m' do
system 'bundle exec rake demo:mail_users'
end 

# this will trigger the mail_users task every 15 minutes.

Note: Similarly, task can be schedule every hour, daily, weekly or monthly basis




Hope there might be something for you in this blog !!