lib/mailcannon/adapters/sendgrid_web.rb
require 'json-schema'
# Provides the Sendgrid Web API Adapter, refer to http://sendgrid.com/docs/API_Reference/Web_API/mail.html
module MailCannon::Adapter::SendgridWeb
include MailCannon::Adapter
module InstanceMethods
def send!
begin
validate_envelope!
response = send_multiple_emails
success = successfully_sent?(response)
raise MailCannon::Adapter::DeliveryFailedException.new(response) unless success
self.after_sent
rescue Exception => e
if e.message == "[\"Permission denied, wrong credentials\"]"
raise MailCannon::Adapter::AuthException
else
raise e
end
end
true
end
def send_bulk!
self.send! # send! does bulk too!
end
def auth_pair
default_auth = {'username'=>ENV['SENDGRID_USERNAME'],'password'=>ENV['SENDGRID_PASSWORD']}
begin
self.auth || self.envelope_bag.auth || default_auth
rescue Exception => e
logger.warn "Unable to read auth config from Envelope or Bag, using default auth options from ENV"
return default_auth
end
end
end
def self.included(receiver)
receiver.send :include, InstanceMethods
end
private
def api_client
SendGridWebApi::Client.new(self.auth_pair['username'],self.auth_pair['password'])
end
def validate_envelope!
raise "Invalid Document! #{self.errors.messages}" unless self.valid?
end
def prepare_xsmtpapi!
validate_envelope!
self.xsmtpapi = {} if self.xsmtpapi.nil?
self.xsmtpapi['sub']={} unless self.xsmtpapi['sub']
self.xsmtpapi = self.xsmtpapi.deep_merge(build_xsmtpapi({'to'=>self.to},{'sub'=>self.substitutions}))
validate_xsmtpapi!
self.save!
end
def build_to_subs(placeholder, to_key)
selected_hash_array = []
self.to.map {|h| selected_hash_array.push h[to_key]||h[to_key.to_sym]||''}
{'sub'=>{"#{placeholder}"=>selected_hash_array}}
end
def build_name_subs
placeholder = MailCannon.config['default_name_placeholder'] || '%name%'
build_to_subs(placeholder, 'name')
end
def build_email_subs
placeholder = MailCannon.config['default_email_placeholder'] || '%email%'
build_to_subs(placeholder, 'email')
end
def build_unique_args
unique_args = {}
if MailCannon.config['add_envelope_id_to_unique_args']
unique_args.merge!({'envelope_id'=>self.id})
end
if MailCannon.config['add_envelope_bag_id_to_unique_args'] && self.envelope_bag
unique_args.merge!({'envelope_bag_id'=>self.envelope_bag.id})
end
unique_args
end
def build_xsmtpapi(recipients,subs)
xsmtpapi = self.xsmtpapi || {}
recipients.symbolize_keys!
to = extract_values(recipients[:to],:email)
xsmtpapi.merge!({'to' => to}) if to
xsmtpapi = merge_subs_hash(xsmtpapi,subs)
xsmtpapi = merge_subs_hash(xsmtpapi,build_name_subs)
xsmtpapi = merge_subs_hash(xsmtpapi,build_email_subs)
xsmtpapi.merge!({'unique_args' => build_unique_args })
return xsmtpapi
end
def extract_values(values,key)
extract=[]
values.each do |h|
h.symbolize_keys!
extract.push h[key]
end
extract
end
def merge_subs_hash(xsmtpapi,subs)
if subs!=nil && subs.is_a?(Hash)
xsmtpapi.deep_merge(subs)
else
xsmtpapi
end
end
def validate_xsmtpapi!
return true
if self.to.size>1
if xsmtpapi['sub']
xsmtpapi['sub'].each do |sub|
raise 'sub[Array] must match to[Array] size!' unless sub.size==xsmtpapi['to'].size
end
end
end
=begin
schema = {
"type" => "object",
"required" => ["to"],
"properties" => {
"to" => {"type" => "array", "default" => [self.to.first]}
}
}
JSON::Validator.validate!(schema, self.xsmtpapi)
=end
end
def send_multiple_emails
prepare_xsmtpapi!
api_client.mail.send(
:to => self.from,
:subject => self.subject,
:text => self.mail.text,
:html => self.mail.html,
:from => self.from,
:fromname => self.from_name,
:bcc => self.bcc,
:replyto => self.reply_to,
:"x-smtpapi" => self.xsmtpapi.to_json
)
end
def successfully_sent?(response)
response['message'] == 'success'
end
end