Skip to content

Instantly share code, notes, and snippets.

@hadees
Last active August 29, 2015 14:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hadees/bbfda3e2002e57f340bc to your computer and use it in GitHub Desktop.
Save hadees/bbfda3e2002e57f340bc to your computer and use it in GitHub Desktop.
Better way to create the crazy email Mailgun wants you to send for batch emails through SMTP.
ActionMailer::Base.register_interceptor(MailgunBatch)
class MailgunBatch
# This is where the magic happens
def self.delivering_email(message)
if batch?(message)
add_recipient_variables(message)
end
end
# Have either of the batch headers been set?
def self.batch?(message)
message.header_fields.any? { |header_field| header_field.name.to_s.starts_with?('X-Mailgun-Batch') }
end
def self.add_recipient_variables(message)
# Building the individual recipient email
recipient_message = Mail.new(message)
recipient_message.to = '%recipient%'
recipient_variables = retrive_recipient_variables(recipient_message)
recipient_variables.reverse_merge! extract_to_addresses(message)
# Mail gun headers should only be on the main message
remove_headers_starting_with!(recipient_message, 'X-Mailgun')
message.body = nil # Clearing the body so we can build the new message
message.content_type = 'multipart/mailgun-variables' # Setting a special content type
# The recipient variables hash is converted to base64 encoded json then added to the message
message.add_part Mail::Part.new(content_type: 'application/json', content_transfer_encoding: 'base64', body: Base64.encode64(recipient_variables.to_json))
#Removing the batch headers after already addeding the encoded json
remove_headers_starting_with!(message, 'X-Mailgun-Batch')
# Adding the customized message with headers
message.add_part Mail::Part.new(content_type: 'message/rfc822', body: recipient_message.encoded)
end
# Takes headers that are either json or hashes and merges them together into one hash
def self.retrive_recipient_variables(message)
message.header_fields.each_with_object({}) do |field, h|
if field.name === 'X-Mailgun-Batch-Variables'
case field.value
when Hash then h.merge! field.value
when String then h.merge! JSON.parse(field.value)
end
end
end
end
# Pulls out the to addresses and adds them as empty recipient variables
# Enable using headers['X-Mailgun-Batch-Send'] = true
def self.extract_to_addresses(message)
message.to.each.each_with_object({}) do |address, h|
h[address] = {}
end
end
# Delete any headers that start with the given string
def self.remove_headers_starting_with!(message, str)
message.header.fields.delete_if { |header| header.name.to_s.starts_with?(str) }
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment