lotus-mailer 0.0.0 → 0.1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +361 -10
- data/lib/lotus-mailer.rb +1 -0
- data/lib/lotus/mailer.rb +311 -2
- data/lib/lotus/mailer/configuration.rb +307 -0
- data/lib/lotus/mailer/dsl.rb +288 -0
- data/lib/lotus/mailer/rendering/template_name.rb +52 -0
- data/lib/lotus/mailer/rendering/templates_finder.rb +133 -0
- data/lib/lotus/mailer/template.rb +40 -0
- data/lib/lotus/mailer/version.rb +2 -1
- data/lotus-mailer.gemspec +4 -3
- metadata +47 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 010f5e6d0f8485fe6d90af54b84181fceb6d639e
|
4
|
+
data.tar.gz: be1bbd47898677b7f6a6179377d86c0457944899
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 71838f83857156392f4cd227676ac025a3dca6ba8021b0c05aa5c03b4e00ffa0f87eb5df58c7d1333d9a21520237f9e9dcb2c9294035a3992966e2381285eba3
|
7
|
+
data.tar.gz: 9eefa471b50fa187498e31a58eb484dcded69b0f43f540655f42a2966c055cd5d165a4e895aa43b6e529e2ffad66d5fab5eea4f0bd38493277d81a9056988339
|
data/CHANGELOG.md
CHANGED
@@ -1,2 +1,10 @@
|
|
1
1
|
# Lotus::Router
|
2
2
|
Mail for Ruby applications
|
3
|
+
|
4
|
+
## v0.1.0 - 2015-09-30
|
5
|
+
### Added
|
6
|
+
- [Ines Coelho & Rosa Faria & Luca Guidi] Email delivery
|
7
|
+
- [Ines Coelho & Rosa Faria & Luca Guidi] Attachments
|
8
|
+
- [Ines Coelho & Rosa Faria & Luca Guidi] Multipart rendering
|
9
|
+
- [Ines Coelho & Rosa Faria & Luca Guidi] Configuration
|
10
|
+
- [Ines Coelho & Rosa Faria & Luca Guidi] Official support for Ruby 2.0
|
data/README.md
CHANGED
@@ -42,24 +42,375 @@ Or install it yourself as:
|
|
42
42
|
|
43
43
|
## Usage
|
44
44
|
|
45
|
-
|
45
|
+
### Conventions
|
46
46
|
|
47
|
-
|
47
|
+
* Templates are searched under `Lotus::Mailer.configuration.root`, set this value according to your app structure (eg. `"app/templates"`).
|
48
|
+
* A mailer will look for a template with a file name that is composed by its full class name (eg. `"articles/index"`).
|
49
|
+
* A template must have two concatenated extensions: one for the format and one for the engine (eg. `".html.erb"`).
|
50
|
+
* The framework must be loaded before rendering the first time: `Lotus::Mailer.load!`.
|
48
51
|
|
49
|
-
|
52
|
+
### Mailers
|
50
53
|
|
51
|
-
|
54
|
+
A simple mailer looks like this:
|
52
55
|
|
53
|
-
|
56
|
+
```ruby
|
57
|
+
require lotus/mailer
|
54
58
|
|
55
|
-
|
59
|
+
class InvoiceMailer
|
60
|
+
include Lotus::Mailer
|
61
|
+
end
|
62
|
+
```
|
56
63
|
|
57
|
-
|
64
|
+
A mailer with `.to` and `.from` addresses and mailer delivery:
|
58
65
|
|
59
|
-
|
66
|
+
```ruby
|
67
|
+
require lotus/mailer
|
60
68
|
|
61
|
-
|
69
|
+
Lotus::Mailer.configuration do
|
70
|
+
delivery_method :smtp,
|
71
|
+
address: "smtp.gmail.com",
|
72
|
+
port: 587,
|
73
|
+
domain: "example.com",
|
74
|
+
user_name: ENV['SMTP_USERNAME'],
|
75
|
+
password: ENV['SMTP_PASSWORD'],
|
76
|
+
authentication: "plain",
|
77
|
+
enable_starttls_auto: true
|
78
|
+
end.load!
|
62
79
|
|
63
|
-
|
80
|
+
class WelcomeMailer
|
81
|
+
include Lotus::Mailer
|
82
|
+
|
83
|
+
from 'noreply@sender.com'
|
84
|
+
to 'noreply@recipient.com'
|
85
|
+
subject 'Welcome'
|
86
|
+
end
|
87
|
+
|
88
|
+
WelcomeMailer.deliver
|
89
|
+
```
|
90
|
+
|
91
|
+
### Locals
|
92
|
+
|
93
|
+
The set of objects passed in the `deliver` call are called `locals` and are avaliable inside the mailer and the template.
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
require lotus/mailer
|
97
|
+
|
98
|
+
User = Struct.new(:name, :username)
|
99
|
+
user = User.new('Luca', 'jodosha')
|
100
|
+
|
101
|
+
Lotus::Mailer.load!
|
102
|
+
|
103
|
+
class WelcomeMailer
|
104
|
+
include Lotus::Mailer
|
105
|
+
|
106
|
+
from 'noreply@sender.com'
|
107
|
+
subject 'Welcome'
|
108
|
+
to :recipient
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def recipient
|
113
|
+
user.email
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
InvoiceMailer.deliver(user: luca)
|
118
|
+
```
|
119
|
+
|
120
|
+
The corresponding `erb` file:
|
121
|
+
|
122
|
+
```erb
|
123
|
+
Hello <%= user.name %>!
|
124
|
+
```
|
125
|
+
|
126
|
+
### Scope
|
127
|
+
|
128
|
+
All public methods defined in the mailer are accessible from the template:
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
require lotus/mailer
|
132
|
+
|
133
|
+
class WelcomeMailer
|
134
|
+
include Lotus::Mailer
|
135
|
+
|
136
|
+
from 'noreply@sender.com'
|
137
|
+
to 'noreply@recipient.com'
|
138
|
+
subject 'Welcome'
|
139
|
+
|
140
|
+
def greeting
|
141
|
+
'Ahoy'
|
142
|
+
end
|
143
|
+
end
|
144
|
+
```
|
145
|
+
|
146
|
+
```erb
|
147
|
+
<h2><%= greeting %></h2>
|
148
|
+
```
|
149
|
+
|
150
|
+
### Template
|
151
|
+
|
152
|
+
The template file must be located under the relevant `root` and must match the inflected snake case of the mailer class name.
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
# Given this root
|
156
|
+
Lotus::Mailer.configuration.root # => #<Pathname:app/templates>
|
157
|
+
|
158
|
+
# For InvoiceMailer, it looks for:
|
159
|
+
# * app/templates/invoice_mailer.html.erb
|
160
|
+
# * app/templates/invoice_mailer.txt.erb
|
161
|
+
```
|
162
|
+
|
163
|
+
If we want to specify a different template, we can do:
|
164
|
+
|
165
|
+
```ruby
|
166
|
+
class InvoiceMailer
|
167
|
+
include Lotus::Mailer
|
168
|
+
|
169
|
+
template 'invoice'
|
170
|
+
end
|
171
|
+
|
172
|
+
# It will look for:
|
173
|
+
# * app/templates/invoice.html.erb
|
174
|
+
# * app/templates/invoice.txt.erb
|
175
|
+
```
|
176
|
+
|
177
|
+
### Engines
|
178
|
+
|
179
|
+
The builtin rendering engine is [ERb](http://en.wikipedia.org/wiki/ERuby).
|
64
180
|
|
181
|
+
This is the list of the supported engines.
|
182
|
+
They are listed in order of **higher precedence**, for a given extension.
|
183
|
+
For instance, if [ERubis](http://www.kuwata-lab.com/erubis/) is loaded, it will be preferred over ERb to render `.erb` templates.
|
65
184
|
|
185
|
+
<table>
|
186
|
+
<tr>
|
187
|
+
<th>Engine</th>
|
188
|
+
<th>Extensions</th>
|
189
|
+
</tr>
|
190
|
+
<tr>
|
191
|
+
<td>Erubis</td>
|
192
|
+
<td>erb, rhtml, erubis</td>
|
193
|
+
</tr>
|
194
|
+
<tr>
|
195
|
+
<td>ERb</td>
|
196
|
+
<td>erb, rhtml</td>
|
197
|
+
</tr>
|
198
|
+
<tr>
|
199
|
+
<td>Redcarpet</td>
|
200
|
+
<td>markdown, mkd, md</td>
|
201
|
+
</tr>
|
202
|
+
<tr>
|
203
|
+
<td>RDiscount</td>
|
204
|
+
<td>markdown, mkd, md</td>
|
205
|
+
</tr>
|
206
|
+
<tr>
|
207
|
+
<td>Kramdown</td>
|
208
|
+
<td>markdown, mkd, md</td>
|
209
|
+
</tr>
|
210
|
+
<tr>
|
211
|
+
<td>Maruku</td>
|
212
|
+
<td>markdown, mkd, md</td>
|
213
|
+
</tr>
|
214
|
+
<tr>
|
215
|
+
<td>BlueCloth</td>
|
216
|
+
<td>markdown, mkd, md</td>
|
217
|
+
</tr>
|
218
|
+
<tr>
|
219
|
+
<td>Asciidoctor</td>
|
220
|
+
<td>ad, adoc, asciidoc</td>
|
221
|
+
</tr>
|
222
|
+
<tr>
|
223
|
+
<td>Builder</td>
|
224
|
+
<td>builder</td>
|
225
|
+
</tr>
|
226
|
+
<tr>
|
227
|
+
<td>CSV</td>
|
228
|
+
<td>rcsv</td>
|
229
|
+
</tr>
|
230
|
+
<tr>
|
231
|
+
<td>CoffeeScript</td>
|
232
|
+
<td>coffee</td>
|
233
|
+
</tr>
|
234
|
+
<tr>
|
235
|
+
<td>WikiCloth</td>
|
236
|
+
<td>wiki, mediawiki, mw</td>
|
237
|
+
</tr>
|
238
|
+
<tr>
|
239
|
+
<td>Creole</td>
|
240
|
+
<td>wiki, creole</td>
|
241
|
+
</tr>
|
242
|
+
<tr>
|
243
|
+
<td>Etanni</td>
|
244
|
+
<td>etn, etanni</td>
|
245
|
+
</tr>
|
246
|
+
<tr>
|
247
|
+
<td>Haml</td>
|
248
|
+
<td>haml</td>
|
249
|
+
</tr>
|
250
|
+
<tr>
|
251
|
+
<td>Less</td>
|
252
|
+
<td>less</td>
|
253
|
+
</tr>
|
254
|
+
<tr>
|
255
|
+
<td>Liquid</td>
|
256
|
+
<td>liquid</td>
|
257
|
+
</tr>
|
258
|
+
<tr>
|
259
|
+
<td>Markaby</td>
|
260
|
+
<td>mab</td>
|
261
|
+
</tr>
|
262
|
+
<tr>
|
263
|
+
<td>Nokogiri</td>
|
264
|
+
<td>nokogiri</td>
|
265
|
+
</tr>
|
266
|
+
<tr>
|
267
|
+
<td>Plain</td>
|
268
|
+
<td>html</td>
|
269
|
+
</tr>
|
270
|
+
<tr>
|
271
|
+
<td>RDoc</td>
|
272
|
+
<td>rdoc</td>
|
273
|
+
</tr>
|
274
|
+
<tr>
|
275
|
+
<td>Radius</td>
|
276
|
+
<td>radius</td>
|
277
|
+
</tr>
|
278
|
+
<tr>
|
279
|
+
<td>RedCloth</td>
|
280
|
+
<td>textile</td>
|
281
|
+
</tr>
|
282
|
+
<tr>
|
283
|
+
<td>Sass</td>
|
284
|
+
<td>sass</td>
|
285
|
+
</tr>
|
286
|
+
<tr>
|
287
|
+
<td>Scss</td>
|
288
|
+
<td>scss</td>
|
289
|
+
</tr>
|
290
|
+
<tr>
|
291
|
+
<td>Slim</td>
|
292
|
+
<td>slim</td>
|
293
|
+
</tr>
|
294
|
+
<tr>
|
295
|
+
<td>String</td>
|
296
|
+
<td>str</td>
|
297
|
+
</tr>
|
298
|
+
<tr>
|
299
|
+
<td>Yajl</td>
|
300
|
+
<td>yajl</td>
|
301
|
+
</tr>
|
302
|
+
</table>
|
303
|
+
|
304
|
+
|
305
|
+
### Configuration
|
306
|
+
|
307
|
+
__Lotus::Mailer__ can be configured with a DSL that determines its behavior.
|
308
|
+
It supports a few options:
|
309
|
+
|
310
|
+
```ruby
|
311
|
+
require 'lotus/mailer'
|
312
|
+
|
313
|
+
Lotus::Maler.configure do
|
314
|
+
# Set the root path where to search for templates
|
315
|
+
# Argument: String, Pathname, #to_pathname, defaults to the current directory
|
316
|
+
#
|
317
|
+
root '/path/to/root'
|
318
|
+
|
319
|
+
# Set the default charset for emails
|
320
|
+
# Argument: String, defaults to "UTF-8"
|
321
|
+
#
|
322
|
+
default_charset 'iso-8859'
|
323
|
+
|
324
|
+
# Set the delivery method
|
325
|
+
# Argument: Symbol
|
326
|
+
# Argument: Hash, optional configurations
|
327
|
+
delivery_method :stmp
|
328
|
+
```
|
329
|
+
|
330
|
+
### Attachments
|
331
|
+
|
332
|
+
Attachments can be added with the following API:
|
333
|
+
|
334
|
+
```ruby
|
335
|
+
class InvoiceMailer
|
336
|
+
include Lotus::Mailer
|
337
|
+
# ...
|
338
|
+
|
339
|
+
def prepare
|
340
|
+
mail.attachments['invoice.pdf'] = '/path/to/invoice.pdf'
|
341
|
+
# or
|
342
|
+
mail.attachments['invoice.pdf'] = File.read('/path/to/invoice.pdf')
|
343
|
+
end
|
344
|
+
end
|
345
|
+
```
|
346
|
+
|
347
|
+
### Delivery Method
|
348
|
+
|
349
|
+
The global delivery method is defined through the __Lotus::Mailer__ configuration, as:
|
350
|
+
|
351
|
+
```ruby
|
352
|
+
Lotus::Mailer.configuration do
|
353
|
+
delivery_method :smtp
|
354
|
+
end
|
355
|
+
```
|
356
|
+
|
357
|
+
```ruby
|
358
|
+
Lotus::Mailer.configuration do
|
359
|
+
delivery_method :smtp, address: "localhost", port: 1025
|
360
|
+
end
|
361
|
+
```
|
362
|
+
|
363
|
+
Builtin options are:
|
364
|
+
|
365
|
+
* Exim (`:exim`)
|
366
|
+
* Sendmail (`:sendmail`)
|
367
|
+
* SMTP (`:smtp`, for local installations)
|
368
|
+
* SMTP Connection (`:smtp_connection`, via `Net::SMTP` - for remote installations)
|
369
|
+
* Test (`:test`, for testing purposes)
|
370
|
+
|
371
|
+
### Custom Delivery Method
|
372
|
+
|
373
|
+
Developers can specify their own custom delivery policy:
|
374
|
+
|
375
|
+
```ruby
|
376
|
+
require 'lotus/mailer'
|
377
|
+
|
378
|
+
class MandrillDeliveryMethod
|
379
|
+
def initialize(options)
|
380
|
+
@options = options
|
381
|
+
end
|
382
|
+
|
383
|
+
def deliver!(mail)
|
384
|
+
# ...
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
Lotus::Mailer.configure do
|
389
|
+
delivery_method MandrillDeliveryMethod,
|
390
|
+
username: ENV['MANDRILL_USERNAME'],
|
391
|
+
password: ENV['MANDRILL_API_KEY']
|
392
|
+
end.load!
|
393
|
+
```
|
394
|
+
|
395
|
+
The class passed to `.delivery_method` must accept an optional set of options
|
396
|
+
with the constructor (`#initialize`) and respond to `#deliver!`.
|
397
|
+
|
398
|
+
### Multipart Delivery
|
399
|
+
|
400
|
+
All the email are sent as multipart messages by default.
|
401
|
+
For a given mailer, the framework looks up for associated text (`.txt`) and `HTML` (`.html`) templates and render them.
|
402
|
+
|
403
|
+
```ruby
|
404
|
+
InvoiceMailer.deliver # delivers both text and html templates
|
405
|
+
InvoiceMailer.deliver(format: :txt) # delivers only text template
|
406
|
+
```
|
407
|
+
|
408
|
+
Please note that **they aren't both mandatory, but at least one of them MUST** be present.
|
409
|
+
|
410
|
+
## Versioning
|
411
|
+
|
412
|
+
__Lotus::Mailer__ uses [Semantic Versioning 2.0.0](http://semver.org)
|
413
|
+
|
414
|
+
## Copyright
|
415
|
+
|
416
|
+
Copyright © 2015 Luca Guidi – Released under MIT License
|
data/lib/lotus-mailer.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'lotus/mailer'
|
data/lib/lotus/mailer.rb
CHANGED
@@ -1,7 +1,316 @@
|
|
1
|
-
require
|
1
|
+
require 'lotus/utils/class_attribute'
|
2
|
+
require 'lotus/mailer/version'
|
3
|
+
require 'lotus/mailer/configuration'
|
4
|
+
require 'lotus/mailer/dsl'
|
5
|
+
require 'mail'
|
2
6
|
|
3
7
|
module Lotus
|
8
|
+
# Lotus::Mailer
|
9
|
+
#
|
10
|
+
# @since 0.1.0
|
4
11
|
module Mailer
|
5
|
-
#
|
12
|
+
# Base error for Lotus::Mailer
|
13
|
+
#
|
14
|
+
# @since 0.1.0
|
15
|
+
class Error < ::StandardError
|
16
|
+
end
|
17
|
+
|
18
|
+
# Missing delivery data error
|
19
|
+
#
|
20
|
+
# It's raised when a mailer doesn't specify <tt>from</tt> or <tt>to</tt>.
|
21
|
+
#
|
22
|
+
# @since 0.1.0
|
23
|
+
class MissingDeliveryDataError < Error
|
24
|
+
def initialize
|
25
|
+
super("Missing delivery data, please check 'from', or 'to'")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Content types mapping
|
30
|
+
#
|
31
|
+
# @since 0.1.0
|
32
|
+
# @api private
|
33
|
+
CONTENT_TYPES = {
|
34
|
+
html: 'text/html',
|
35
|
+
txt: 'text/plain'
|
36
|
+
}.freeze
|
37
|
+
|
38
|
+
include Utils::ClassAttribute
|
39
|
+
|
40
|
+
# @since 0.1.0
|
41
|
+
# @api private
|
42
|
+
class_attribute :configuration
|
43
|
+
self.configuration = Configuration.new
|
44
|
+
|
45
|
+
# Configure the framework.
|
46
|
+
# It yields the given block in the context of the configuration
|
47
|
+
#
|
48
|
+
# @param blk [Proc] the configuration block
|
49
|
+
#
|
50
|
+
# @since 0.1.0
|
51
|
+
#
|
52
|
+
# @see Lotus::Mailer::Configuration
|
53
|
+
#
|
54
|
+
# @example
|
55
|
+
# require 'lotus/mailer'
|
56
|
+
#
|
57
|
+
# Lotus::Mailer.configure do
|
58
|
+
# root '/path/to/root'
|
59
|
+
# end
|
60
|
+
def self.configure(&blk)
|
61
|
+
configuration.instance_eval(&blk)
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
# Override Ruby's hook for modules.
|
66
|
+
# It includes basic Lotus::Mailer modules to the given Class.
|
67
|
+
# It sets a copy of the framework configuration
|
68
|
+
#
|
69
|
+
# @param base [Class] the target mailer
|
70
|
+
#
|
71
|
+
# @since 0.1.0
|
72
|
+
# @api private
|
73
|
+
#
|
74
|
+
# @see http://www.ruby-doc.org/core/Module.html#method-i-included
|
75
|
+
def self.included(base)
|
76
|
+
conf = self.configuration
|
77
|
+
conf.add_mailer(base)
|
78
|
+
|
79
|
+
base.class_eval do
|
80
|
+
extend Dsl
|
81
|
+
extend ClassMethods
|
82
|
+
|
83
|
+
include Utils::ClassAttribute
|
84
|
+
class_attribute :configuration
|
85
|
+
|
86
|
+
self.configuration = conf.duplicate
|
87
|
+
end
|
88
|
+
|
89
|
+
conf.copy!(base)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Test deliveries
|
93
|
+
#
|
94
|
+
# This is a collection of delivered messages, used when <tt>delivery_method</tt>
|
95
|
+
# is set on <tt>:test</tt>
|
96
|
+
#
|
97
|
+
# @return [Array] a collection of delivered messages
|
98
|
+
#
|
99
|
+
# @since 0.1.0
|
100
|
+
#
|
101
|
+
# @see Lotus::Mailer::Configuration#delivery_mode
|
102
|
+
#
|
103
|
+
# @example
|
104
|
+
# require 'lotus/mailer'
|
105
|
+
#
|
106
|
+
# Lotus::Mailer.configure do
|
107
|
+
# delivery_method :test
|
108
|
+
# end.load!
|
109
|
+
#
|
110
|
+
# # In testing code
|
111
|
+
# Signup::Welcome.deliver
|
112
|
+
# Lotus::Mailer.deliveries.count # => 1
|
113
|
+
def self.deliveries
|
114
|
+
Mail::TestMailer.deliveries
|
115
|
+
end
|
116
|
+
|
117
|
+
# Load the framework
|
118
|
+
#
|
119
|
+
# @since 0.1.0
|
120
|
+
# @api private
|
121
|
+
def self.load!
|
122
|
+
Mail.eager_autoload!
|
123
|
+
configuration.load!
|
124
|
+
end
|
125
|
+
|
126
|
+
# @since 0.1.0
|
127
|
+
module ClassMethods
|
128
|
+
# Delivers a multipart email message.
|
129
|
+
#
|
130
|
+
# When a mailer defines a <tt>html</tt> and <tt>txt</tt> template, they are
|
131
|
+
# both delivered.
|
132
|
+
#
|
133
|
+
# In order to selectively deliver only one of the two templates, use
|
134
|
+
# <tt>Signup::Welcome.deliver(format: :txt)</tt>
|
135
|
+
#
|
136
|
+
# All the given locals, excepted the reserved ones (<tt>:format</tt> and
|
137
|
+
# <tt>charset</tt>), are avaliable as rendering context for the templates.
|
138
|
+
#
|
139
|
+
# @param locals [Hash] a set of objects that acts as context for the rendering
|
140
|
+
# @option :format [Symbol] specify format to deliver
|
141
|
+
# @option :charset [String] charset
|
142
|
+
#
|
143
|
+
# @since 0.1.0
|
144
|
+
#
|
145
|
+
# @see Lotus::Mailer::Configuration#default_charset
|
146
|
+
#
|
147
|
+
# @example
|
148
|
+
# require 'lotus/mailer'
|
149
|
+
#
|
150
|
+
# Lotus::Mailer.configure do
|
151
|
+
# delivery_method :smtp
|
152
|
+
# end.load!
|
153
|
+
#
|
154
|
+
# module Billing
|
155
|
+
# class Invoice
|
156
|
+
# include Lotus::Mailer
|
157
|
+
#
|
158
|
+
# from 'noreply@example.com'
|
159
|
+
# to :recipient
|
160
|
+
# subject :subject_line
|
161
|
+
#
|
162
|
+
# def prepare
|
163
|
+
# mail.attachments['invoice.pdf'] = File.read('/path/to/invoice.pdf')
|
164
|
+
# end
|
165
|
+
#
|
166
|
+
# private
|
167
|
+
#
|
168
|
+
# def recipient
|
169
|
+
# user.email
|
170
|
+
# end
|
171
|
+
#
|
172
|
+
# def subject_line
|
173
|
+
# "Invoice - #{ invoice.number }"
|
174
|
+
# end
|
175
|
+
# end
|
176
|
+
# end
|
177
|
+
#
|
178
|
+
# invoice = Invoice.new
|
179
|
+
# user = User.new(name: 'L', email: 'user@example.com')
|
180
|
+
#
|
181
|
+
# Billing::Invoice.deliver(invoice: invoice, user: user) # Deliver both text, HTML parts and the attachment
|
182
|
+
# Billing::Invoice.deliver(invoice: invoice, user: user, format: :txt) # Deliver only the text part and the attachment
|
183
|
+
# Billing::Invoice.deliver(invoice: invoice, user: user, format: :html) # Deliver only the text part and the attachment
|
184
|
+
# Billing::Invoice.deliver(invoice: invoice, user: user, charset: 'iso-8859') # Deliver both the parts with "iso-8859"
|
185
|
+
def deliver(locals = {})
|
186
|
+
new(locals).deliver
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
# Initialize a mailer
|
191
|
+
#
|
192
|
+
# @param locals [Hash] a set of objects that acts as context for the rendering
|
193
|
+
# @option :format [Symbol] specify format to deliver
|
194
|
+
# @option :charset [String] charset
|
195
|
+
#
|
196
|
+
# @since 0.1.0
|
197
|
+
def initialize(locals = {})
|
198
|
+
@locals = locals
|
199
|
+
@format = locals.fetch(:format, nil)
|
200
|
+
@charset = charset = locals.fetch(:charset, self.class.configuration.default_charset)
|
201
|
+
@mail = Mail.new.tap do |m|
|
202
|
+
m.from = __dsl(:from)
|
203
|
+
m.to = __dsl(:to)
|
204
|
+
m.subject = __dsl(:subject)
|
205
|
+
|
206
|
+
m.charset = charset
|
207
|
+
m.html_part = __part(:html)
|
208
|
+
m.text_part = __part(:txt)
|
209
|
+
|
210
|
+
m.delivery_method(*Lotus::Mailer.configuration.delivery_method)
|
211
|
+
end
|
212
|
+
|
213
|
+
prepare
|
214
|
+
end
|
215
|
+
|
216
|
+
# Render a single template with the specified format.
|
217
|
+
#
|
218
|
+
# @param format [Symbol] format
|
219
|
+
#
|
220
|
+
# @return [String] the output of the rendering process.
|
221
|
+
#
|
222
|
+
# @since 0.1.0
|
223
|
+
# @api private
|
224
|
+
def render(format)
|
225
|
+
self.class.templates(format).render(self, @locals)
|
226
|
+
end
|
227
|
+
|
228
|
+
# Delivers a multipart email, by looking at all the associated templates and render them.
|
229
|
+
#
|
230
|
+
# @since 0.1.0
|
231
|
+
# @api private
|
232
|
+
def deliver
|
233
|
+
mail.deliver
|
234
|
+
rescue ArgumentError
|
235
|
+
raise MissingDeliveryDataError
|
236
|
+
end
|
237
|
+
|
238
|
+
protected
|
239
|
+
|
240
|
+
# Prepare the email message when a new mailer is initialized.
|
241
|
+
#
|
242
|
+
# This is a hook that can be overwritten by mailers.
|
243
|
+
#
|
244
|
+
# @since 0.1.0
|
245
|
+
#
|
246
|
+
# @example
|
247
|
+
# require 'lotus/mailer'
|
248
|
+
#
|
249
|
+
# module Billing
|
250
|
+
# class Invoice
|
251
|
+
# include Lotus::Mailer
|
252
|
+
#
|
253
|
+
# subject 'Invoice'
|
254
|
+
# from 'noreply@example.com'
|
255
|
+
# to ''
|
256
|
+
#
|
257
|
+
# def prepare
|
258
|
+
# mail.attachments['invoice.pdf'] = File.read('/path/to/invoice.pdf')
|
259
|
+
# end
|
260
|
+
#
|
261
|
+
# private
|
262
|
+
#
|
263
|
+
# def recipient
|
264
|
+
# user.email
|
265
|
+
# end
|
266
|
+
# end
|
267
|
+
# end
|
268
|
+
#
|
269
|
+
# invoice = Invoice.new
|
270
|
+
# user = User.new(name: 'L', email: 'user@example.com')
|
271
|
+
def prepare
|
272
|
+
end
|
273
|
+
|
274
|
+
# @private
|
275
|
+
# @since 0.1.0
|
276
|
+
def method_missing(m)
|
277
|
+
@locals.fetch(m) { super }
|
278
|
+
end
|
279
|
+
|
280
|
+
# @since 0.1.0
|
281
|
+
attr_reader :mail
|
282
|
+
|
283
|
+
# @private
|
284
|
+
# @since 0.1.0
|
285
|
+
attr_reader :charset
|
286
|
+
|
287
|
+
private
|
288
|
+
|
289
|
+
# @private
|
290
|
+
# @since 0.1.0
|
291
|
+
def __dsl(method_name)
|
292
|
+
case result = self.class.__send__(method_name)
|
293
|
+
when Symbol
|
294
|
+
__send__(result)
|
295
|
+
else
|
296
|
+
result
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
# @private
|
301
|
+
# @since 0.1.0
|
302
|
+
def __part(format)
|
303
|
+
Mail::Part.new.tap do |part|
|
304
|
+
part.content_type = "#{ CONTENT_TYPES.fetch(format) }; charset=#{ charset }"
|
305
|
+
part.body = render(format)
|
306
|
+
end if __part?(format)
|
307
|
+
end
|
308
|
+
|
309
|
+
# @private
|
310
|
+
# @since 0.1.0
|
311
|
+
def __part?(format)
|
312
|
+
@format == format ||
|
313
|
+
(!@format && !self.class.templates(format).nil?)
|
314
|
+
end
|
6
315
|
end
|
7
316
|
end
|