onesignal-rails-plugin 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +215 -0
- data/LICENSE +24 -0
- data/README.md +239 -0
- data/Rakefile +12 -0
- data/lib/onesignal/rails/plugin/delivery_error.rb +19 -0
- data/lib/onesignal/rails/plugin/delivery_method.rb +170 -0
- data/lib/onesignal/rails/plugin/literals.rb +9 -0
- data/lib/onesignal/rails/plugin/railtie.rb +18 -0
- data/lib/onesignal/rails/plugin/version.rb +9 -0
- data/lib/onesignal/rails/plugin.rb +61 -0
- data/onesignal-rails-plugin.gemspec +36 -0
- data/spec/lib/onesignal/rails/plugin/delivery_method_spec.rb +308 -0
- data/spec/spec_helper.rb +26 -0
- metadata +116 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 54e86f1ddbe283916a63b125cce2b1c305524bda45ff3b6ca7b8055cf3ac8c34
|
4
|
+
data.tar.gz: a85a401454cdef5db2a480311d15be0e89498f8488ac4c4c06ae8e2cfc85e75b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 11807aa7f347a12863029745f76b654c34798d0fc7cf2dd0a67f856c1fe773eea125c36ec07ff9709396e319d5fa23b29fc3654ca8da9171beaaab7ad4439ef2
|
7
|
+
data.tar.gz: a2c65de51c44706e60a38f07efd194883a289d4b90d1e45c5452334591ddfc52ce3a55f92967ab3a45ec38da18696d3fadc41aded0db11534d94dcd3c374573a
|
data/Gemfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
# Specify your gem's dependencies in onesignal-rails-plugin.gemspec
|
6
|
+
gemspec
|
7
|
+
|
8
|
+
group :development, :test do
|
9
|
+
gem 'pry'
|
10
|
+
gem 'rake', '~> 13.0.1'
|
11
|
+
gem 'rubocop', '~> 1.29'
|
12
|
+
gem 'standard'
|
13
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,215 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
onesignal-rails-plugin (1.0.0)
|
5
|
+
onesignal (~> 1.0.1)
|
6
|
+
rails
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
actioncable (7.0.3)
|
12
|
+
actionpack (= 7.0.3)
|
13
|
+
activesupport (= 7.0.3)
|
14
|
+
nio4r (~> 2.0)
|
15
|
+
websocket-driver (>= 0.6.1)
|
16
|
+
actionmailbox (7.0.3)
|
17
|
+
actionpack (= 7.0.3)
|
18
|
+
activejob (= 7.0.3)
|
19
|
+
activerecord (= 7.0.3)
|
20
|
+
activestorage (= 7.0.3)
|
21
|
+
activesupport (= 7.0.3)
|
22
|
+
mail (>= 2.7.1)
|
23
|
+
net-imap
|
24
|
+
net-pop
|
25
|
+
net-smtp
|
26
|
+
actionmailer (7.0.3)
|
27
|
+
actionpack (= 7.0.3)
|
28
|
+
actionview (= 7.0.3)
|
29
|
+
activejob (= 7.0.3)
|
30
|
+
activesupport (= 7.0.3)
|
31
|
+
mail (~> 2.5, >= 2.5.4)
|
32
|
+
net-imap
|
33
|
+
net-pop
|
34
|
+
net-smtp
|
35
|
+
rails-dom-testing (~> 2.0)
|
36
|
+
actionpack (7.0.3)
|
37
|
+
actionview (= 7.0.3)
|
38
|
+
activesupport (= 7.0.3)
|
39
|
+
rack (~> 2.0, >= 2.2.0)
|
40
|
+
rack-test (>= 0.6.3)
|
41
|
+
rails-dom-testing (~> 2.0)
|
42
|
+
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
43
|
+
actiontext (7.0.3)
|
44
|
+
actionpack (= 7.0.3)
|
45
|
+
activerecord (= 7.0.3)
|
46
|
+
activestorage (= 7.0.3)
|
47
|
+
activesupport (= 7.0.3)
|
48
|
+
globalid (>= 0.6.0)
|
49
|
+
nokogiri (>= 1.8.5)
|
50
|
+
actionview (7.0.3)
|
51
|
+
activesupport (= 7.0.3)
|
52
|
+
builder (~> 3.1)
|
53
|
+
erubi (~> 1.4)
|
54
|
+
rails-dom-testing (~> 2.0)
|
55
|
+
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
56
|
+
activejob (7.0.3)
|
57
|
+
activesupport (= 7.0.3)
|
58
|
+
globalid (>= 0.3.6)
|
59
|
+
activemodel (7.0.3)
|
60
|
+
activesupport (= 7.0.3)
|
61
|
+
activerecord (7.0.3)
|
62
|
+
activemodel (= 7.0.3)
|
63
|
+
activesupport (= 7.0.3)
|
64
|
+
activestorage (7.0.3)
|
65
|
+
actionpack (= 7.0.3)
|
66
|
+
activejob (= 7.0.3)
|
67
|
+
activerecord (= 7.0.3)
|
68
|
+
activesupport (= 7.0.3)
|
69
|
+
marcel (~> 1.0)
|
70
|
+
mini_mime (>= 1.1.0)
|
71
|
+
activesupport (7.0.3)
|
72
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
73
|
+
i18n (>= 1.6, < 2)
|
74
|
+
minitest (>= 5.1)
|
75
|
+
tzinfo (~> 2.0)
|
76
|
+
ast (2.4.2)
|
77
|
+
builder (3.2.4)
|
78
|
+
coderay (1.1.3)
|
79
|
+
concurrent-ruby (1.1.10)
|
80
|
+
crass (1.0.6)
|
81
|
+
diff-lcs (1.5.0)
|
82
|
+
digest (3.1.0)
|
83
|
+
erubi (1.10.0)
|
84
|
+
ethon (0.15.0)
|
85
|
+
ffi (>= 1.15.0)
|
86
|
+
ffi (1.15.5)
|
87
|
+
globalid (1.0.0)
|
88
|
+
activesupport (>= 5.0)
|
89
|
+
i18n (1.10.0)
|
90
|
+
concurrent-ruby (~> 1.0)
|
91
|
+
loofah (2.18.0)
|
92
|
+
crass (~> 1.0.2)
|
93
|
+
nokogiri (>= 1.5.9)
|
94
|
+
mail (2.7.1)
|
95
|
+
mini_mime (>= 0.1.1)
|
96
|
+
marcel (1.0.2)
|
97
|
+
method_source (1.0.0)
|
98
|
+
mini_mime (1.1.2)
|
99
|
+
minitest (5.15.0)
|
100
|
+
net-imap (0.2.3)
|
101
|
+
digest
|
102
|
+
net-protocol
|
103
|
+
strscan
|
104
|
+
net-pop (0.1.1)
|
105
|
+
digest
|
106
|
+
net-protocol
|
107
|
+
timeout
|
108
|
+
net-protocol (0.1.3)
|
109
|
+
timeout
|
110
|
+
net-smtp (0.3.1)
|
111
|
+
digest
|
112
|
+
net-protocol
|
113
|
+
timeout
|
114
|
+
nio4r (2.5.8)
|
115
|
+
nokogiri (1.13.6-x86_64-darwin)
|
116
|
+
racc (~> 1.4)
|
117
|
+
onesignal (1.0.1)
|
118
|
+
typhoeus (~> 1.0, >= 1.0.1)
|
119
|
+
parallel (1.22.1)
|
120
|
+
parser (3.1.2.0)
|
121
|
+
ast (~> 2.4.1)
|
122
|
+
pry (0.14.1)
|
123
|
+
coderay (~> 1.1)
|
124
|
+
method_source (~> 1.0)
|
125
|
+
racc (1.6.0)
|
126
|
+
rack (2.2.3.1)
|
127
|
+
rack-test (1.1.0)
|
128
|
+
rack (>= 1.0, < 3)
|
129
|
+
rails (7.0.3)
|
130
|
+
actioncable (= 7.0.3)
|
131
|
+
actionmailbox (= 7.0.3)
|
132
|
+
actionmailer (= 7.0.3)
|
133
|
+
actionpack (= 7.0.3)
|
134
|
+
actiontext (= 7.0.3)
|
135
|
+
actionview (= 7.0.3)
|
136
|
+
activejob (= 7.0.3)
|
137
|
+
activemodel (= 7.0.3)
|
138
|
+
activerecord (= 7.0.3)
|
139
|
+
activestorage (= 7.0.3)
|
140
|
+
activesupport (= 7.0.3)
|
141
|
+
bundler (>= 1.15.0)
|
142
|
+
railties (= 7.0.3)
|
143
|
+
rails-dom-testing (2.0.3)
|
144
|
+
activesupport (>= 4.2.0)
|
145
|
+
nokogiri (>= 1.6)
|
146
|
+
rails-html-sanitizer (1.4.2)
|
147
|
+
loofah (~> 2.3)
|
148
|
+
railties (7.0.3)
|
149
|
+
actionpack (= 7.0.3)
|
150
|
+
activesupport (= 7.0.3)
|
151
|
+
method_source
|
152
|
+
rake (>= 12.2)
|
153
|
+
thor (~> 1.0)
|
154
|
+
zeitwerk (~> 2.5)
|
155
|
+
rainbow (3.1.1)
|
156
|
+
rake (13.0.6)
|
157
|
+
regexp_parser (2.4.0)
|
158
|
+
rexml (3.2.5)
|
159
|
+
rspec (3.11.0)
|
160
|
+
rspec-core (~> 3.11.0)
|
161
|
+
rspec-expectations (~> 3.11.0)
|
162
|
+
rspec-mocks (~> 3.11.0)
|
163
|
+
rspec-core (3.11.0)
|
164
|
+
rspec-support (~> 3.11.0)
|
165
|
+
rspec-expectations (3.11.0)
|
166
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
167
|
+
rspec-support (~> 3.11.0)
|
168
|
+
rspec-mocks (3.11.1)
|
169
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
170
|
+
rspec-support (~> 3.11.0)
|
171
|
+
rspec-support (3.11.0)
|
172
|
+
rubocop (1.29.1)
|
173
|
+
parallel (~> 1.10)
|
174
|
+
parser (>= 3.1.0.0)
|
175
|
+
rainbow (>= 2.2.2, < 4.0)
|
176
|
+
regexp_parser (>= 1.8, < 3.0)
|
177
|
+
rexml (>= 3.2.5, < 4.0)
|
178
|
+
rubocop-ast (>= 1.17.0, < 2.0)
|
179
|
+
ruby-progressbar (~> 1.7)
|
180
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
181
|
+
rubocop-ast (1.18.0)
|
182
|
+
parser (>= 3.1.1.0)
|
183
|
+
rubocop-performance (1.13.3)
|
184
|
+
rubocop (>= 1.7.0, < 2.0)
|
185
|
+
rubocop-ast (>= 0.4.0)
|
186
|
+
ruby-progressbar (1.11.0)
|
187
|
+
standard (1.12.1)
|
188
|
+
rubocop (= 1.29.1)
|
189
|
+
rubocop-performance (= 1.13.3)
|
190
|
+
strscan (3.0.3)
|
191
|
+
thor (1.2.1)
|
192
|
+
timeout (0.3.0)
|
193
|
+
typhoeus (1.4.0)
|
194
|
+
ethon (>= 0.9.0)
|
195
|
+
tzinfo (2.0.4)
|
196
|
+
concurrent-ruby (~> 1.0)
|
197
|
+
unicode-display_width (2.1.0)
|
198
|
+
websocket-driver (0.7.5)
|
199
|
+
websocket-extensions (>= 0.1.0)
|
200
|
+
websocket-extensions (0.1.5)
|
201
|
+
zeitwerk (2.5.4)
|
202
|
+
|
203
|
+
PLATFORMS
|
204
|
+
x86_64-darwin-21
|
205
|
+
|
206
|
+
DEPENDENCIES
|
207
|
+
onesignal-rails-plugin!
|
208
|
+
pry
|
209
|
+
rake (~> 13.0.1)
|
210
|
+
rspec
|
211
|
+
rubocop (~> 1.29)
|
212
|
+
standard
|
213
|
+
|
214
|
+
BUNDLED WITH
|
215
|
+
2.2.3
|
data/LICENSE
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
Modified MIT License
|
2
|
+
|
3
|
+
Copyright 2021 OneSignal
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
1. The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
2. All copies of substantial portions of the Software may only be used in connection
|
16
|
+
with services provided by OneSignal.
|
17
|
+
|
18
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
19
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
20
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
21
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
22
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
23
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
24
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,239 @@
|
|
1
|
+
<h1 align="center">Welcome to the official OneSignal Ruby on Rails Plugin 👋</h1>
|
2
|
+
|
3
|
+
[![Gem Version][rgb]][rgl]
|
4
|
+
|
5
|
+
<p>
|
6
|
+
<a href="https://github.com/OneSignal/onesignal-rails-plugin/blob/master/README.md" target="_blank">
|
7
|
+
<img alt="Documentation" src="https://img.shields.io/badge/documentation-yes-brightgreen.svg" />
|
8
|
+
</a>
|
9
|
+
<a href="https://github.com/OneSignal/onesignal-rails-plugin/graphs/commit-activity" target="_blank">
|
10
|
+
<img alt="Maintenance" src="https://img.shields.io/badge/Maintained%3F-yes-green.svg" />
|
11
|
+
</a>
|
12
|
+
<a href="https://twitter.com/onesignal" target="_blank">
|
13
|
+
<img alt="Twitter: onesignal" src="https://img.shields.io/twitter/follow/onesignal.svg?style=social" />
|
14
|
+
</a>
|
15
|
+
</p>
|
16
|
+
|
17
|
+
OneSignal - the Ruby on Rails gem for OneSignal
|
18
|
+
|
19
|
+
A powerful way to send personalized messages at scale and build effective customer engagement strategies. Learn more at onesignal.com
|
20
|
+
|
21
|
+
This gem provides OneSignal integration via the Ruby on Rails ActionMailer. A custom delivery method `:onesignal` can be used to direct
|
22
|
+
your Action Mailers to send emails through the OneSignal API. Additional extensions to the mail functionality are provided to take
|
23
|
+
advantage of OneSignal's customer engagement platform!
|
24
|
+
|
25
|
+
### 🖤 [RubyGems](https://rubygems.org/gems/onesignal-rails-plugin)
|
26
|
+
|
27
|
+
## 🚧 In Beta 🚧
|
28
|
+
|
29
|
+
## Installation
|
30
|
+
|
31
|
+
Add this line to your application's Gemfile:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
gem 'onesignal-rails-plugin', '~> 1.0.0.beta1'
|
35
|
+
```
|
36
|
+
|
37
|
+
And then execute:
|
38
|
+
|
39
|
+
$ bundle
|
40
|
+
|
41
|
+
Or install it yourself as:
|
42
|
+
|
43
|
+
$ gem install onesignal-rails-plugin -pre
|
44
|
+
|
45
|
+
Or install from Github:
|
46
|
+
|
47
|
+
$ gem "onesignal-rails-plugin", '~> 1.0.0.beta1', git: 'git://github.com/OneSignal/onesignal-rails-plugin.git'
|
48
|
+
|
49
|
+
|
50
|
+
## Configuration
|
51
|
+
|
52
|
+
To change all action mailers to target the OneSignal integration, edit `config/application.app` or `config/environments/$ENVIRONMENT.rb` and
|
53
|
+
add/change the following to the ActionMailer configuration
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
config.action_mailer.delivery_method = :onesignal
|
57
|
+
```
|
58
|
+
|
59
|
+
Alternatively a specific ActionMailer can be configured to use the OneSignal delivery method. Within your ActionMailer
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
class MyOneSignalActionMailer < ActionMailer::Base
|
63
|
+
self.delivery_method = :onesignal
|
64
|
+
|
65
|
+
def some_email(params)
|
66
|
+
mail(...)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
The OneSignal-specific configuration information can be set in either environment variables or more dynamically via code. To access your app ID
|
72
|
+
and REST API key, please view the [documentation](https://documentation.onesignal.com/docs/accounts-and-keys).
|
73
|
+
|
74
|
+
Choose one of the following ways to provide your OneSignal-specific configuration:
|
75
|
+
1. [Using Environment Variables](#Using-Environment-Variables)
|
76
|
+
2. [Using Application Configuration](#Using-Application-Configuration)
|
77
|
+
3. [Using ActionMailer Configuration](#Using-ActionMailer-Configuration)
|
78
|
+
|
79
|
+
### Using Environment Variables
|
80
|
+
Ensure the OneSignal environment variables have been set, the `OneSignal::Rails::Plugin` module will pick these up automatically
|
81
|
+
```
|
82
|
+
ONESIGNAL_APP_KEY = 'your-app-key'
|
83
|
+
ONESIGNAL_APP_ID = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
|
84
|
+
```
|
85
|
+
|
86
|
+
### Using Application Configuration
|
87
|
+
The `OneSignal::Rails::Plugin` module can be configured in code by creating initializer file `config/initializers/onesignal_rails_plugin.rb` and adding the following
|
88
|
+
(Warning: for security purposes, REST API keys should not be hardcoded into your application)
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
OneSignal::Rails::Plugin.configure do |c|
|
92
|
+
c.app_key = 'your-app-key'
|
93
|
+
c.app_id = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
|
94
|
+
end
|
95
|
+
```
|
96
|
+
|
97
|
+
### Using ActionMailer Configuration
|
98
|
+
For more granular and dynamic control, you can also configure as part of the ActionMailer configuration. Edit `config/application.app` or
|
99
|
+
`config/environments/$ENVIRONMENT.rb` and add the following to the ActionMailer configuration (Warning: for security purposes, REST API keys should not
|
100
|
+
be hardcoded into your application)
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
config.action_mailer.onesignal_settings = {
|
104
|
+
app_key = 'your-app-key',
|
105
|
+
app_id = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
|
106
|
+
}
|
107
|
+
```
|
108
|
+
|
109
|
+
Similar to how the `delivery_method` is configured, alternatively a specific ActionMailer can be configured to have a more granular configuration. Within your
|
110
|
+
ActionMailer add the following (Warning: for security purposes, REST API keys should not be hardcoded into your application)
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
class MyOneSignalActionMailer < ActionMailer::Base
|
114
|
+
self.delivery_method = :onesignal
|
115
|
+
self.onesignal_settings = {
|
116
|
+
app_key = 'your-app-key',
|
117
|
+
app_id = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
|
118
|
+
}
|
119
|
+
|
120
|
+
def some_email(params)
|
121
|
+
mail(...)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
```
|
125
|
+
|
126
|
+
## Usage
|
127
|
+
If the purpose of the ActionMailer is to generate a transactional email where the recipient, subject, and body are specified within the application,
|
128
|
+
no additional changes are required. Your existing ActionMailers will now send emails through your OneSignal integration!
|
129
|
+
|
130
|
+
## OneSignal Extensions
|
131
|
+
The mail functionality is extended to include additional attributes provided by the OneSignal API. These attributes should be specified within your
|
132
|
+
ActionMailer through the `mail` invocation. See [Examples](#Examples) for examples of how to invoke `mail` to exploit these extensions.
|
133
|
+
|
134
|
+
### template_id (string)
|
135
|
+
Specifies the id of a template created within OneSignal that should be used, rather than the body provided by your application (either via the `body`
|
136
|
+
parameter, or defined within the view of the ActionMailer). To use the subject within the template, specify a `OneSignal::Rails::Plugin::USE_TEMPLATE_SUBJECT` within
|
137
|
+
the `subject` parameter. If the `subject` parameter is set to anything else, it will be used as the subject of the email, overriding the subject within the template.
|
138
|
+
|
139
|
+
### include_external_user_ids (string array)
|
140
|
+
A string array that lists the OneSignal external IDs that are to be the recipients of the email being sent, rather than the information provided by your application via the `to` parameter.
|
141
|
+
|
142
|
+
### include_player_ids (string array)
|
143
|
+
A string array that lists the OneSignal player IDs that are to be the recipients of the email being sent, rather than the information provided by your application via the `to` parameter.
|
144
|
+
|
145
|
+
### included_segments (string array)
|
146
|
+
A string array that lists the OneSignal segments that are to be the recipients of the email being sent, rather than the information provided by your application via the `to` parameter.
|
147
|
+
|
148
|
+
### excluded_segments (string array)
|
149
|
+
A string array that lists the OneSignal segments that will not be the recipients of the email being sent (all others will), rather than the information provided by your application via the `to` parameter.
|
150
|
+
|
151
|
+
### custom_notification_args (object)
|
152
|
+
An object that allows for customizing the email notification that will be sent. Each property key and value of the object will be copied into the payload of the create notification operation.
|
153
|
+
This allows for greater customization of notification being sent. Example of parameters that would most likely be specified within this object:
|
154
|
+
- *external_id:* Correlation and idempotency key.
|
155
|
+
- *send_after:* Schedule the message for future delivery.
|
156
|
+
- *throttle_rate_per_minute:* throttle delivery of the notification, either because throttling is not enabled at the application level or to override the application level throttling settings.
|
157
|
+
|
158
|
+
Note the following are not currently supported by the Ruby API library.
|
159
|
+
- *name:* identifier for tracking this message within the OneSignal dashboard or export analytics, not shown to the end user.
|
160
|
+
- *disable_email_click_tracking:* When true the URLs in the email will not change to link tracking URLs and will stay the same as originally set. Best used for emails containing Universal Links. Defaults to false.
|
161
|
+
|
162
|
+
Note the following are not currently supported by the API backend.
|
163
|
+
- *delayed_option:* Can be `timezone` or `last-active`.
|
164
|
+
- *delivery_time_of_day:* when delayed_option=timezone, this is the time of day to deliver within the timezone.
|
165
|
+
|
166
|
+
## Examples
|
167
|
+
|
168
|
+
The following shows examples of how to invoke the `mail` function within your ActionMailer when integrated with OneSignal. Note the body is not specified as it is assumed to be generated through the view associated
|
169
|
+
to the ActionMailer. This is not an exhaustive list, and different examples could be combined depending on your specific scenario.
|
170
|
+
|
171
|
+
```ruby
|
172
|
+
# Send a transactional email to a specific recipient (standard ActionMailer usage)
|
173
|
+
mail(subject: "email example", from: 'no-reply@company.com', to: 'user@company.co')
|
174
|
+
|
175
|
+
# Send a transactional email, relying on the OneSignal default 'from' address specified within the OneSignal dashboard
|
176
|
+
mail(subject: "use OneSignal default from address example", to: 'user@company.co')
|
177
|
+
|
178
|
+
# Send an email using a OneSignal template as both the subject and body of the email
|
179
|
+
mail(subject: OneSignal::Rails::Plugin::USE_TEMPLATE_SUBJECT, to: 'user@company.co', template_id: '00000000-0000-0000-0000-000000000000')
|
180
|
+
|
181
|
+
# Send an email using a OneSignal template, overriding the subject specified on the template
|
182
|
+
mail(subject: "template subject override example", to: 'user@company.co', template_id: '00000000-0000-0000-0000-000000000000')
|
183
|
+
|
184
|
+
# Send an email to a list of OneSignal users via their external user IDs
|
185
|
+
mail(subject: "external id example", include_external_user_ids: ["User123", "User456"])
|
186
|
+
|
187
|
+
# Send an email to a list of OneSignal users via their player IDs
|
188
|
+
mail(subject: "player id example", include_player_ids: ["00000000-0000-0000-0000-000000000000", "11111111-1111-1111-1111-111111111111"])
|
189
|
+
|
190
|
+
# Send an email to a list of OneSignal users that are within the provided segments
|
191
|
+
mail(subject: "include segments example", included_segments: ["Subscribed Users"])
|
192
|
+
|
193
|
+
# Send an email to the app's audience, excluding the provided segments.
|
194
|
+
mail(subject: "excluded segments example", excluded_segments: ["Engaged Users"])
|
195
|
+
|
196
|
+
# Send an email with the external_id, which ensures idempotency
|
197
|
+
mail(subject: "set external_id example", to: 'user@company.co', custom_notification_args: { 'external_id' => "00000000-0000-0000-0000-000000000000" })
|
198
|
+
|
199
|
+
# Send an email after a certain time
|
200
|
+
mail(subject: "send after example", to: 'user@company.co', custom_notification_args: { 'send_after' => "2022-05-19 15:20:00 GMT-0400" })
|
201
|
+
|
202
|
+
# Send an email with rate throttling
|
203
|
+
mail(subject: "throttle rate example", to: 'user@company.co', custom_notification_args: { 'throttle_rate_per_minute' => 1 })
|
204
|
+
```
|
205
|
+
|
206
|
+
## Testing
|
207
|
+
|
208
|
+
To run the rspec tests
|
209
|
+
|
210
|
+
$ bundle exec rspec --format documentation
|
211
|
+
|
212
|
+
|
213
|
+
## License
|
214
|
+
|
215
|
+
The gem is available as open source under the terms of the [MIT License][mit].
|
216
|
+
|
217
|
+
[rgb]: https://img.shields.io/gem/v/onesignal-rails-plugin.svg
|
218
|
+
[rgl]: https://rubygems.org/gems/onesignal-rails-plugin
|
219
|
+
[osa]: https://documentation.onesignal.com/reference/
|
220
|
+
[mit]: http://opensource.org/licenses/MIT
|
221
|
+
|
222
|
+
## Author
|
223
|
+
|
224
|
+
* Website: https://onesignal.com
|
225
|
+
* Twitter: [@onesignal](https://twitter.com/onesignal)
|
226
|
+
* Github: [@OneSignal](https://github.com/OneSignal)
|
227
|
+
|
228
|
+
## 🤝 Contributing
|
229
|
+
|
230
|
+
Contributions, issues and feature requests are welcome!<br />Feel free to check [issues page](https://github.com/OneSignal/onesignal-rail-plugin/issues).
|
231
|
+
|
232
|
+
## Show your support
|
233
|
+
|
234
|
+
Give a ⭐️ if this project helped you!
|
235
|
+
|
236
|
+
## 📝 License
|
237
|
+
|
238
|
+
Copyright © 2022 [OneSignal](https://github.com/OneSignal).<br />
|
239
|
+
This project is [MIT](https://opensource.org/licenses/MIT) licensed.
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OneSignal
|
4
|
+
module Rails
|
5
|
+
module Plugin
|
6
|
+
##
|
7
|
+
# Provides a custom exception for when OneSignal is unable to deliver a mail.
|
8
|
+
class DeliveryError < StandardError
|
9
|
+
# The response from the OneSignal API, if a response exists.
|
10
|
+
attr_reader :response
|
11
|
+
|
12
|
+
def initialize(msg = 'OneSignal Delivery Error', response = nil)
|
13
|
+
@response = response
|
14
|
+
super(msg)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'onesignal'
|
4
|
+
|
5
|
+
module OneSignal
|
6
|
+
module Rails
|
7
|
+
module Plugin
|
8
|
+
##
|
9
|
+
# Provides the ActionMailer delivery method of :onesignal. When this delivery method is used,
|
10
|
+
# mail sent by an ActionMailer is sent to OneSignal through an email notification. Alternatively
|
11
|
+
# or in addition to the standard mail funcitonality, additional OneSignal specific parameters
|
12
|
+
# can be specified to take advantage of OneSignal specific functionality.
|
13
|
+
class DeliveryMethod
|
14
|
+
DEFAULTS = {
|
15
|
+
perform_send_request: true,
|
16
|
+
return_response: false,
|
17
|
+
app_key: nil,
|
18
|
+
app_id: nil
|
19
|
+
}.freeze
|
20
|
+
|
21
|
+
attr_accessor :settings
|
22
|
+
|
23
|
+
def initialize(settings = {})
|
24
|
+
self.settings = DEFAULTS.merge(settings)
|
25
|
+
end
|
26
|
+
|
27
|
+
def deliver!(mail)
|
28
|
+
validate(mail)
|
29
|
+
|
30
|
+
notification = OneSignal::Notification.new({ app_id: settings[:app_id] || OneSignal::Rails::Plugin.configuration.app_id,
|
31
|
+
is_ios: false })
|
32
|
+
|
33
|
+
add_from(notification, mail)
|
34
|
+
add_to(notification, mail)
|
35
|
+
add_subject(notification, mail)
|
36
|
+
add_body(notification, mail)
|
37
|
+
add_custom_notification_args(notification, mail)
|
38
|
+
|
39
|
+
response = if settings[:perform_send_request] == false
|
40
|
+
notification
|
41
|
+
else
|
42
|
+
send notification
|
43
|
+
end
|
44
|
+
|
45
|
+
settings[:return_response] ? response : self
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def validate(mail)
|
51
|
+
# subject cannot be USE_TEMPLATE_SUBJECT unless template_id is specified (templates provide the subject)
|
52
|
+
if (mail.subject == USE_TEMPLATE_SUBJECT) && !mail['template_id']
|
53
|
+
raise 'Must specify template_id if setting subject to OneSignal::Rails::Plugin::USE_TEMPLATE_SUBJECT!'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def add_from(notification, mail)
|
58
|
+
from_email = first_email(mail.from)
|
59
|
+
|
60
|
+
notification.email_from_address = from_email.address if from_email&.address
|
61
|
+
notification.email_from_name = from_email.display_name || from_email.name if from_email&.address
|
62
|
+
end
|
63
|
+
|
64
|
+
def add_to(notification, mail)
|
65
|
+
# a specified "to override" takes priority over any "to" provided within the mail input
|
66
|
+
if does_override_to(mail)
|
67
|
+
if mail['include_external_user_ids']
|
68
|
+
notification.include_external_user_ids = mail['include_external_user_ids'].value.split(',').map(&:strip)
|
69
|
+
notification.channel_for_external_user_ids = 'email'
|
70
|
+
end
|
71
|
+
if mail['include_player_ids']
|
72
|
+
notification.include_player_ids = mail['include_player_ids'].value.split(',').map(&:strip)
|
73
|
+
end
|
74
|
+
if mail['included_segments']
|
75
|
+
notification.included_segments = mail['included_segments'].value.split(',').map(&:strip)
|
76
|
+
end
|
77
|
+
if mail['excluded_segments']
|
78
|
+
notification.excluded_segments = mail['excluded_segments'].value.split(',').map(&:strip)
|
79
|
+
end
|
80
|
+
else
|
81
|
+
notification.include_email_tokens = mail.to
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def does_override_to(mail)
|
86
|
+
mail['include_external_user_ids'] ||
|
87
|
+
mail['include_player_ids'] ||
|
88
|
+
mail['included_segments'] ||
|
89
|
+
mail['excluded_segments']
|
90
|
+
end
|
91
|
+
|
92
|
+
def add_subject(notification, mail)
|
93
|
+
notification.email_subject = mail.subject if mail.subject != USE_TEMPLATE_SUBJECT
|
94
|
+
end
|
95
|
+
|
96
|
+
def add_body(notification, mail)
|
97
|
+
# a specified template takes priority over any body provided within the mail
|
98
|
+
if mail['template_id']
|
99
|
+
notification.template_id = mail['template_id'].value
|
100
|
+
else
|
101
|
+
case mail.mime_type
|
102
|
+
when 'text/plain', 'text/html'
|
103
|
+
notification.email_body = mail.body.decoded
|
104
|
+
when 'multipart/alternative', 'multipart/mixed', 'multipart/related'
|
105
|
+
# for multipart, the html will always win if it exists
|
106
|
+
notification.email_body = mail.text_part.decoded if mail.text_part
|
107
|
+
notification.email_body = mail.html_part.decoded if mail.html_part
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def add_custom_notification_args(notification, mail)
|
113
|
+
input = mail['custom_notification_args']
|
114
|
+
if input.is_a?(Mail::Field)
|
115
|
+
input.unparsed_value.each do |key, value|
|
116
|
+
notification.send("#{key}=", value)
|
117
|
+
end
|
118
|
+
elsif input.respond_to?('each')
|
119
|
+
input.each do |item|
|
120
|
+
item.unparsed_value.each do |key, value|
|
121
|
+
notification.send("#{key}=", value)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
elsif input
|
125
|
+
raise DeliveryError, "Unknown type for customer_notification_args: #{input.class.name}"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def first_email(input)
|
130
|
+
convert_emails(input).first
|
131
|
+
end
|
132
|
+
|
133
|
+
def convert_emails(input)
|
134
|
+
if input.is_a?(String)
|
135
|
+
[Mail::Address.new(input)]
|
136
|
+
elsif input.is_a?(::Mail::AddressContainer) && !input.instance_variable_get('@field').nil?
|
137
|
+
input.instance_variable_get('@field').addrs.map # Already Mail::Address
|
138
|
+
elsif input.is_a?(::Mail::AddressContainer)
|
139
|
+
input.map do |addr|
|
140
|
+
Mail::Address.new(addr)
|
141
|
+
end
|
142
|
+
elsif input.is_a?(::Mail::StructuredField)
|
143
|
+
[Mail::Address.new(input.value)]
|
144
|
+
elsif input.nil?
|
145
|
+
[]
|
146
|
+
else
|
147
|
+
raise OneSignalDeliveryError, "Unknown type for email: #{input.class.name}"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def client
|
152
|
+
# we create our own configuration in case the OneSignal library is used outside of the
|
153
|
+
# ActionMailer context, with different options
|
154
|
+
config = OneSignal::Configuration.new
|
155
|
+
config.configure do |c|
|
156
|
+
c.app_key = settings[:app_key] || OneSignal::Rails::Plugin.configuration.app_key
|
157
|
+
end
|
158
|
+
|
159
|
+
OneSignal::DefaultApi.new(OneSignal::ApiClient.new(config))
|
160
|
+
end
|
161
|
+
|
162
|
+
def send(notification)
|
163
|
+
response = client.create_notification(notification)
|
164
|
+
|
165
|
+
raise DeliveryError.new('OneSignal request responded with errors', response) if response.errors
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OneSignal
|
4
|
+
module Rails
|
5
|
+
module Plugin
|
6
|
+
##
|
7
|
+
# The One Signal Rails Extension class
|
8
|
+
class Railtie < ::Rails::Railtie
|
9
|
+
# Add the :onesignal delivery method to the ActionMailer framework
|
10
|
+
initializer 'onesignal_rails_plugin.add_delivery_method', before: 'action_mailer.set_configs' do
|
11
|
+
ActiveSupport.on_load(:action_mailer) do
|
12
|
+
ActionMailer::Base.add_delivery_method(:onesignal, OneSignal::Rails::Plugin::DeliveryMethod)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'onesignal/rails/plugin/delivery_method'
|
4
|
+
require 'onesignal/rails/plugin/delivery_error'
|
5
|
+
require 'onesignal/rails/plugin/literals'
|
6
|
+
require 'onesignal/rails/plugin/railtie'
|
7
|
+
require 'onesignal/rails/plugin/version'
|
8
|
+
|
9
|
+
##
|
10
|
+
# This module contains all classes provided by the OneSignal Rails plugin.
|
11
|
+
module OneSignal
|
12
|
+
module Rails
|
13
|
+
class << self
|
14
|
+
# This is required because other gems in the OneSignal module namespace
|
15
|
+
# specifically use `Rails.logger` thinking they are picking up the
|
16
|
+
# Rails logger. So we proxy that for them.
|
17
|
+
def logger
|
18
|
+
::Rails.logger
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
module Plugin
|
23
|
+
class << self
|
24
|
+
attr_writer :configuration
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.configuration
|
28
|
+
@configuration ||= Configuration.new
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.configure
|
32
|
+
self.configuration ||= Configuration.new
|
33
|
+
yield(configuration)
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
# Configuration options for the OneSignal plugin.
|
38
|
+
class Configuration
|
39
|
+
attr_accessor :app_key, :app_id
|
40
|
+
|
41
|
+
def initialize
|
42
|
+
set_defaults
|
43
|
+
end
|
44
|
+
|
45
|
+
def set_defaults
|
46
|
+
@app_key = if ENV.key?('ONESIGNAL_APP_KEY')
|
47
|
+
ENV['ONESIGNAL_APP_KEY']
|
48
|
+
else
|
49
|
+
''
|
50
|
+
end
|
51
|
+
|
52
|
+
@app_id = if ENV.key?('ONESIGNAL_APP_ID')
|
53
|
+
ENV['ONESIGNAL_APP_ID']
|
54
|
+
else
|
55
|
+
''
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# #OneSignal
|
4
|
+
#
|
5
|
+
# A powerful way to send personalized messages at scale and build effective customer
|
6
|
+
# engagement strategies. Learn more at onesignal.com.
|
7
|
+
#
|
8
|
+
# Contact: devrel@onesignal.com
|
9
|
+
#
|
10
|
+
|
11
|
+
$LOAD_PATH.push File.expand_path('lib', __dir__)
|
12
|
+
require 'onesignal/rails/plugin/version'
|
13
|
+
|
14
|
+
Gem::Specification.new do |s|
|
15
|
+
s.name = 'onesignal-rails-plugin'
|
16
|
+
s.version = OneSignal::Rails::Plugin::VERSION
|
17
|
+
s.platform = Gem::Platform::RUBY
|
18
|
+
s.authors = ['OneSignal']
|
19
|
+
s.email = ['devrel@onesignal.com']
|
20
|
+
s.homepage = 'https://onesignal.com/'
|
21
|
+
s.summary = 'OneSignal for Rails'
|
22
|
+
s.description = 'A custom Rails ActionMailer delivery method which will send emails through your OneSignal integration'
|
23
|
+
s.license = 'Modified MIT'
|
24
|
+
s.required_ruby_version = '>= 2.5'
|
25
|
+
|
26
|
+
s.add_dependency 'onesignal', '~> 1.0.1'
|
27
|
+
s.add_dependency 'rails'
|
28
|
+
|
29
|
+
s.add_development_dependency 'rake'
|
30
|
+
s.add_development_dependency 'rspec'
|
31
|
+
|
32
|
+
s.files = `find *`.split("\n").uniq.sort.reject(&:empty?)
|
33
|
+
s.test_files = `find spec/*`.split("\n")
|
34
|
+
s.executables = []
|
35
|
+
s.require_paths = ['lib']
|
36
|
+
end
|
@@ -0,0 +1,308 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../../../spec_helper'
|
4
|
+
require 'mail'
|
5
|
+
|
6
|
+
module OneSignal
|
7
|
+
module Rails
|
8
|
+
module Plugin
|
9
|
+
EMAIL_TEXT_BODY = 'I am a plain text body'
|
10
|
+
EMAIL_HTML_BODY = 'I am an <b>HTML</b> body'
|
11
|
+
ALT_APP_ID = '11111111-1111-1111-1111-111111111111'
|
12
|
+
ALT_APP_KEY = 'ALT_APP_KEY'
|
13
|
+
|
14
|
+
describe 'DeliveryMethod' do
|
15
|
+
subject(:mailer) do
|
16
|
+
DeliveryMethod.new(perform_send_request: false, return_response: true)
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'initializing' do
|
20
|
+
it 'defaults return_response to false' do
|
21
|
+
m = DeliveryMethod.new
|
22
|
+
expect(m.settings[:return_response]).to eq(false)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'defaults perform_send_request to true' do
|
26
|
+
m = DeliveryMethod.new
|
27
|
+
expect(m.settings[:perform_send_request]).to eq(true)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'defaults app_id to nil' do
|
31
|
+
m = DeliveryMethod.new
|
32
|
+
expect(m.settings[:app_id]).to be_nil
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'defaults app_key to nil' do
|
36
|
+
m = DeliveryMethod.new
|
37
|
+
expect(m.settings[:app_key]).to be_nil
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'allows setting of return_response to true' do
|
41
|
+
m = DeliveryMethod.new(return_response: true)
|
42
|
+
expect(m.settings[:return_response]).to eq(true)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'allows setting of app_id to a value' do
|
46
|
+
m = DeliveryMethod.new(app_id: ALT_APP_ID)
|
47
|
+
expect(m.settings[:app_id]).to eq(ALT_APP_ID)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'allows setting of app_key to a value' do
|
51
|
+
m = DeliveryMethod.new(app_key: ALT_APP_KEY)
|
52
|
+
expect(m.settings[:app_key]).to eq(ALT_APP_KEY)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#deliver!' do
|
57
|
+
let(:mail) do
|
58
|
+
Mail.new(
|
59
|
+
to: 'test@example.com',
|
60
|
+
from: 'test@company.co',
|
61
|
+
subject: 'Hello Test!'
|
62
|
+
)
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'when using initialization' do
|
66
|
+
it 'returns mailer itself' do
|
67
|
+
m = DeliveryMethod.new(perform_send_request: false)
|
68
|
+
ret = m.deliver!(mail)
|
69
|
+
expect(ret).to eq(m)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'captures app id in notification from configuration' do
|
73
|
+
notification = mailer.deliver!(mail)
|
74
|
+
expect(notification.app_id).to eq(APP_ID)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'uses app id from configuration when set' do
|
78
|
+
m = DeliveryMethod.new(app_id: ALT_APP_ID, perform_send_request: false, return_response: true)
|
79
|
+
notification = m.deliver!(mail)
|
80
|
+
expect(notification.app_id).to eq(ALT_APP_ID)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'when sending email to' do
|
85
|
+
it 'supports single email address' do
|
86
|
+
notification = mailer.deliver!(mail)
|
87
|
+
expect(notification.include_email_tokens).to eq ['test@example.com']
|
88
|
+
end
|
89
|
+
it 'supports single email address with name' do
|
90
|
+
mail.to = 'Test Person <test@example.com>'
|
91
|
+
notification = mailer.deliver!(mail)
|
92
|
+
expect(notification.include_email_tokens).to eq ['test@example.com']
|
93
|
+
end
|
94
|
+
it 'supports single email address with quoted name' do
|
95
|
+
mail.to = '"Test Person" <test@example.com>'
|
96
|
+
notification = mailer.deliver!(mail)
|
97
|
+
expect(notification.include_email_tokens).to eq ['test@example.com']
|
98
|
+
end
|
99
|
+
it 'supports multiple email addresses' do
|
100
|
+
mail.to = 'test1@example.com;test2@example.com'
|
101
|
+
notification = mailer.deliver!(mail)
|
102
|
+
expect(notification.include_email_tokens).to eq ['test1@example.com', 'test2@example.com']
|
103
|
+
end
|
104
|
+
it 'supports multiple email addresses with names' do
|
105
|
+
mail.to = 'Test1 Person <test1@example.com>; Test2 Person <test2@example.com>'
|
106
|
+
notification = mailer.deliver!(mail)
|
107
|
+
expect(notification.include_email_tokens).to eq ['test1@example.com', 'test2@example.com']
|
108
|
+
end
|
109
|
+
it 'supports multiple email addresses with quoted names' do
|
110
|
+
mail.to = '"Test1 Person" <test1@example.com>; "Test2 Person" <test2@example.com>'
|
111
|
+
notification = mailer.deliver!(mail)
|
112
|
+
expect(notification.include_email_tokens).to eq ['test1@example.com', 'test2@example.com']
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context 'when sending email from' do
|
117
|
+
it 'supports not setting from' do
|
118
|
+
mail.from = nil
|
119
|
+
notification = mailer.deliver!(mail)
|
120
|
+
expect(notification.email_from_address).to be_nil
|
121
|
+
expect(notification.email_from_name).to be_nil
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'supports email address' do
|
125
|
+
notification = mailer.deliver!(mail)
|
126
|
+
expect(notification.email_from_address).to eq('test@company.co')
|
127
|
+
expect(notification.email_from_name).to be_nil
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'supports email address with name' do
|
131
|
+
mail.from = 'Test Person <test@company.co>'
|
132
|
+
notification = mailer.deliver!(mail)
|
133
|
+
expect(notification.email_from_address).to eq('test@company.co')
|
134
|
+
expect(notification.email_from_name).to eq('Test Person')
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'supports email address with quoted name' do
|
138
|
+
mail.from = '"Test Person" <test@company.co>'
|
139
|
+
notification = mailer.deliver!(mail)
|
140
|
+
expect(notification.email_from_address).to eq('test@company.co')
|
141
|
+
expect(notification.email_from_name).to eq('Test Person')
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'ignores all but first email address' do
|
145
|
+
mail.from = 'test1@company.co;test2@company.co'
|
146
|
+
notification = mailer.deliver!(mail)
|
147
|
+
expect(notification.email_from_address).to eq('test1@company.co')
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
context 'when sending email subject' do
|
152
|
+
it 'supports subject' do
|
153
|
+
notification = mailer.deliver!(mail)
|
154
|
+
expect(notification.email_subject).to eq('Hello Test!')
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'fails if told not to provide subject but no template is used' do
|
158
|
+
mail.subject = OneSignal::Rails::Plugin::USE_TEMPLATE_SUBJECT
|
159
|
+
expect do
|
160
|
+
mailer.deliver!(mail)
|
161
|
+
end.to raise_exception('Must specify template_id if setting subject to OneSignal::Rails::Plugin::USE_TEMPLATE_SUBJECT!')
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
context 'when sending email body' do
|
166
|
+
it 'supports body with text/plain content' do
|
167
|
+
mail.content_type = 'text/plain'
|
168
|
+
mail.body = EMAIL_TEXT_BODY
|
169
|
+
notification = mailer.deliver!(mail)
|
170
|
+
expect(notification.email_body).to eq(EMAIL_TEXT_BODY)
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'supports body with text/html content' do
|
174
|
+
mail.content_type = 'text/html'
|
175
|
+
mail.body = EMAIL_HTML_BODY
|
176
|
+
notification = mailer.deliver!(mail)
|
177
|
+
expect(notification.email_body).to eq(EMAIL_HTML_BODY)
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'chooses text/html body with both text/html and text/plain content' do
|
181
|
+
mail.content_type = 'multipart/mixed'
|
182
|
+
mail.part do |p|
|
183
|
+
p.html_part = Mail::Part.new do
|
184
|
+
content_type 'text/html'
|
185
|
+
body EMAIL_HTML_BODY
|
186
|
+
end
|
187
|
+
p.text_part = Mail::Part.new do
|
188
|
+
content_type 'text/plain'
|
189
|
+
body EMAIL_TEXT_BODY
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
notification = mailer.deliver!(mail)
|
194
|
+
expect(notification.email_body).to eq(EMAIL_HTML_BODY)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
context 'when sending email template' do
|
199
|
+
before do
|
200
|
+
mail['template_id'] = '1'
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'sets template_id with value' do
|
204
|
+
notification = mailer.deliver!(mail)
|
205
|
+
expect(notification.template_id).to eq('1')
|
206
|
+
end
|
207
|
+
|
208
|
+
it 'sets subject if specified' do
|
209
|
+
notification = mailer.deliver!(mail)
|
210
|
+
expect(notification.email_subject).to eq('Hello Test!')
|
211
|
+
end
|
212
|
+
|
213
|
+
it 'ignores subject when told to not use it' do
|
214
|
+
mail.subject = OneSignal::Rails::Plugin::USE_TEMPLATE_SUBJECT
|
215
|
+
notification = mailer.deliver!(mail)
|
216
|
+
expect(notification.email_subject).to be_nil
|
217
|
+
end
|
218
|
+
|
219
|
+
it 'ignores body if specified' do
|
220
|
+
mail.content_type = 'text/plain'
|
221
|
+
mail.body = EMAIL_TEXT_BODY
|
222
|
+
notification = mailer.deliver!(mail)
|
223
|
+
expect(notification.email_body).to be_nil
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
context 'when sending email to existing OneSignal users via extensions' do
|
228
|
+
it 'supports include_external_user_ids' do
|
229
|
+
mail['include_external_user_ids'] = %w[1 2 3]
|
230
|
+
notification = mailer.deliver!(mail)
|
231
|
+
expect(notification.include_external_user_ids).to eq(%w[1 2 3])
|
232
|
+
expect(notification.channel_for_external_user_ids).to eq('email')
|
233
|
+
expect(notification.include_email_tokens).to be_nil
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'supports include_player_ids' do
|
237
|
+
mail['include_player_ids'] = %w[1 2 3]
|
238
|
+
notification = mailer.deliver!(mail)
|
239
|
+
expect(notification.include_player_ids).to eq(%w[1 2 3])
|
240
|
+
expect(notification.include_email_tokens).to be_nil
|
241
|
+
end
|
242
|
+
|
243
|
+
it 'supports included_segments' do
|
244
|
+
mail['included_segments'] = %w[1 2 3]
|
245
|
+
notification = mailer.deliver!(mail)
|
246
|
+
expect(notification.included_segments).to eq(%w[1 2 3])
|
247
|
+
expect(notification.include_email_tokens).to be_nil
|
248
|
+
end
|
249
|
+
|
250
|
+
it 'supports excluded_segments' do
|
251
|
+
mail['excluded_segments'] = %w[1 2 3]
|
252
|
+
notification = mailer.deliver!(mail)
|
253
|
+
expect(notification.excluded_segments).to eq(%w[1 2 3])
|
254
|
+
expect(notification.include_email_tokens).to be_nil
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
context 'when sending email with custom_notification_args extensions' do
|
259
|
+
# TODO: These properties exist in the API, but not in the Ruby client yet
|
260
|
+
# it 'supports name' do
|
261
|
+
# mail['custom_notification_args'] = {'name' => 'Test'}
|
262
|
+
# notification = mailer.deliver!(mail)
|
263
|
+
# expect(notification.name).to eq("Test")
|
264
|
+
# end
|
265
|
+
# it 'supports disable_email_click_tracking' do
|
266
|
+
# mail['custom_notification_args'] = {'disable_email_click_tracking' => true}
|
267
|
+
# notification = mailer.deliver!(mail)
|
268
|
+
# expect(notification.disable_email_click_tracking).to eq(true)
|
269
|
+
# end
|
270
|
+
|
271
|
+
it 'supports external_id' do
|
272
|
+
mail['custom_notification_args'] = { 'external_id' => 'Test' }
|
273
|
+
notification = mailer.deliver!(mail)
|
274
|
+
expect(notification.external_id).to eq('Test')
|
275
|
+
end
|
276
|
+
|
277
|
+
it 'supports send_after' do
|
278
|
+
mail['custom_notification_args'] = { 'send_after' => 'Thu Sep 24 2015 14:00:00 GMT-0700 (PDT)' }
|
279
|
+
notification = mailer.deliver!(mail)
|
280
|
+
expect(notification.send_after).to eq('Thu Sep 24 2015 14:00:00 GMT-0700 (PDT)')
|
281
|
+
end
|
282
|
+
|
283
|
+
# NOTE: Though this is supported by the API, Email time of day is not currently supported by the backend
|
284
|
+
it 'supports time of day delivery' do
|
285
|
+
mail['custom_notification_args'] = { 'delayed_option' => 'timezone', 'delivery_time_of_day' => '9:00AM' }
|
286
|
+
notification = mailer.deliver!(mail)
|
287
|
+
expect(notification.delayed_option).to eq('timezone')
|
288
|
+
expect(notification.delivery_time_of_day).to eq('9:00AM')
|
289
|
+
end
|
290
|
+
|
291
|
+
# NOTE: Though this is supported by the API, Email time of day is not currently supported by the backend
|
292
|
+
it 'supports last active delivery' do
|
293
|
+
mail['custom_notification_args'] = { 'delayed_option' => 'last-active' }
|
294
|
+
notification = mailer.deliver!(mail)
|
295
|
+
expect(notification.delayed_option).to eq('last-active')
|
296
|
+
end
|
297
|
+
|
298
|
+
it 'supports throttle_rate_per_minute' do
|
299
|
+
mail['custom_notification_args'] = { 'throttle_rate_per_minute' => 4 }
|
300
|
+
notification = mailer.deliver!(mail)
|
301
|
+
expect(notification.throttle_rate_per_minute).to eq(4)
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails'
|
4
|
+
require_relative '../lib/onesignal/rails/plugin'
|
5
|
+
|
6
|
+
APP_KEY = 'TEST_API_KEY'
|
7
|
+
APP_ID = '00000000-0000-0000-0000-000000000000'
|
8
|
+
|
9
|
+
RSpec.configure do |config|
|
10
|
+
config.before(:each) do |_example|
|
11
|
+
OneSignal::Rails::Plugin.configure do |c|
|
12
|
+
c.app_key = APP_KEY
|
13
|
+
c.app_id = APP_ID
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
config.expect_with :rspec do |expectations|
|
18
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
19
|
+
end
|
20
|
+
|
21
|
+
config.mock_with :rspec do |mocks|
|
22
|
+
mocks.verify_partial_doubles = true
|
23
|
+
end
|
24
|
+
|
25
|
+
config.shared_context_metadata_behavior = :apply_to_host_groups
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: onesignal-rails-plugin
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- OneSignal
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-06-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: onesignal
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.0.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.0.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rails
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: A custom Rails ActionMailer delivery method which will send emails through
|
70
|
+
your OneSignal integration
|
71
|
+
email:
|
72
|
+
- devrel@onesignal.com
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- Gemfile
|
78
|
+
- Gemfile.lock
|
79
|
+
- LICENSE
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- lib/onesignal/rails/plugin.rb
|
83
|
+
- lib/onesignal/rails/plugin/delivery_error.rb
|
84
|
+
- lib/onesignal/rails/plugin/delivery_method.rb
|
85
|
+
- lib/onesignal/rails/plugin/literals.rb
|
86
|
+
- lib/onesignal/rails/plugin/railtie.rb
|
87
|
+
- lib/onesignal/rails/plugin/version.rb
|
88
|
+
- onesignal-rails-plugin.gemspec
|
89
|
+
- spec/lib/onesignal/rails/plugin/delivery_method_spec.rb
|
90
|
+
- spec/spec_helper.rb
|
91
|
+
homepage: https://onesignal.com/
|
92
|
+
licenses:
|
93
|
+
- Modified MIT
|
94
|
+
metadata: {}
|
95
|
+
post_install_message:
|
96
|
+
rdoc_options: []
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '2.5'
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
requirements: []
|
110
|
+
rubygems_version: 3.2.3
|
111
|
+
signing_key:
|
112
|
+
specification_version: 4
|
113
|
+
summary: OneSignal for Rails
|
114
|
+
test_files:
|
115
|
+
- spec/lib/onesignal/rails/plugin/delivery_method_spec.rb
|
116
|
+
- spec/spec_helper.rb
|