hubspot-mailer 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,8 @@
1
+ require 'action_mailer'
2
+ require 'hubspot-ruby'
3
+ require 'hubspot/mailer/delivery'
4
+ require 'hubspot/mailer/exceptions'
5
+ require 'hubspot/mailer/hubspot_preview_interceptor'
6
+ require 'hubspot/mailer/message'
7
+ require 'hubspot/mailer'
8
+
@@ -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
@@ -0,0 +1,10 @@
1
+ module Hubspot
2
+ class Mailer < ActionMailer::Base
3
+ class Message < Mail::Message
4
+ attr_accessor :email_id
5
+ attr_accessor :send_id
6
+ attr_accessor :contact_properties
7
+ attr_accessor :custom_properties
8
+ end
9
+ end
10
+ 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: []