hubspot-mailer 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/hubspot-mailer.rb +8 -0
- data/lib/hubspot/mailer.rb +179 -0
- data/lib/hubspot/mailer/delivery.rb +17 -0
- data/lib/hubspot/mailer/exceptions.rb +21 -0
- data/lib/hubspot/mailer/hubspot_preview_interceptor.rb +48 -0
- data/lib/hubspot/mailer/message.rb +10 -0
- metadata +98 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 84be921dddd2279d24cd15c9a4f0a182bba57e58
|
4
|
+
data.tar.gz: 27960c36c5cccfeb6a0a02835c3af5ef4fa3c4c6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c825a4740b1758e896823f147d7298b453163247753d863049604d9555cfb53b62f9e9679e6efaa0aa6e7bbf21e2dd55a80b460d50a0002ac33265874c49dfab
|
7
|
+
data.tar.gz: f3f538cdc9547886dec6ec50b6fb4a8ed77fe0ff6bc7dfc397112e0f0462e3f7b348b7e75a2a73f162afd1536f4ce2f970d3fed65dcb21866ed830a5e2857562
|
@@ -0,0 +1,179 @@
|
|
1
|
+
module Hubspot
|
2
|
+
class Mailer < ActionMailer::Base
|
3
|
+
abstract!
|
4
|
+
|
5
|
+
register_preview_interceptor(HubspotPreviewInterceptor)
|
6
|
+
|
7
|
+
# Register our own delivery method
|
8
|
+
add_delivery_method :hubspot, Delivery
|
9
|
+
|
10
|
+
# Set hubspot as a default delivery method
|
11
|
+
self.delivery_method = :hubspot
|
12
|
+
|
13
|
+
# Set credentials
|
14
|
+
# self.hubspot_settings = { :hapikey => ENV.fetch("HUBSPOT_API_KEY") }
|
15
|
+
|
16
|
+
self.default_params = {}.freeze
|
17
|
+
|
18
|
+
SINGLE_SEND_PATH = '/email/public/v1/singleEmail/send'.freeze
|
19
|
+
|
20
|
+
class << self
|
21
|
+
# Wraps an email delivery inside of <tt>ActiveSupport::Notifications</tt> instrumentation.
|
22
|
+
#
|
23
|
+
# This method is actually called by the <tt>Mail::Message</tt> object itself
|
24
|
+
# through a callback when you call <tt>:deliver</tt> on the <tt>Mail::Message</tt>,
|
25
|
+
# calling +deliver_mail+ directly and passing a <tt>Mail::Message</tt> will do
|
26
|
+
# nothing except tell the logger you sent the email.
|
27
|
+
def deliver_mail(mail) #:nodoc:
|
28
|
+
ActiveSupport::Notifications.instrument("deliver.hubspot_mailer") do |payload|
|
29
|
+
set_payload_for_mail(payload, mail)
|
30
|
+
yield # Let Mail do the delivery actions
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Perform the delivery by calling Hubspot's API
|
35
|
+
#
|
36
|
+
# Receives regular mail object that contains additional template details.
|
37
|
+
def single_send(mail)
|
38
|
+
# Format the request data
|
39
|
+
data = single_send_params(mail)
|
40
|
+
|
41
|
+
# Call the API
|
42
|
+
response = Hubspot::Connection.post_json(SINGLE_SEND_PATH, params: {}, body: data)
|
43
|
+
|
44
|
+
# Parse response and either raise or return event details
|
45
|
+
parse_response(response)
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def set_payload_for_mail(payload, mail)
|
51
|
+
payload[:mailer] = name
|
52
|
+
payload[:message_id] = mail.message_id
|
53
|
+
payload[:subject] = mail.subject
|
54
|
+
payload[:to] = mail.to
|
55
|
+
payload[:from] = mail.from if mail.from.present?
|
56
|
+
payload[:send_id] = mail.send_id if mail.send_id.present?
|
57
|
+
payload[:reply_to] = mail.reply_to if mail.reply_to.present?
|
58
|
+
payload[:cc] = mail.cc if mail.cc.present?
|
59
|
+
payload[:bcc] = mail.bcc if mail.bcc.present?
|
60
|
+
end
|
61
|
+
|
62
|
+
def single_send_params(mail)
|
63
|
+
raise MissingTemplateError, "Missing emailId parameter." unless mail.email_id.present?
|
64
|
+
raise MissingRecipientError, "Missing recipient emaul." unless mail.to.present?
|
65
|
+
|
66
|
+
data = {
|
67
|
+
emailId: mail.email_id,
|
68
|
+
message: { to: mail.to.first }
|
69
|
+
}
|
70
|
+
|
71
|
+
data[:message][:from] = mail.from.first if mail.from.present?
|
72
|
+
data[:message][:cc] = mail.cc if mail.cc.present?
|
73
|
+
data[:message][:bcc] = mail.bcc if mail.bcc.present?
|
74
|
+
data[:message][:sendId] = mail.send_id if mail.send_id.present?
|
75
|
+
|
76
|
+
if mail.reply_to.present?
|
77
|
+
if mail.reply_to.size > 1
|
78
|
+
data[:message][:replyToList] = mail.reply_to
|
79
|
+
else
|
80
|
+
data[:message][:replyTo] = mail.reply_to.first
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Copy subject from header to custom property
|
85
|
+
if mail.subject.present? and not mail.custom_properties.try(:[], :subject)
|
86
|
+
mail.custom_properties ||= {}
|
87
|
+
mail.custom_properties[:subject] = mail.subject
|
88
|
+
end
|
89
|
+
|
90
|
+
if mail.contact_properties.present?
|
91
|
+
data[:contactProperties] =
|
92
|
+
Hubspot::Utils.hash_to_properties(mail.contact_properties, :key_name => :name)
|
93
|
+
end
|
94
|
+
|
95
|
+
if mail.custom_properties.present?
|
96
|
+
data[:customProperties] =
|
97
|
+
Hubspot::Utils.hash_to_properties(mail.custom_properties, :key_name => :name)
|
98
|
+
end
|
99
|
+
|
100
|
+
data
|
101
|
+
end
|
102
|
+
|
103
|
+
def parse_response(response)
|
104
|
+
status_code = response["sendResult"]
|
105
|
+
|
106
|
+
case status_code
|
107
|
+
when "SENT", "QUEUED"
|
108
|
+
response["eventId"]
|
109
|
+
when "INVALID_TO_ADDRESS"
|
110
|
+
raise RecipientAddressError.new(response), "The TO address is invalid: #{status_code}"
|
111
|
+
when "INVALID_FROM_ADDRESS"
|
112
|
+
raise SenderAddressError.new(response), "The FROM address is invalid: #{status_code}"
|
113
|
+
when "BLOCKED_DOMAIN", "PORTAL_SUSPENDED"
|
114
|
+
raise SendingError.new(response), "Message can't be sent: #{status_code}"
|
115
|
+
when "PREVIOUSLY_BOUNCED", "PREVIOUS_SPAM"
|
116
|
+
raise DeliveryError.new(response), "Message can't be delivered: #{status_code}"
|
117
|
+
when "MISSING_CONTENT"
|
118
|
+
raise InvalidTemplateError.new(response), "The emailId is invalid, or the emailId is an email that is not set up for Single Send: #{status_code}"
|
119
|
+
else
|
120
|
+
raise UnknownResponseError.new(response), "Unrecognized status code: #{status_code}"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
attr_internal :message
|
126
|
+
|
127
|
+
def initialize
|
128
|
+
super()
|
129
|
+
@_mail_was_called = false
|
130
|
+
@_message = Message.new
|
131
|
+
end
|
132
|
+
|
133
|
+
def process(method_name, *args) #:nodoc:
|
134
|
+
payload = {
|
135
|
+
mailer: self.class.name,
|
136
|
+
action: method_name,
|
137
|
+
args: args
|
138
|
+
}
|
139
|
+
|
140
|
+
ActiveSupport::Notifications.instrument("process.hubspot_mailer", payload) do
|
141
|
+
super
|
142
|
+
@_message = ActionMailer::Base::NullMail.new unless @_mail_was_called
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def mail(headers = {}, &block)
|
147
|
+
return message if @_mail_was_called && headers.blank? && !block
|
148
|
+
|
149
|
+
headers = apply_defaults(headers)
|
150
|
+
|
151
|
+
# Set configure delivery behavior
|
152
|
+
wrap_delivery_behavior!(headers[:delivery_method], headers[:delivery_method_options])
|
153
|
+
|
154
|
+
# Hubspot-specific attributes, e.g. emailId (template ID)
|
155
|
+
assign_attributes_to_message(message, headers)
|
156
|
+
|
157
|
+
# Default headers
|
158
|
+
assign_headers_to_message(message, headers)
|
159
|
+
|
160
|
+
@_mail_was_called = true
|
161
|
+
|
162
|
+
message
|
163
|
+
end
|
164
|
+
|
165
|
+
private
|
166
|
+
|
167
|
+
def assign_attributes_to_message(message, headers)
|
168
|
+
hubspot_props = %i[email_id send_id contact_properties custom_properties]
|
169
|
+
|
170
|
+
headers.slice(*hubspot_props).each { |k, v| message.try("#{k}=", v) }
|
171
|
+
headers.except!(*hubspot_props)
|
172
|
+
end
|
173
|
+
|
174
|
+
def assign_headers_to_message(message, headers)
|
175
|
+
headers.except(:parts_order, :content_type, :body, :template_name,
|
176
|
+
:template_path, :delivery_method, :delivery_method_options).each { |k, v| message[k] = v }
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Hubspot
|
2
|
+
class Mailer < ActionMailer::Base
|
3
|
+
class Delivery
|
4
|
+
attr_accessor :settings
|
5
|
+
|
6
|
+
DEFAULTS = {}
|
7
|
+
|
8
|
+
def initialize(values)
|
9
|
+
self.settings = DEFAULTS.merge(values)
|
10
|
+
end
|
11
|
+
|
12
|
+
def deliver!(mail)
|
13
|
+
Hubspot::Mailer.single_send(mail)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Hubspot
|
2
|
+
class Mailer < ActionMailer::Base
|
3
|
+
class MissingTemplateError < StandardError; end
|
4
|
+
class MissingRecipientError < StandardError; end
|
5
|
+
|
6
|
+
class RequestError < StandardError
|
7
|
+
attr_reader :response
|
8
|
+
|
9
|
+
def initialize(response = nil)
|
10
|
+
@response = response
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class RecipientAddressError < RequestError; end
|
15
|
+
class SenderAddressError < RequestError; end
|
16
|
+
class SendingError < RequestError; end
|
17
|
+
class DeliveryError < RequestError; end
|
18
|
+
class InvalidTemplateError < RequestError; end
|
19
|
+
class UnknownResponseError < RequestError; end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Hubspot
|
2
|
+
class Mailer < ActionMailer::Base
|
3
|
+
class HubspotPreviewInterceptor
|
4
|
+
class << self
|
5
|
+
def previewing_email(message)
|
6
|
+
new(message).transform!
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :message
|
11
|
+
|
12
|
+
def initialize(message)
|
13
|
+
@message = message
|
14
|
+
end
|
15
|
+
|
16
|
+
def transform!
|
17
|
+
build_preview
|
18
|
+
message
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def build_preview
|
24
|
+
html_part = "<b>Email ID (template)</b>: #{message.email_id}<br/><br/>"
|
25
|
+
|
26
|
+
html_part << list_properties("Contact Properties (use via {{contact.propertyname}})", message.contact_properties)
|
27
|
+
html_part << list_properties("Custom Properties (use via {{custom.property_name}})", message.custom_properties)
|
28
|
+
|
29
|
+
message.html_part = html_part
|
30
|
+
|
31
|
+
message
|
32
|
+
end
|
33
|
+
|
34
|
+
def list_properties(label, list)
|
35
|
+
buffer = ""
|
36
|
+
return buffer unless list.present?
|
37
|
+
|
38
|
+
buffer << "<b>#{label}</b>:<ul>"
|
39
|
+
|
40
|
+
list.each_pair do |property, value|
|
41
|
+
buffer << "<li><i>#{property}</i>: #{value}</li>"
|
42
|
+
end
|
43
|
+
|
44
|
+
buffer << "</ul>"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
metadata
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hubspot-mailer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- heaven
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-12-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: hubspot-ruby
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.4'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.4'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: actionmailer
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '5.1'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '5.1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.0'
|
55
|
+
description: Create beautiful transactional emails right within HubSpot using the
|
56
|
+
email editor with all the benefits of smart content, personalization and templates
|
57
|
+
- just like regular HubSpot emails. Create beautiful transactional emails right
|
58
|
+
within HubSpot using the email editor with all the benefits of smart content, personalization
|
59
|
+
and templates - just like regular HubSpot emails. Create beautiful transactional
|
60
|
+
emails right within HubSpot using the email editor with all the benefits of smart
|
61
|
+
content, personalization and templates - just like regular HubSpot emails.
|
62
|
+
email:
|
63
|
+
- hello@codeart.us
|
64
|
+
executables: []
|
65
|
+
extensions: []
|
66
|
+
extra_rdoc_files: []
|
67
|
+
files:
|
68
|
+
- lib/hubspot-mailer.rb
|
69
|
+
- lib/hubspot/mailer.rb
|
70
|
+
- lib/hubspot/mailer/delivery.rb
|
71
|
+
- lib/hubspot/mailer/exceptions.rb
|
72
|
+
- lib/hubspot/mailer/hubspot_preview_interceptor.rb
|
73
|
+
- lib/hubspot/mailer/message.rb
|
74
|
+
homepage: https://github.com/heaven/hubspot-mailer
|
75
|
+
licenses:
|
76
|
+
- MIT
|
77
|
+
metadata: {}
|
78
|
+
post_install_message:
|
79
|
+
rdoc_options: []
|
80
|
+
require_paths:
|
81
|
+
- lib
|
82
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
requirements: []
|
93
|
+
rubyforge_project:
|
94
|
+
rubygems_version: 2.6.14
|
95
|
+
signing_key:
|
96
|
+
specification_version: 3
|
97
|
+
summary: HubSpot Single Send API SDK for use with Ruby on Rails
|
98
|
+
test_files: []
|