snails 0.4.2 → 0.5.0

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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/lib/snails/mailer.rb +127 -26
  3. data/snails.gemspec +1 -1
  4. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b9ee5f0ad2cdda5a366dfc31d197b29948e63b7d24be394e8a6b779ea0f11bc2
4
- data.tar.gz: 6f838a808f32036b57ab67ae24e26e2cae9442af0b086aa7d524d78d94ae5df2
3
+ metadata.gz: 06b4aea8ffe430adc00748ea5f48ace43cd79fdf26cebb02da08b31ea88765ac
4
+ data.tar.gz: 9c856ce125123fe7d3423b362ea948dba6b41038490dea3b0158084ecf2d6b35
5
5
  SHA512:
6
- metadata.gz: f4b100c320293b3f66944182bde37c32567795838358c09bad18cf94ec34ce91932d5e923245faa29ffb63350d2876b60c97c1e378aa6b75e459353f057c2f5e
7
- data.tar.gz: 4a120754c9dad45639f27e1b23ed44c84054440937ac1bfaccce508263090b84feb1175388867b12ded067b4ac936615e39d3490bdc0fe69b8e9447e7f7bb737
6
+ metadata.gz: ddff99a5c53edfb7a897b2c3015cbf883e1db67124df89d5c9cbe7058798cdc644f3954d575b6381ef017c458fa908df40bb14e825bb2ce174810f26844c4e24
7
+ data.tar.gz: ed3065454f356aaf82e325ae2e46bccafc8c93f39de9ccf99f7079b43bfab913231f4abfd355e437444e7d9d7268532e072c9b8447c782cd09f7079227fa83a1
data/lib/snails/mailer.rb CHANGED
@@ -12,32 +12,40 @@ module Snails
12
12
 
13
13
  @queue = :emails
14
14
 
15
- def initialize(opts)
16
- mail_config = (opts[:smtp] || opts[:mail]) or raise ":smtp options missing"
15
+ # class Bounce < StandardError; end
16
+ # class SoftBounce < Bounce; end
17
+ # class HardBounce < Bounce; end
18
+
19
+ def self.backends
20
+ {
21
+ 'test_backend' => 'Snails::Mailer::TestBackend',
22
+ 'smtp' => 'Snails::Mailer::TuktukBackend',
23
+ 'mailgun' => 'Snails::Mailer::MailgunBackend'
24
+ }
25
+ end
17
26
 
18
- if key = mail_config.dig(:dkim, :private_key) and File.exist?(key)
19
- mail_config[:dkim][:private_key] = IO.read(key)
20
- elsif mail_config[:dkim]
21
- puts "Private key for DKIM not found! Disabling..."
22
- mail_config.delete(:dkim)
23
- end
27
+ def self.init_backend(backend_name, opts = {})
28
+ backend_name = backend_name.presence || 'test_backend'
29
+ backends[backend_name].constantize.new(opts)
30
+ end
24
31
 
25
- Tuktuk.options = mail_config
26
- @debug = mail_config[:debug]
32
+ def initialize(opts)
27
33
  @from_email = opts[:from] or raise ":from required"
28
34
  @base_subject = opts[:base_subject] || ''
29
35
  @views = opts[:views] || Snails.root.join('lib', 'views')
30
36
  @logfile = opts[:logfile] # || Snails.root.join('log', 'mailer.log')
37
+
38
+ @backend = self.class.init_backend(opts[:backend_name], opts[:backend_options])
31
39
  end
32
40
 
33
41
  def email(name, &block)
34
42
  define_singleton_method(name) do |*args|
35
- instance_exec(*args, &block)
43
+ instance_exec(*args, &block)
36
44
  end
37
45
  end
38
46
 
39
47
  def helpers(&block)
40
- instance_eval(&block)
48
+ instance_eval(&block)
41
49
  end
42
50
 
43
51
  def perform(method, *args)
@@ -81,50 +89,143 @@ A <%= @exception.class %> occurred in <%= @url %>:
81
89
 
82
90
  private
83
91
 
84
- def render(view)
85
- template = File.read(File.join(@views, "#{view}.erb"))
92
+ def render(view_path, layout_path = nil)
93
+ view = File.read(File.join(@views, "#{view_path}.erb"))
94
+ if layout_path
95
+ layout = File.read(File.join(@views, "#{layout_path}.erb"))
96
+ render_erb(layout) { render_erb(view) }
97
+ else
98
+ render_erb(view)
99
+ end
100
+ end
101
+
102
+ def render_erb(template)
86
103
  ERB.new(template).result(binding)
87
104
  end
88
105
 
89
106
  def partial(name)
90
107
  partial_name = name.to_s["/"] ? name.to_s.reverse.sub("/", "_/").reverse : "_#{name}"
91
- render partial_name
108
+ render(partial_name)
92
109
  end
93
110
 
94
111
  def logger
95
112
  @logger ||= @logfile ? Logger.new(@logfile) : Snails.logger
96
113
  end
97
114
 
98
- def send_email(from: nil, to:, subject:, body: nil, template: nil, html_body: nil, html_template: nil, message_id: nil, return_path: nil, list_unsubscribe: nil)
115
+ def send_email(from: @from_email, to:, subject:, body: nil, template: nil, layout: nil, html_body: nil, html_template: nil, html_layout: nil, message_id: nil, attachments: nil, return_path: nil, list_unsubscribe: nil)
99
116
  raise "No recipient given for mail: #{subject}!" if to.blank?
100
117
 
101
118
  message = {
102
119
  to: to,
103
- from: from || @from_email,
104
- subject: @base_subject + subject
120
+ from: from,
121
+ subject: @base_subject + subject
105
122
  }
106
123
 
124
+ raise "Blank from" if message[:from].blank?
125
+ raise "Blank to" if message[:to].blank?
126
+
107
127
  if body or template
108
- message[:body] = template ? render(template) : body
128
+ message[:body] = template ? render(template, layout) : body
109
129
  end
110
130
 
111
131
  if html_body or html_template
112
- message[:html_body] = html_template ? render(html_template) : html_body
132
+ message[:html_body] = html_template ? render(html_template, html_layout) : html_body
113
133
  end
114
134
 
135
+ message[:attachments] = attachments if attachments
115
136
  message[:message_id] = message_id if message_id
116
137
  message[:return_path] = return_path if return_path
117
138
  message[:list_unsubscribe] = list_unsubscribe if list_unsubscribe
118
139
 
119
- logger.info "[#{to}] Delivering: #{subject}"
120
- debug = @debug.nil? ? !Snails.env.production? : @debug # if debug isn't set, determine based on env
121
- resp, email = Tuktuk.deliver(message, debug: debug)
140
+ logger.info "[#{to}] Delivering: #{subject}"
141
+ @backend.deliver(message)
142
+ end
143
+
144
+ alias_method :deliver, :send_email
145
+
146
+ class Backend
147
+ def deliver(email, options = {})
148
+ raise "Please redefine in subclass"
149
+ end
150
+
151
+ def deliver_many(emails, options = {})
152
+ emails.map { |e| deliver(e, options) }
153
+ end
154
+ end
155
+
156
+ class TestBackend < Backend
157
+ def initialize(opts = {})
158
+ end
159
+
160
+ def deliver(email, options = {})
161
+ puts "Deliverying single: #{email[:to]}"
162
+ end
163
+
164
+ def deliver_many(emails, options = {})
165
+ puts "Deliverying many: #{emails.count}"
166
+ end
167
+ end
168
+
169
+ class TuktukBackend < Backend
170
+ def initialize(config = {})
171
+ @debug = config[:debug]
172
+
173
+ puts "-- #{config.inspect}"
174
+
175
+ if key = config.dig(:dkim, :private_key) and File.exist?(key)
176
+ config[:dkim][:private_key] = IO.read(key)
177
+ elsif config[:dkim]
178
+ puts "Private key for DKIM not found! Disabling..."
179
+ config.delete(:dkim)
180
+ end
181
+
182
+ Tuktuk.options = config
183
+ end
184
+
185
+ def deliver(email, options = {})
186
+ debug = @debug.nil? ? !Snails.env.production? : @debug # if debug isn't set, determine based on env
187
+ resp, email = Tuktuk.deliver(email, debug: debug)
188
+
189
+ if resp.is_a?(Tuktuk::Bounce)
190
+ logger.info "[#{to}] Email bounced! [#{resp.code}] #{resp.message}"
191
+ end
192
+
193
+ return resp, email
194
+ end
195
+
196
+ def deliver_many(emails, options = {})
197
+ Tuktuk.deliver_many(emails, options)
198
+ end
199
+ end
200
+
201
+ class MailgunBackend < Backend
202
+
203
+ def initialize(api_key:, domain_name:)
204
+ @key = api_key
205
+ @url = "https://api.mailgun.net/v3/#{domain_name}/messages"
206
+ end
207
+
208
+ def deliver(email, options = {})
209
+ raise "No body!" if email[:body].nil?
210
+
211
+ data = {
212
+ from: email[:from],
213
+ to: email[:to],
214
+ subject: email[:subject],
215
+ }
216
+
217
+ data[:text] = email[:body] if email[:body]
218
+ data[:html] = email[:html_body] if email[:html_body]
219
+
220
+ if data[:text].blank? && data[:html].blank?
221
+ raise ArgumentError, "Either text or html required"
222
+ end
122
223
 
123
- if resp.is_a?(Tuktuk::Bounce)
124
- logger.info "[#{to}] Email bounced! [#{resp.code}] #{resp.message}"
224
+ opts = { username: 'api', password: @key }
225
+ resp = Dagger.post(@url, data, opts)
226
+ resp.ok? ? [resp.data, data[:to]] : nil
125
227
  end
126
228
 
127
- return resp, email
128
229
  end
129
230
 
130
231
  end
data/snails.gemspec CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "snails"
6
- s.version = '0.4.2'
6
+ s.version = '0.5.0'
7
7
  s.platform = Gem::Platform::RUBY
8
8
  s.authors = ['Tomás Pollak']
9
9
  s.email = ['tomas@forkhq.com']
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: snails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tomás Pollak
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-05 00:00:00.000000000 Z
11
+ date: 2022-10-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler