maily_herald 0.8.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +8 -8
  2. data/.gitignore +1 -0
  3. data/.travis.yml +3 -0
  4. data/Gemfile +0 -2
  5. data/Gemfile.lock +5 -13
  6. data/README.md +186 -69
  7. data/app/mailers/maily_herald/mailer.rb +44 -26
  8. data/app/models/maily_herald/ad_hoc_mailing.rb +109 -0
  9. data/app/models/maily_herald/dispatch.rb +97 -4
  10. data/app/models/maily_herald/list.rb +36 -7
  11. data/app/models/maily_herald/log.rb +79 -0
  12. data/app/models/maily_herald/mailing.rb +149 -24
  13. data/app/models/maily_herald/one_time_mailing.rb +114 -9
  14. data/app/models/maily_herald/periodical_mailing.rb +76 -47
  15. data/app/models/maily_herald/sequence.rb +57 -18
  16. data/app/models/maily_herald/sequence_mailing.rb +29 -20
  17. data/app/models/maily_herald/subscription.rb +23 -2
  18. data/config/routes.rb +2 -2
  19. data/lib/maily_herald.rb +57 -18
  20. data/lib/maily_herald/autonaming.rb +8 -0
  21. data/lib/maily_herald/context.rb +6 -2
  22. data/lib/maily_herald/logging.rb +2 -0
  23. data/lib/maily_herald/manager.rb +15 -31
  24. data/lib/maily_herald/utils.rb +65 -24
  25. data/lib/maily_herald/version.rb +1 -1
  26. data/maily_herald.gemspec +1 -1
  27. data/spec/controllers/maily_herald/tokens_controller_spec.rb +13 -13
  28. data/spec/dummy/app/mailers/ad_hoc_mailer.rb +11 -0
  29. data/spec/dummy/app/mailers/custom_one_time_mailer.rb +11 -0
  30. data/spec/dummy/config/application.rb +1 -1
  31. data/spec/dummy/config/environments/test.rb +1 -1
  32. data/spec/dummy/config/initializers/maily_herald.rb +3 -69
  33. data/spec/dummy/config/maily_herald.yml +3 -0
  34. data/spec/dummy/db/seeds.rb +73 -0
  35. data/spec/lib/context_spec.rb +7 -7
  36. data/spec/lib/maily_herald_spec.rb +7 -8
  37. data/spec/lib/utils_spec.rb +65 -25
  38. data/spec/mailers/maily_herald/mailer_spec.rb +20 -13
  39. data/spec/models/maily_herald/ad_hoc_mailing_spec.rb +169 -0
  40. data/spec/models/maily_herald/list_spec.rb +2 -1
  41. data/spec/models/maily_herald/log_spec.rb +10 -10
  42. data/spec/models/maily_herald/mailing_spec.rb +9 -8
  43. data/spec/models/maily_herald/one_time_mailing_spec.rb +212 -39
  44. data/spec/models/maily_herald/periodical_mailing_spec.rb +158 -92
  45. data/spec/models/maily_herald/sequence_mailing_spec.rb +2 -2
  46. data/spec/models/maily_herald/sequence_spec.rb +152 -139
  47. data/spec/models/maily_herald/subscription_spec.rb +21 -4
  48. metadata +17 -8
  49. data/lib/maily_herald/condition_evaluator.rb +0 -82
  50. data/lib/maily_herald/config.rb +0 -5
  51. data/spec/dummy/app/mailers/test_mailer.rb +0 -11
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZjIwNzFmNTFiM2E1MzI0NGM0MjkxZDQyNTk2MDdkY2IzMmE1YzBjNA==
4
+ OTc4OTYyZGUxOTM1ZGNiY2MwYWQxMjYwZjFkYjE0NDAzMTUyMTI5Mw==
5
5
  data.tar.gz: !binary |-
6
- YzBlMTQ1Mzk0ZDEzYTg5N2FhYTlmYjQ3ZGMzY2E0NTZmMGU1NTkzMQ==
6
+ NmNhNjYyZGI2ZDE2MzcxN2JlYmFkZGVmMzMyZjhhZDQ5ZDhhYzU2YQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZmViMzhiN2IzMzg1NWQ0NzI0MjdlMTg3YzI0ZmZlNzU5MjY4NTdjNDJlYTM5
10
- NThhY2Q4NGRlZjYwNjBhNDYyYTFkMDE2NTZjZjVhOWFlZmU5YTAwY2ZlZjhm
11
- MjU2ZDg5OTZlNWEzZDk3ZjdjM2Q0YzU0Y2RmOGViNmUzNmEzMTA=
9
+ NTI5ZTVmNTI5YjRjNmUwNmVlZWEwNWFkNzg0NzI4YWZjN2Y0M2JlN2NkNzM0
10
+ M2EwZjljNjFiZjc3MzA3YWE5MmZkMWZjOWRhMmE2MGUyZjMyMTMxYTVhODc5
11
+ YTQ1M2RlZmQ5MDJlNTJiYTkyZGRlYzgzOTg0ZmUwMGE5ODQ4NWU=
12
12
  data.tar.gz: !binary |-
13
- ODhiYzU0N2Q4YTgyNGZhNTg1OWI2NTE1NzA2NmRmODlkNGUyNjE2ODY5ZWU4
14
- YjcwMDkyZmNlYzhhOGQ3NWNmYWE4N2I3YjUyZjdlMjFjNjY1Nzg3YTU4YTFi
15
- YmI2MTRlNjc1ODNlYzNiNWU2MTNiNjhlODkzY2YxOGVjOTlmYTU=
13
+ Yjk1MjcxNjY5N2Q5ZWMyZDY2ZTFiY2FiMzYzMTNiMGRkMTU4MmFjMjQ4YWE5
14
+ NTFjMDBjZDE2ZmZhZWQ4YTM2OGUyNWIyZTE0NDM4MjM2NDc0NjNhYmVlMTNk
15
+ NTM5MTM0YzkwNzcwZWFkZDNlZTQ4Y2RiMjgxNzU0OThmMjBjNjI=
data/.gitignore CHANGED
@@ -6,6 +6,7 @@ spec/dummy/log/*.log
6
6
  spec/dummy/tmp/
7
7
  spec/dummy/.sass-cache
8
8
  coverage/*
9
+ doc/*
9
10
  dump.rdb
10
11
  tmp
11
12
  *.gem
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ script:
2
+ - RAILS_ENV=test bundle exec rake db:setup
3
+ - bundle exec rspec
data/Gemfile CHANGED
@@ -4,5 +4,3 @@ gemspec
4
4
 
5
5
  # jquery-rails is used by the dummy application
6
6
  gem "jquery-rails"
7
-
8
- gem 'debugger'
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- maily_herald (0.0.1)
4
+ maily_herald (0.9.0)
5
5
  liquid (~> 2.6.1)
6
6
  rails (> 3.2)
7
7
  sidekiq (~> 2.17.8)
@@ -41,15 +41,8 @@ GEM
41
41
  celluloid (0.15.2)
42
42
  timers (~> 1.1.0)
43
43
  coderay (1.1.0)
44
- columnize (0.8.9)
45
- connection_pool (2.0.0)
44
+ connection_pool (2.2.0)
46
45
  database_cleaner (1.3.0)
47
- debugger (1.6.8)
48
- columnize (>= 0.3.1)
49
- debugger-linecache (~> 1.2.0)
50
- debugger-ruby_core_source (~> 1.3.5)
51
- debugger-linecache (1.2.0)
52
- debugger-ruby_core_source (1.3.5)
53
46
  diff-lcs (1.2.5)
54
47
  docile (1.1.3)
55
48
  erubis (2.7.0)
@@ -76,7 +69,7 @@ GEM
76
69
  railties (>= 3.0, < 5.0)
77
70
  thor (>= 0.14, < 2.0)
78
71
  json (1.8.1)
79
- liquid (2.6.1)
72
+ liquid (2.6.2)
80
73
  listen (2.7.7)
81
74
  celluloid (>= 0.15.2)
82
75
  rb-fsevent (>= 0.9.3)
@@ -122,8 +115,8 @@ GEM
122
115
  rdoc (3.12.2)
123
116
  json (~> 1.4)
124
117
  redcarpet (3.2.2)
125
- redis (3.1.0)
126
- redis-namespace (1.5.1)
118
+ redis (3.2.1)
119
+ redis-namespace (1.5.2)
127
120
  redis (~> 3.0, >= 3.0.4)
128
121
  rspec (3.0.0)
129
122
  rspec-core (~> 3.0.0)
@@ -181,7 +174,6 @@ PLATFORMS
181
174
 
182
175
  DEPENDENCIES
183
176
  database_cleaner
184
- debugger
185
177
  factory_girl_rails
186
178
  guard
187
179
  guard-rspec
data/README.md CHANGED
@@ -1,17 +1,20 @@
1
1
  # MailyHerald
2
2
 
3
- MailyHerald is a Ruby on Rails gem that helps you sending and managing your mailings. Think of Maily as a self-hosted Mailchimp alternative you can easily integrate with your site. MailyHerald is great both for email marketing and conducting daily stream of notifications you send to your users.
3
+ ![MailyHerald with its Web UI](./doc/webui.png)
4
+
5
+ MailyHerald is a Ruby on Rails gem that helps you send and manage your application mailings. Think of Maily as a self-hosted Mailchimp alternative you can easily integrate into your site. MailyHerald is great both for email marketing and conducting the daily stream of notifications you send to your users.
4
6
 
5
7
  With MailyHerald you can send:
6
- * one-time mailings (i.e. welcome emails, special offers),
8
+ * ad-hoc mailings - arbitrary emails sent to one or more users at a given point in time (i.e. password reset instructions, special offers, announcements),
9
+ * one-time mailings (i.e. account activation, welcome emails),
7
10
  * periodical mailings (i.e. weekly notifications, reminders),
8
- * mailing sequences - multiple ordered emails delivered with certain delays since specific point in time (i.e. onboarding emails, site feature overview).
11
+ * mailing sequences - multiple ordered emails delivered with certain delays from a specific point in time (i.e. onboarding emails, site feature overview, reminders).
9
12
 
10
- Maily keeps track of user subscriptions and allow them to easily opt out. You can define who receives which emails and specify conditions that control delivery. All deliveries are tracked and logged. Periodical and Sequence mailing deliveries are scheduled individually for each recipient.
13
+ Maily keeps track of user subscriptions and allows them to easily opt out. You can define who receives which emails and specify conditions that control delivery. All mailing deliveries are scheduled individually for each recipient, tracked and logged.
11
14
 
12
- Maily seamlessly integrates with your app. It can use your regular Mailers or you can build ad-hoc mailings with [Liquid](http://liquidmarkup.org/) markup templates.
15
+ Maily seamlessly integrates with your app. It can use your regular Action Mailers or you can build email contents with [Liquid](http://liquidmarkup.org/) markup templates.
13
16
 
14
- Core Maily features are accessible for Rails programmers via API. Apart from that, Maily has a nice web UI provided by separate [maily_herald-webui](https://github.com/Sology/maily_herald-webui) gem.
17
+ Core Maily features are accessible for Rails programmers via the API. Apart from that, Maily has a nice Web UI provided by a separate [maily_herald-webui](https://github.com/Sology/maily_herald-webui) gem.
15
18
 
16
19
  ## Requirements
17
20
 
@@ -19,7 +22,7 @@ Both Ruby on Rails 3.2 and 4 are supported.
19
22
 
20
23
  ## Installation
21
24
 
22
- Simply just
25
+ Simply just run
23
26
 
24
27
  gem install maily_herald
25
28
 
@@ -32,72 +35,72 @@ or put in your Gemfile
32
35
  * Designed for Ruby on Rails
33
36
  * Self-hosted
34
37
  * Seamless and flexible integration
35
- * Asynchronous processing
36
- * Individual delivery scheduling
37
- * Great both for developers (API) and end-users (Web UI)
38
- * Ad-hoc email templating using [Liquid](http://liquidmarkup.org/) syntax
39
- * Three different mailing types
38
+ * Asynchronous email processing
39
+ * Per-recipient delivery scheduling
40
+ * Great both for developers (API) and end users (Web UI)
41
+ * On-the-fly email templating using [Liquid](http://liquidmarkup.org/) syntax
42
+ * Four different mailing types
40
43
  * User-friendly subscription management i.e. via automatic & personal opt-out links
41
44
  * Correspondence logging
42
- * Mailing conditions
45
+ * Delivery conditions
43
46
 
44
47
  ## Development state
45
48
 
46
- MailyHerald is relatively young piece of software and can't be considered stable. Although it has been deployed to few production environments for quite some time now, we can't guarantee it will suite your needs too.
49
+ MailyHerald is a relatively young piece of software and it has been deployed in a few different production environments.
47
50
 
48
- If you decide to use it, please tell us what you think about it, post some issues on GitHub etc. We're waiting for your feedback.
51
+ If you decide to use it, please tell us what you think about it. You can post some issues on GitHub or email us directly. We're waiting for your feedback.
49
52
 
50
53
  Here are some things we would like to implement in the future:
51
54
 
52
- * better mailing scheduling,
53
55
  * message analytics,
54
56
  * link tracking,
55
- * better Web UI,
57
+ * fetching bounces from email service (Amazon SES, Mandrill, Sendgrid etc.),
58
+ * better templating,
56
59
  * _put your beloved feature here_.
57
60
 
58
61
  ## How it works
59
62
 
60
- There are few key concepts that need to be explained in order to understand how Maily works. Some of them are similar to what you might know form other conventional email marketing software. Others come strictly from Ruby on Rails world.
63
+ There are a few key concepts that need to be explained in order to understand how Maily works. Some of them are similar to what you might know from other conventional email marketing software. Others come strictly from the Ruby on Rails world.
61
64
 
62
65
  **Entities**
63
66
 
64
- Entities are basically your mailing recipients. They will be probably represented in your application by `User` model.
67
+ Entities are your mailing recipients. They will probably be represented in your application by `User` model.
65
68
 
66
69
  **Mailings**
67
70
 
68
- You usually send single emails to your users - one at a time. Mailing is a bunch of emails sent out to many users. MailyHerald allows you to send three types of Mailings: one-times, periodicals and sequences.
71
+ You usually send single emails to your users, one at a time. Mailing is a bunch of emails sent out to many users. MailyHerald allows you to send four types of Mailings: ad-hoc, one-times, periodicals and sequences.
69
72
 
70
73
  **Contexts**
71
74
 
72
- Maily Contexts are abstraction layer for accessing collections of entities and their attributes.
75
+ Maily Contexts provide a layer of abstraction for accessing collections of entities and their attributes.
73
76
 
74
77
  There are three main things that Contexts do:
75
78
 
76
- * They define sets of entities via Rails scopes (i.e. `User.activated` meaning all application users that activated their accounts).
79
+ * They define sets of entities via standard Rails scopes (i.e. `User.activated` meaning all application users that activated their accounts).
77
80
  * They specify destination email addresses for entities (i.e. you can define that `User#email` method returns email address or specify a custom proc that does that).
78
- * They specify additional entity attributes that can be used inside Mailing templates, conditions etc. (basically - attributes accessible via Liquid).
81
+ * They specify additional entity attributes that can be used inside Mailing templates, conditions etc. (essentially, any attribute accessible via Liquid).
79
82
 
80
83
  **Lists and Subscriptions**
81
84
 
82
- Lists are sets of entities that receive certain mailings. Entities are added to Lists by creating Subscriptions. It is entirely up to you how you manage subscriptions in application. Typically, you put some checkbox in user's profile page that subscribes and unsubscribes them from mailing lists.
85
+ Lists are sets of entities that receive certain mailings. Entities are added to Lists by creating Subscriptions. It is entirely up to you how you manage subscriptions in the application. Typically, you would put a checkbox in the user's profile page which subscribes and unsubscribes them from mailing lists.
83
86
 
84
- Each Subscription has it's unique token allowing users to be provided with one click opt-out link.
87
+ Each Subscription has a unique token allowing users to be provided with one-click opt-out links.
85
88
 
86
89
  **Mailers**
87
90
 
88
- Mailers are standard way of sending emails in Rails applications. MailyHerald hooks into ActionMailer internals and allows you to send Mailings just like you send your regular emails. All you need to do is inherit `MailyHerald::Mailer` in your Mailer.
91
+ Mailers are the standard way of sending emails in Rails applications. MailyHerald hooks into ActionMailer internals and allows you to send Mailings just like you send your regular emails. All you need to do is inherit `MailyHerald::Mailer` in your Mailer.
89
92
 
90
- There's also a possibility to send Mailings without using any of your custom Mailers. `MailyHerald::Mailer` is in this case used implicitly; email body and subject is stored directly in your Mailing definition as a Liquid template. Liquid gives you access to entity attributes defined in the Context. This way of creating Mailings is especially useful within Web UI where you can build new Mailing by just typing its template.
93
+ There's also a possibility to send Mailings without using any of your custom Mailers. `MailyHerald::Mailer` is in this case used implicitly; email body and subject is stored directly in your Mailing definition as a Liquid template. Liquid gives you access to entity attributes defined in the Context. This way of creating Mailings is especially useful within the Web UI where you can build new Mailing by simply typing in its template.
91
94
 
92
95
  **Delivery**
93
96
 
94
- MailyHerald uses great gem [Sidekiq](http://sidekiq.org/) to process deliveries in the background. This applies to Periodical and Sequence Mailings - their delivieries are scheduled individually for each entity on the subscription list.
97
+ MailyHerald uses the great gem [Sidekiq](http://sidekiq.org/) to process deliveries in the background. This applies to all kinds of Mailings - their deliveries are scheduled individually for each entity on the subscription list.
95
98
 
96
- Maily needs to check periodically for scheduled mailings and if their time come - queue them for delivery. This is job for MailyHerald Paperboy - tiny daemon that runs in the background and check the schedules. It is essential to make you periodical and sequence mailings work.
99
+ Maily checks periodically for scheduled mailings, and then the time comes, queues them for delivery. This is the job of MailyHerald Paperboy - a tiny daemon that runs in the background and checks the schedules. It is essential to make your mailings work.
97
100
 
98
101
  ## Usage
99
102
 
100
- Let's assume your entities are your `User` model objects. Read on in order to find out how to start with Maily.
103
+ Let's assume your entities are your `User` model objects. Read on in order to find out how to get started with Maily.
101
104
 
102
105
  ### Migrations
103
106
 
@@ -110,9 +113,10 @@ rake db:migrate
110
113
 
111
114
  ### Defaults (optional)
112
115
 
113
- In some cases, you need to specify default `from` and `host` mailer options in order to ensure proper email rendering:
116
+ In some cases, you need to specify default `from` and `host` mailer options in your application in order to ensure proper email rendering:
114
117
 
115
118
  ```ruby
119
+ # config/application.rb
116
120
  config.action_mailer.default_options = { from: "hello@mailyherald.org" }
117
121
  config.action_mailer.default_url_options = { host: "mailyherald.org" }
118
122
 
@@ -120,7 +124,7 @@ config.action_mailer.default_url_options = { host: "mailyherald.org" }
120
124
 
121
125
  ### Initializer
122
126
 
123
- Generate and setup an initializer.
127
+ Generate an initializer:
124
128
 
125
129
  ```ruby
126
130
  rails g maily_herald:install
@@ -139,7 +143,7 @@ There are few things you need to put there.
139
143
 
140
144
  **Set up your context**
141
145
 
142
- Say for example, you want to deliver your mailings to all your active users:
146
+ Say, for example, you want to deliver your mailings to all your active users:
143
147
 
144
148
  ```ruby
145
149
  config.context :active_users do |context|
@@ -153,7 +157,7 @@ end
153
157
 
154
158
  **Set up your lists**
155
159
 
156
- Following means that all users in `:active_users` context scope can be subscribed to `:newsletters` list.
160
+ The following means that all users in the `:active_users` context scope can be subscribed to the `:newsletters` list.
157
161
 
158
162
  ```ruby
159
163
  config.list :newsletters do |list|
@@ -161,34 +165,110 @@ config.list :newsletters do |list|
161
165
  end
162
166
  ```
163
167
 
168
+ MailyHerald lists are opt-in lists. They are empty by default, so make sure to add entities to them, i.e. by using `MailyHerald.subscribe` method.
169
+
164
170
  **Set up your mailings**
165
171
 
166
172
  ```ruby
167
173
  config.one_time_mailing :hello do |mailing|
168
174
  mailing.title = "Hello mailing"
169
- mailing.context_name = :active_users
175
+ mailing.list = :notifications
170
176
  mailing.mailer_name = "UserMailer"
177
+ mailing.start_at = Proc.new{|user| user.created_at + 1.hour}
171
178
  mailing.enable # mailings are disabled by default
172
179
  end
173
180
 
174
181
  config.periodical_mailing :weekly_newsletter do |mailing|
175
182
  mailing.title = "Weekly newsletter"
176
- mailing.context_name = :active_users
183
+ mailing.list = :newsletters
177
184
  mailing.mailer_name = "UserMailer"
185
+ mailing.start_at = Proc.new{|user| user.created_at + 1.week}
186
+ mailing.period = 1.week
187
+ mailing.enable
188
+ end
189
+ ```
190
+
191
+ **Configuration locking**
192
+
193
+ By default, all contexts, lists and mailings initialized inside `MailyHerald.setup` block are locked and cannot be edited at runtime. This constraint is enforced to maintain the nature of RoR application initializer files. Things set up in the initializer should always be read-only because the initializer is executed every time the application spawns.
194
+
195
+ If you need to set up mailings programmatically and make them unlocked, don't simply use `MailyHerald.setup`. Instead, use methods from the `MailyHerald` class directly. You can then enter your code, i.e. in a DB seed file or a rake task.
196
+
197
+ You would typically put your `MailyHerald.setup` block in the Maily initializer file. Keep in mind that this file is evaluated every time Rails boots up, so changes made there (i.e. new mailings added) will be reflected at next application launch.
198
+
199
+ ### Different mailing types
200
+
201
+ **AdHocMailing** is the most similar to regular Ruby on Rails emails sent using ActionMailer. The only difference is that their delivery is handled by Maily and thus logged and optionally backgrounded.
202
+
203
+ **OneTimeMailing** deliveries are performed only once to a single recipient at a scheduled delivery time. It is fully automatic and its delivery can't be manually triggered. OneTimeMailing schedules are created based on the `start_at` attribute individually for each recipient.
204
+
205
+ **PeriodicalMailing** handles multiple, periodical email deliveries to individual recipients. It is also automatic. Apart from the `start_at` attribute, it also uses a `period` which defines the time distance between consecutive deliveries.
206
+
207
+ **Sequence** allows you to send multiple different mailings to a given entity with various time delays. It is achieved by defining SequenceMailings associated to a Sequence with delivery delays stored in their `absolute_delay` attributes. A mailing delivery delay is calculated from a point in time defined in Sequence's `start_at` attribute (similar to PeriodicalMailing).
208
+
209
+ ### Procs and Liquid syntax
210
+
211
+ Mailing attributes such as `start_at` and `conditions` can be defined programmatically as procs or as a string using Liquid syntax. Here's an example of those two cases:
212
+
213
+ ```ruby
214
+ # Using Proc:
215
+ mailing.start_at = Proc.new{|user| user.created_at + 5.minutes}
216
+
217
+ # Using Liquid:
218
+ mailing.start_at = "user.created_at | plus: 5, 'minutes'"
219
+ ```
220
+
221
+ Liquid syntax is obviously more convenient for non-programmers (and can be safely used i.e. in WebUI) but requires some additional setup inside Maily Context. Context attributes available within Liquid templates have to be defined:
222
+
223
+ ```ruby
224
+ config.context :all_users do |context|
225
+ context.scope {User.all}
226
+ context.destination = :email
227
+ context.attributes do |user|
228
+ attribute_group(:user) do
229
+ attribute(:name) {user.name}
230
+ attribute(:email) {user.email}
231
+ attribute(:created_at) {user.created_at}
232
+ end
233
+ end
234
+ end
235
+ ```
236
+
237
+ Maily provides some Liquid filters that are particularly useful for time manipulation:
238
+
239
+ * `plus: <number>, '<period>'`
240
+ * `minus: <number>, '<period>'`
241
+
242
+ They can be used for incrementing and decrementing the time value. `<number>` is simply an integer; `<period>` is one of 'minutes', 'hours', 'days' etc.
243
+
244
+ The Mailing body can also be defined programmatically using custom Mailer. The other way is to not define explicit Mailer but rather set the subject and template as Liquid templates.
245
+
246
+ ```ruby
247
+ # Using custom ActionMailer:
248
+ config.ad_hoc_mailing :hello do |mailing|
249
+ mailing.list = :all_users
250
+ mailing.mailer_name = "UserMailer" # In this case, you should have a mailer called 'UserMailer' that defines method 'hello'.
251
+ mailing.enable
252
+ end
253
+
254
+ # Using Liquid templates:
255
+ config.ad_hoc_mailing :hello do |mailing|
256
+ mailing.list = :all_users
257
+ mailing.subject = "Hello {{user.name}}!"
258
+ mailing.template = "What's up?"
178
259
  mailing.enable
179
260
  end
180
261
  ```
181
262
 
182
263
  ### Mailers
183
264
 
184
- You don't need to have any Mailer to use MailyHerald. It works perfectly fine with its generic `MailyHerald::Mailer` and mailing templates written in Luquid.
265
+ If you want to use your custom ActionMailers with Maily, you need to modify them a bit.
185
266
 
186
- But if you still want your fancy Mailer views and features, you need to modify it a bit.
267
+ First, each Mailer you want to use with MailyHerald needs to extend the `MailyHerald::Mailer` class.
187
268
 
188
- First, each Mailer you want to use with MailyHerald needs to extend `MailyHerald::Mailer` class.
189
- Then each Mailer method must be named after mailing identification name and accept only one parameter which is your entity (i.e. `User` class object).
269
+ Then each Mailer method must be named after the mailing identification name and accept only one parameter, which will be your entity (i.e. `User` class object).
190
270
 
191
- This setup gives you some extra instance variables available in your views:
271
+ This setup gives you additional instance variables available to you in your views:
192
272
 
193
273
  * `@maily_entity` - entity you are sending this email to,
194
274
  * `@maily_mailing` - Mailing you are sending,
@@ -206,9 +286,9 @@ end
206
286
 
207
287
  ### Opt-outs
208
288
 
209
- MailyHerald allows entities to easily opt-out using direct unsubscribe urls. Each entity subscription has its own token and based on this token, opt-out URL is generated.
289
+ MailyHerald allows entities to easily opt-out using direct unsubscribe urls. Each entity subscription has its own token and based on this token, the opt-out URL is generated.
210
290
 
211
- To process user opt-out requests you need to mount Maily into your app:
291
+ To process user opt-out requests, you need to mount Maily into your app:
212
292
 
213
293
  ```ruby
214
294
  # config/routes.rb
@@ -216,50 +296,57 @@ To process user opt-out requests you need to mount Maily into your app:
216
296
  mount MailyHerald::Engine => "/unsubscribe", :as => "maily_herald_engine"
217
297
  ```
218
298
 
219
- Maily provides you with URL helper that generates opt-out URLs (i.e. in your ActionMailer views):
299
+ Maily provides you with a URL helper that generates opt-out URLs (i.e. in your ActionMailer views):
220
300
 
221
301
  ```ruby
222
- maily_herald_engine.unsubscribe_url(@maily_subscription)
302
+ maily_herald_engine.maily_unsubscribe_url(@maily_subscription)
223
303
  ```
224
304
 
225
- When you use Liquid for email templating, you should use following syntax:
305
+ When you use Liquid for email templating, your context will always include the special attribute `subscription` that allows you to easily output unique opt-out URLs. Use the following syntax:
306
+
226
307
  ```
227
308
  {{subscription.token_url}}
228
309
  ```
229
310
 
230
- Visiting opt-out url disables subscription and by default redirects to "/".
231
-
232
- ### Delivery
311
+ Visiting an opt-out URL disables the subscription and by default redirects to "/".
233
312
 
234
- From now on, Maily will handle and track your regular mail deliveries:
313
+ ### Delivery and background processing
235
314
 
236
- ```ruby
237
- UserMailer.hello(User.first).deliver
238
- ```
315
+ Scheduled MailyHerald mailings are always sent in the background.
239
316
 
240
- Of course, you can also run the mailing for all users in scope at once:
317
+ In order to make your deliveries work, you need to run MailyHerald Paperboy, which will take care of it:
241
318
 
242
- ```ruby
243
- MailyHerald.dispatch(:hello).run
319
+ ```
320
+ $ bundle exec maily_herald paperboy --start
244
321
  ```
245
322
 
246
- See [API Docs](http://www.rubydoc.info/gems/maily_herald) for more details about delivery methods.
323
+ Paperboy will monitor your mailing schedules and queue their delivery. The actual sending of emails is handled in the background as a Sidekiq job, so make sure you run Sidekiq alongside Paperboy.
247
324
 
248
- ### Background processing
325
+ You can't manually trigger delivery of one-time, periodical and sequence mailings. Their schedules and deliveries are maintained automatically.
249
326
 
250
- Start MailyHerald Paperboy which will take care of your other periodical and sequence deliveries:
327
+ Ad-hoc mailing, on the other hand, can (and should!) be manually scheduled for delivery:
251
328
 
329
+ ```ruby
330
+ MailyHerald.ad_hoc_mailing(:password_reset).schedule_delivery_to User.first, Time.now
252
331
  ```
253
- $ maily_herald paperboy --start
332
+
333
+ Alernatively, for Action Mailer compatibility, you can use the standard syntax for sending emails:
334
+
335
+ ```ruby
336
+ UserMailer.password_reset(User.first).deliver
254
337
  ```
255
338
 
256
- **That's it!**
339
+ This code will process email delivery immediately, in the current thread, just like a regular Action Mailer.
340
+
341
+ ### That's it!
257
342
 
258
343
  Your Maily setup is now complete.
259
344
 
345
+ See [API Docs](http://www.rubydoc.info/gems/maily_herald) for more details about usage and configuration.
346
+
260
347
  ## Configuring
261
348
 
262
- You can configure your Maily using config file `config/maily_herald.yml`. Supported options:
349
+ You can configure your Maily using the config file `config/maily_herald.yml`. Supported options:
263
350
 
264
351
  * `verbose`: true,false
265
352
  * `logfile`: where all the stuff is logged, usually 'log/maily_herald.log`
@@ -268,11 +355,29 @@ You can configure your Maily using config file `config/maily_herald.yml`. Suppor
268
355
  * `redis_namespace`: string
269
356
  * `redis_driver`: string
270
357
 
271
- ## Customizing
358
+ ## Other stuff
359
+
360
+ ### Periodical mailing scheduling
361
+
362
+ Periodical mailing is kind of a special one and has two modes of scheduling: general and individual. If you specify `start_at` as an absolute time, i.e. `"2111-01-01 11:11"`, it goes into general scheduling mode and consecutive mailings will be delivered to all subscribed entities at the same time at every period. This way you can send, for example, weekly newsletters every Monday to all subscribers.
363
+
364
+ When you specify `start_at` as an individual time, i.e. `"user.start_at"`, individual scheduling mode will be enabled. In this case, delivery periods will count individually for each user and deliveries will be made accordingly.
365
+
366
+ Individual scheduling mode is the only mode available for all other mailing types.
367
+
368
+ ### Deployments
369
+
370
+ Maily has a built-in simple support for Capistrano. It supports both v2 and v3 and automates the task of starting, stopping and restarting the Paperboy daemon during deployments.
371
+
372
+ To enable, just put the following line into your `Capfile`:
373
+
374
+ ```ruby
375
+ require 'maily_herald/capistrano'
376
+ ```
272
377
 
273
378
  ### Opt-out URLs
274
379
 
275
- By default, visiting opt-out URL disables subscription and redirects to "/". You can easily customize the redirect path by specifying `token_redirect` proc:
380
+ By default, visiting an opt-out URL silently disables the subscription and redirects to "/". You can easily customize the redirect path by specifying `token_redirect` proc:
276
381
 
277
382
  ```ruby
278
383
  # Evaluated within config:
@@ -310,7 +415,7 @@ end
310
415
 
311
416
  ### Redis namespaces
312
417
 
313
- If you want to use MailyHerald with non-standard Redis namespace, make sure your Sidekiq is also configured properly. This usually involves creating initializer file:
418
+ If you want to use MailyHerald with non-standard Redis namespace, make sure your Sidekiq is also configured properly. This usually involves creating an initializer file:
314
419
 
315
420
  ```ruby
316
421
  # config/initializers/sidekiq.rb
@@ -322,7 +427,7 @@ Sidekiq.configure_client do |config|
322
427
  end
323
428
  ```
324
429
 
325
- Then of course you need to tell Maily about that too:
430
+ Then make sure you tell Maily about the change:
326
431
 
327
432
  ```yaml
328
433
  # config/maily_herald.yml
@@ -330,14 +435,26 @@ Then of course you need to tell Maily about that too:
330
435
  :redis_namespace: maily
331
436
  ```
332
437
 
438
+ ## Contributing
439
+
440
+ Please aim your pull requests to 'development' branch.
441
+
442
+ Your changes should be well tested. To set up test environment just run:
443
+
444
+ ```
445
+ RAILS_ENV=test rake db:setup
446
+ rspec
447
+ guard # execute specs interactively
448
+ ```
449
+
333
450
  ## More Information
334
451
 
335
- * [Home Page](http://www.mailyherald.org)
452
+ * [Home Page](http://mailyherald.org)
336
453
  * [API Docs](http://www.rubydoc.info/gems/maily_herald)
337
- * Showcase (_coming soon_)
454
+ * [Showcase](http://showcase.sology.eu/maily_herald)
338
455
  * [Sample application](https://github.com/Sology/maily_testapp)
339
456
 
340
- For bug reports or feature requests see the [issues on Github](https://github.com/Sology/maily_herald/issues).
457
+ Although we work hard on MailyHerald development, we can't guarantee it is free of bugs. If you find one, please make sure to report it using [issues tracker on Github](https://github.com/Sology/maily_herald/issues). You can also post your feature requests there too.
341
458
 
342
459
  ## License
343
460