Tom Pinchen
Tom Pinchen

Reputation: 2497

Where to put ruby helpers Sendgrid V3 Send API

I am trying to integrate Sendgrid using their Github documentation.

In their examples they suggest that you create a Mail Helper class but give very little guidance on how to actually do this.

I have a scheduled Rake task running using Heroku Scheduler that I would like to send an email when the task is complete and was hoping to use Sendgrid for this.

Currently I have the following code in /lib/tasks/scheduler.rake

require 'sendgrid-ruby'
include SendGrid

desc "Testing Email Rake"
task :test_sendgrid => :environment do
  puts 'Starting Sendgrid Email Test'
  send_task_complete_email()
  puts 'Sendgrid Email Test Complete'
end 

def send_task_complete_email
  from = Email.new(email: '[email protected]')
  to = Email.new(email: '[email protected]')
  subject = 'Sending with SendGrid is Fun'
  content = Content.new(type: 'text/plain', value: 'and easy to do anywhere, even with Ruby')
  mail = Mail.new(from, subject, to, content)

  sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'])
  response = sg.client.mail._('send').post(request_body: mail.to_json)
  puts response.status_code
  puts response.body
  puts response.headers
end

I don't have the helper classes added anywhere as I am not sure which bits to add or where to put them. At the moment when I run this task I receive a 400 Bad request error back from Sendgrid and I believe it's because I don't have these helpers in place.

Any advice to fix this would be much appreciated as when I try to integrate without using the helpers and instead writing out the JSON I can successfully send the email but receive a TypeError: Mail is not a module when I try to deploy to Heroku.

UPDATE: ERROR RECEIVED USING ANSWER BELOW

400
{"errors":[{"message":"Invalid type. Expected: object, given: string.","field":"(root)","help":"http://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/errors.html#-Request-Body-Parameters"}]}
{"server"=>["nginx"], "date"=>["Thu, 07 Jun 2018 09:02:42 GMT"], "content-type"=>["application/json"], "content-length"=>["191"], "connection"=>["close"], "access-control-allow-origin"=>["https://sendgrid.api-docs.io"], "access-control-allow-methods"=>["POST"], "access-control-allow-headers"=>["Authorization, Content-Type, On-behalf-of, x-sg-elas-acl"], "access-control-max-age"=>["600"], "x-no-cors-reason"=>["https://sendgrid.com/docs/Classroom/Basics/API/cors.html"]}

Upvotes: 0

Views: 656

Answers (1)

Moamen Naanou
Moamen Naanou

Reputation: 1713

You need to use Action Mailer:

First create a mailer class to add your mail details (i.e. UserMailer):

$ bin/rails generate mailer UserMailer

it will create the following files:

create  app/mailers/user_mailer.rb
create  app/mailers/application_mailer.rb
invoke  erb
create    app/views/user_mailer
create    app/views/layouts/mailer.text.erb
create    app/views/layouts/mailer.html.erb
invoke  test_unit
create    test/mailers/user_mailer_test.rb
create    test/mailers/previews/user_mailer_preview.rb

Now edit the file app/mailers/user_mailer.rb:

require 'sendgrid-ruby'
include SendGrid

class UserMailer < ApplicationMailer
  def send_task_complete_email
    from = Email.new(email: '[email protected]')
    to = Email.new(email: '[email protected]')
    subject = 'Sending with SendGrid is Fun'
    content = Content.new(type: 'text/plain', value: 'and easy to do anywhere, even with Ruby')
    mail = Mail.new(from, subject, to, content)

    sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'])
    response = sg.client.mail._('send').post(request_body: mail.to_json)
    puts response.status_code
    puts response.body
    puts response.headers
  end
end

Then you can simply send emails using this code:

UserMailer.send_task_complete_email.deliver_now

Or from rake task:

desc "Testing Email Rake"
task :test_sendgrid => :environment do
  puts 'Starting Sendgrid Email Test'
  UserMailer.send_task_complete_email.deliver_now
  puts 'Sendgrid Email Test Complete'
end 

Update:

Because there is Mail module in Rails, you need to specify the correct SendGrid Mail module by changing:

 mail = Mail.new(from, subject, to, content)

to

mail = SendGrid::Mail.new(from, subject, to, content)

Upvotes: 3

Related Questions