diff --git a/app/controllers/light/newsletters_controller.rb b/app/controllers/light/newsletters_controller.rb index acabd75..4ca8bc9 100644 --- a/app/controllers/light/newsletters_controller.rb +++ b/app/controllers/light/newsletters_controller.rb @@ -72,7 +72,7 @@ def send_opt_in_test end def send_opt_in - Light::OptInWorker.perform_async(@newsletter.id.to_s) + Light::OptInWorker.perform_async(params[:template_type], @newsletter.id.to_s) redirect_to opt_in_newsletters_path end @@ -86,7 +86,7 @@ def send_opt_out_test end def send_opt_out - Light::OptOutWorker.perform_async(@newsletter.id.to_s) + Light::OptOutWorker.perform_async(params[:template_type], @newsletter.id.to_s) redirect_to opt_out_newsletters_path end diff --git a/app/controllers/light/users_controller.rb b/app/controllers/light/users_controller.rb index a53e4d2..af774cd 100644 --- a/app/controllers/light/users_controller.rb +++ b/app/controllers/light/users_controller.rb @@ -67,7 +67,7 @@ def subscribe end def sendmailer - Light::UserWorker.perform_async + Light::UserWorker.perform_async(params[:template_type]) redirect_to newsletters_path end diff --git a/app/models/light/newsletter.rb b/app/models/light/newsletter.rb index 828b286..1899ee3 100644 --- a/app/models/light/newsletter.rb +++ b/app/models/light/newsletter.rb @@ -13,6 +13,7 @@ class Newsletter field :sent_on, type: Date field :users_count, type: Integer, default: 0 field :newsletter_type, type: String, default: VALID_NEWSLETTER_TYPES[:MONTHLY] + field :sent_via_sendgrid_api, type: Boolean, default: false validates :content, :subject, :newsletter_type, presence: true validates :subject, uniqueness: true diff --git a/app/services/light/sendgrid_mailer.rb b/app/services/light/sendgrid_mailer.rb new file mode 100644 index 0000000..e9bf9cc --- /dev/null +++ b/app/services/light/sendgrid_mailer.rb @@ -0,0 +1,69 @@ +module Light + class SendgridMailer + require 'sendgrid-ruby' + include SendGrid + + TEMPLATES = { + newsletter_id: ENV['NEWSLETTER_ID'] + } + + def self.mail_to(user=nil) + if Rails.env.production? + user.email + else + ENV['NEWSLETTER_DEFAULT_EMAILS'] + end + end + + def self.send(user, extra_params = {}) + to = SendgridMailer.mail_to(user) + substitutions = SendgridMailer.substitutions_for(user) + template_id = TEMPLATES[:newsletter_id] + SendgridMailer.send_mail(to, substitutions, template_id) + end + + def self.send_mail(to, substitutions, template_id) + data = { + 'personalizations': [ + { + 'to': [ + { + 'email': to + } + ], + 'dynamic_template_data': substitutions + } + ], + 'from': { + 'email': 'no-reply@joshsoftware.com' + }, + 'template_id': template_id + } + sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY']) + begin + response = sg.client.mail._('send').post(request_body: data) + return response.status_code + rescue Exception => e + puts 'Error in sending newsletter email...' + puts e.inspect + Rollbar.critical(e, e.message, { + email_to: to, + template_id: template_id, + substitutions: substitutions, + backtrace: e.backtrace + }) + return '500' + end + end + + def self.substitutions_for(user, extra_params: {}) + { + unsubscribeURL: unsubscribe_url + "/unsubscribe?token=#{user.token}" + }.merge(extra_params) + end + + def self.unsubscribe_url + 'https://' + ActionMailer::Base.default_url_options[:host] + end + end +end \ No newline at end of file diff --git a/app/views/light/newsletters/_top_navbar.html.haml b/app/views/light/newsletters/_top_navbar.html.haml index bbabe36..9c02602 100644 --- a/app/views/light/newsletters/_top_navbar.html.haml +++ b/app/views/light/newsletters/_top_navbar.html.haml @@ -11,6 +11,6 @@ = menu_item "Show Users", users_path, ({:method => 'get'} if params[:controller] == 'light/users' && params[:action].in?(['new', 'create'])) = menu_group :pull => :right do .btn-mail - = content_tag :a, "Send Mail", :href => sendmailer_path, :class => 'btn btn-danger', :data => { :confirm => 'Are you sure ?'} + = content_tag :a, "Send Mail", :href => sendmailer_path(template_type: 'Newsletter'), :class => 'btn btn-danger', :data => { :confirm => 'Are you sure ?'} = content_tag :a, "Test Mail", :href => testmail_path, :class => 'btn btn-success' %br diff --git a/app/views/light/newsletters/show.html.haml b/app/views/light/newsletters/show.html.haml index d1c70c9..0686b62 100644 --- a/app/views/light/newsletters/show.html.haml +++ b/app/views/light/newsletters/show.html.haml @@ -1,11 +1,11 @@ = render 'top_navbar' = raw @newsletter.content - if @newsletter.opt_in? - = link_to "Send Opt-In Mail", send_opt_in_newsletter_path(@newsletter), + = link_to "Send Opt-In Mail", send_opt_in_newsletter_path(@newsletter, template_type: 'Newsletter'), :class => 'btn btn-danger', :data => { :confirm => 'Are you sure ?'}, method: :post = link_to "Send Opt-In Test Mail", test_opt_in_newsletter_path(@newsletter), :class => "btn btn-success" - elsif @newsletter.opt_out? - = link_to "Send Opt-Out Mail", send_opt_out_newsletter_path(@newsletter), + = link_to "Send Opt-Out Mail", send_opt_out_newsletter_path(@newsletter, template_type: 'Newsletter'), :class => 'btn btn-danger', :data => { :confirm => 'Are you sure ?'}, method: :post = link_to "Send Opt-Out Test Mail", test_opt_out_newsletter_path(@newsletter), :class => "btn btn-success" diff --git a/app/workers/light/hard_worker.rb b/app/workers/light/hard_worker.rb index 3b86625..07de594 100644 --- a/app/workers/light/hard_worker.rb +++ b/app/workers/light/hard_worker.rb @@ -3,18 +3,18 @@ class HardWorker include Sidekiq::Worker sidekiq_options :queue => :lightair - def perform(user_ids, newsletter_id, date, status = nil) + def perform(template_type, user_ids, newsletter_id, date, status = nil) newsletter = Light::Newsletter.where(id: newsletter_id).first user_ids.each do |id| user = Light::User.where(id: id, :sent_on.nin => [date]).first if user.present? - Light::UserMailer.welcome_message(user.email_id, newsletter, user.token).deliver + response = send_mail(newsletter, user, template_type) sent_on = user.sent_on << date - if status.present? && status.include?('Opt in') + if response == '202' && status.present? && status.include?('Opt in') user.update_attributes(sent_on: sent_on, sidekiq_status: status, opt_in_mail_sent_at: DateTime.now) - elsif status.present? && status.include?('Opt out') + elsif response == '202' && status.present? && status.include?('Opt out') user.update_attributes(sent_on: sent_on, sidekiq_status: 'Subscribed', subscribed_at: DateTime.now, @@ -25,5 +25,14 @@ def perform(user_ids, newsletter_id, date, status = nil) end end end + + def send_mail(newsletter, user, template_type) + if template_type == 'Sendgrid' + Light::SendgridMailer.send(user) + elsif template_type == 'Newsletter' + Light::UserMailer.welcome_message(user.email_id, newsletter, user.token).deliver_now + return '202' + end + end end end diff --git a/app/workers/light/opt_in_worker.rb b/app/workers/light/opt_in_worker.rb index ffc4f24..83ae989 100644 --- a/app/workers/light/opt_in_worker.rb +++ b/app/workers/light/opt_in_worker.rb @@ -3,26 +3,40 @@ class OptInWorker include Sidekiq::Worker sidekiq_options :queue => :lightair - def perform(newsletter_id) + def perform(template_type, newsletter_id=nil) + newsletter = Light::Newsletter.where(id: newsletter_id).first + + if template_type == 'Newsletter' && newsletter + send_opt_in_mail(newsletter, template_type) + elsif template_type == 'Sendgrid' + newsletter = Light::Newsletter.new( + newsletter_type: Light::Newsletter::VALID_NEWSLETTER_TYPES[:OPT_IN], + subject: "Josh Software | Newsletter | #{Date.today.strftime("%B %Y")}", + sent_via_sendgrid_api: true + ) + newsletter.save(validate: false) + send_opt_in_mail(newsletter, template_type) + else + logger.info = "No newsletter present" + end + end + + def send_opt_in_mail(newsletter, template_type) date = Date.today.strftime("%Y%m") users = Light::User.users_for_opt_in_mail number_of_opt_in_users = users.count number_of_opt_in_users_count = number_of_opt_in_users current_batch = 0 users_in_batch = 250 - newsletter = Light::Newsletter.find_by(id: newsletter_id) - if newsletter - while number_of_opt_in_users > 0 - user_ids = users.limit(users_in_batch).skip(users_in_batch*current_batch).collect { |user| user.id.to_s } - current_batch += 1 - number_of_opt_in_users -= users_in_batch - Light::HardWorker.perform_async(user_ids, newsletter.id.to_s, date, "Opt in mail sent") - end - opt_in_count = newsletter.users_count + number_of_opt_in_users_count - newsletter.update_attribute(:users_count, opt_in_count) - else - logger.info = "No newsletter present" + + while number_of_opt_in_users > 0 + user_ids = users.limit(users_in_batch).skip(users_in_batch*current_batch).collect { |user| user.id.to_s } + current_batch += 1 + number_of_opt_in_users -= users_in_batch + Light::HardWorker.perform_async(template_type, user_ids, newsletter.id.to_s, date, "Opt in mail sent") end + opt_in_count = newsletter.users_count + number_of_opt_in_users_count + newsletter.set(users_count: opt_in_count) end end end diff --git a/app/workers/light/opt_out_worker.rb b/app/workers/light/opt_out_worker.rb index 72da0b3..3a06472 100644 --- a/app/workers/light/opt_out_worker.rb +++ b/app/workers/light/opt_out_worker.rb @@ -3,26 +3,42 @@ class OptOutWorker include Sidekiq::Worker sidekiq_options :queue => :lightair - def perform(newsletter_id) + def perform(template_type, newsletter_id=nil) + newsletter = Light::Newsletter.where(id: newsletter_id).first + + if template_type == 'Newsletter' && newsletter + send_opt_out_mails(newsletter, template_type) + elsif template_type == 'Sendgrid' + newsletter = Light::Newsletter.new( + newsletter_type: Light::Newsletter::VALID_NEWSLETTER_TYPES[:OPT_OUT], + subject: "Josh Software | Newsletter | #{Date.today.strftime("%B %Y")}", + sent_via_sendgrid_api: true + ) + newsletter.save(validate: false) + send_opt_out_mails(newsletter, template_type) + else + logger.info = 'No newsletter present' + end + end + + def send_opt_out_mails(newsletter, template_type) date = Date.today.strftime("%Y%m") users = Light::User.users_for_opt_out_mail number_of_opt_out_users = users.count number_of_opt_out_users_count = number_of_opt_out_users current_batch = 0 users_in_batch = 250 - newsletter = Light::Newsletter.find_by(id: newsletter_id) - if newsletter - while number_of_opt_out_users > 0 - user_ids = users.limit(users_in_batch).skip(users_in_batch*current_batch).collect { |user| user.id.to_s } - current_batch += 1 - number_of_opt_out_users -= users_in_batch - Light::HardWorker.perform_async(user_ids, newsletter.id.to_s, date, 'Opt out mail sent') - end - opt_out_count = newsletter.users_count + number_of_opt_out_users_count - newsletter.update_attribute(:users_count, opt_out_count) - else - logger.info = 'No newsletter present' + + while number_of_opt_out_users > 0 + user_ids = users.limit(users_in_batch) + .skip(users_in_batch*current_batch) + .collect { |user| user.id.to_s } + current_batch += 1 + number_of_opt_out_users -= users_in_batch + Light::HardWorker.perform_async(template_type, user_ids, newsletter.id.to_s, date, 'Opt out mail sent') end + opt_out_count = newsletter.users_count + number_of_opt_out_users_count + newsletter.set(users_count: opt_out_count) end end end diff --git a/app/workers/light/user_worker.rb b/app/workers/light/user_worker.rb index 992b28c..1dc891e 100644 --- a/app/workers/light/user_worker.rb +++ b/app/workers/light/user_worker.rb @@ -3,30 +3,53 @@ class UserWorker include Sidekiq::Worker sidekiq_options :queue => :lightair - def perform + def perform(template_type) + newsletter = Light::Newsletter.where( + newsletter_type: Light::Newsletter::VALID_NEWSLETTER_TYPES[:MONTHLY] + ).order_by([:sent_on, :desc]).first + + if template_type == 'Newsletter' && newsletter + send_monthly_mails(newsletter, template_type) + elsif template_type == 'Sendgrid' + newsletter = Light::Newsletter.new( + newsletter_type: Light::Newsletter::VALID_NEWSLETTER_TYPES[:MONTHLY], + subject: "Josh Software | Newsletter | #{Date.today.strftime("%B %Y")}", + sent_via_sendgrid_api: true + ) + newsletter.save(validate: false) + send_monthly_mails(newsletter, template_type) + else + logger.info = "No newsletter present" + end + end + + def send_monthly_mails(newsletter, template_type) date = Date.today.strftime("%Y%m") - number_of_subscribed_users = Light::User.where(is_subscribed: true, :sent_on.nin => [date], is_blocked: {"$ne" => true}).count - #number_of_subscribed_users = Light::User.users_for_opt_in_mail.count + number_of_subscribed_users = Light::User.where( + is_subscribed: true, + :sent_on.nin => [date], + is_blocked: {"$ne" => true} + ).count + number_of_subscribed_users_count = number_of_subscribed_users current_batch = 0 users_in_batch = 250 - newsletter = Light::Newsletter.where(newsletter_type: Light::Newsletter::VALID_NEWSLETTER_TYPES[:MONTHLY]). - order_by([:sent_on, :desc]).first - #newsletter = Light::Newsletter.where(newsletter_type: Light::Newsletter::VALID_NEWSLETTER_TYPES[:OPT_IN]). - # order_by([:sent_on, :desc]).first - if newsletter - while number_of_subscribed_users > 0 - user_ids = Light::User.where(is_subscribed: true, :sent_on.nin => [date] , is_blocked: {"$ne" => true}).order_by([:email_id, :asc]).limit(users_in_batch).skip(users_in_batch*current_batch).collect { |user| user.id.to_s } - #user_ids = Light::User.users_for_opt_in_mail.order_by([:email_id, :asc]).limit(users_in_batch).skip(users_in_batch*current_batch).collect { |user| user.id.to_s } - current_batch += 1 - number_of_subscribed_users -= users_in_batch - Light::HardWorker.perform_async(user_ids, newsletter.id.to_s, date) - end - newsletter.update_attribute(:users_count, number_of_subscribed_users_count) - else - logger.info = "No newsletter present" + while number_of_subscribed_users > 0 + user_ids = Light::User.where( + is_subscribed: true, + :sent_on.nin => [date], + is_blocked: {"$ne" => true} + ).order_by([:email_id, :asc]) + .limit(users_in_batch) + .skip(users_in_batch*current_batch) + .collect { |user| user.id.to_s } + + current_batch += 1 + number_of_subscribed_users -= users_in_batch + Light::HardWorker.perform_async(template_type, user_ids, newsletter.id.to_s, date) end + newsletter.set(users_count: number_of_subscribed_users_count) end end end diff --git a/light.gemspec b/light.gemspec index e63a03f..461f774 100644 --- a/light.gemspec +++ b/light.gemspec @@ -46,6 +46,6 @@ Gem::Specification.new do |s| s.add_dependency 'rest-client' s.add_dependency 'select2-rails' s.add_dependency 'sendgrid_toolkit' - + s.add_dependency 'sendgrid-ruby', '~> 6.2.0' s.add_dependency 'mongoid-history' end