gửi mail tự động với whenever và sidekiq
Gửi mail là một trong những chức năng không thể thiếu của một trang web, mail tự động nhằm mục đích báo cáo tình hình hoạt động của một trang web cho người quản lý cũng như các user. Bắt đầu với gửi mail tự động, ta bắt đầu vói việc lập lịch bằng whenever Thêm gem whenever vào gem file và ...
Gửi mail là một trong những chức năng không thể thiếu của một trang web, mail tự động nhằm mục đích báo cáo tình hình hoạt động của một trang web cho người quản lý cũng như các user.
Bắt đầu với gửi mail tự động, ta bắt đầu vói việc lập lịch bằng whenever
Thêm gem whenever vào gem file và bundle
gem 'whenever', :require => false
Khởi tạo file thực thi
bundle install
wheneverize .
Sau khi khởi chạy dòng lệnh trên, ta bắt đầu config thời gian chạy.
+---------------- minute (0 - 59) | +------------- hour (0 - 23) | | +---------- day of month (1 - 31) | | | +------- month (1 - 12) | | | | +---- day of week (0 - 6) (Sunday=0) | | | | | * * * * * command to be executed
Example
#config/schedule.rb every 1.minutes do rake "db:migrate:reset" end
Sau khi config xong thời gian tự động chạy, ta update cho hệ thống
whenever --update-crontab #[write] crontab file updated
Ta có thể thấy lịch trình trên terminal theo định dạng
* * * * * /bin/bash -l -c 'cd /home/ngocha/workspace/fts_62 && RAILS_ENV=production bundle exec rake db:migrate:reset --silent'
Ngoài ra còn 1 số lệnh để cài đặt hệ thống
crontab -l : xem lịch hệ thống crontab -r : xóa lịch hệ thống
Ở đây, chúng ta đã hoàn thành lập lịch cho hệ thống với 1 lệnh rake, nhưng chúng ta cần phải kết hợp với send mail sử dụng sidekiq.
Đầu tiên, chúng ta cần phải gửi mail bằng hệ thống mặc định của rails.
#app/mailers/user_mailer.rb class UserMailer < ApplicationMailer default from: Settings.mail_from def mail_month course @supervisor = course.supervisor ... mail to: @supervisor.email, subject: t("mail.mail_month", content: @course.content) end end
#app/view/user_mailer/mail_month.html.erb <h1><%= @supervisor.name %></h1> ...
#config/environments/development.rb config.consider_all_requests_local = true config.action_controller.perform_caching = false config.action_mailer.default_url_options ={host: "localhost", port: 3000} # Don't care if the mailer can't send. config.active_job.queue_adapter = :sidekiq config.active_job.queue_name_prefix = "mysite" config.active_job.queue_name_delimiter = "_" config.action_mailer.perform_deliveries = true config.action_mailer.raise_delivery_errors = true config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { address: "smtp.gmail.com", port: 587, domain: "example.com", user_name: ENV["GMAIL_USERNAME"], password: ENV["GMAIL_PASSWORD"], authentication: "plain", enable_starttls_auto: true}
Ở đây, ta có thể test việc gửi mail bằng cách gọi
UserMailer.mail_month(course).deliver_now
Hãy nhớ config tài khoản Gmail của bạn cho phép truy cập với độ tin cậy thấp và unlock captcha. Nếu bạn chưa config hãy config theo link dưới đây
https://www.google.com/settings/security/lesssecureapps https://accounts.google.com/b/0/DisplayUnlockCaptcha
Sau khi test đã gửi được mail với mail thường, chúng ta sẽ tiếp tục đưa mail chạy qua sidekiq nhằm mục đích giảm tải cho sever.
Khi bạn gửi mail qua sidekiq, sidekiq sẽ tạo ra một hệ thống gửi mail chạy độc lập với sever. Do đó nó sẽ giảm tải cho sever trong quá trình gửi mail.
gem "sidekiq"
bundle install
Sau đó ta tạo folder workers trong thư mục app. và tạo các file worker trong thư mục này
#app/workers/monthly_worker.rb class MonthlyWorker include Sidekiq::Worker MAIL_MONTH = 1 def perform action case action when MAIL_MONTH Course.all.each do |course| send_email_when_end_month course end end end private def send_email_when_end_month course UserMailer.mail_month(course).deliver_now end end
Nhớ bật sever sidekiq trong terminal bằng lệnh bundle exec sidekiq. Tới đây chúng ta đã thành công trong việc gửi mail thông qua sidekiq.
Việc cuối cùng chúng ta cần làm là gắn lịch hệ thống với tiến trình gửi mail của sidekiq
Như đã nói ở trên, sau mỗi chu trình lập lịch whenever sẽ chạy lệnh rake
#config/schedule.rb rake "db:migrate:reset"
một lần. Ở đây, ta cần tìm hiểu về lệnh rake 1 chút
Để chạy được lệnh rake ta cần tạo foldler tasks trong thư mục lib và tạo 1 file :rake trong đó.
#lib/tasks/job:rake namespace :job do desc "TODO" task mailmonth: :environment do MonthlyWorker.perform_async MonthlyWorker::MAIL_MONTH end end
Ta cần config lại đia chỉ rake của whenever để nó chỉ tới mail hệ thống.
#config/schedule.rb set :environment, "development" #để kiểm soát lỗi gửi mail hệ thống set :output, ".../log.log" #đường dẫn tuyệt đối every "0 0 1 * *" do rake "job:mailmonth" end
Ta có thể test thử bằng rails c của terminal để xem sidekiq có chạy không bằng lệnh rake "job:mailmonth" cuối cùng ta update lại crontab của whenever bằng lệnh whenever --update-crontab
Có thể 1 số bạn sẽ không gửi được mail hoặc gửi mail báo lỗi ` ``undefine bundler```. Trong trường hợp này chúng ta cần chạy bundle cho vendor.
bundle install --path=vendor/bundle
Việc gửi mail tự động đến đây đã hoàn thành, chúc các bạn thành công trong công việc. Cám ơn đã xem bài viết của mình.
tài liệu tham khảo
https://launchschool.com/blog/cron-jobs-and-rails
https://github.com/javan/whenever
https://github.com/mperham/sidekiq/wiki/Getting-Started