send_grid_mailer 1.1.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +102 -0
- data/.circleci/setup-rubygems.sh +3 -0
- data/.rubocop.yml +31 -591
- data/.ruby-version +1 -1
- data/CHANGELOG.md +28 -0
- data/README.md +46 -2
- data/lib/send_grid_mailer/api.rb +14 -9
- data/lib/send_grid_mailer/definition.rb +32 -14
- data/lib/send_grid_mailer/dev_deliverer.rb +72 -0
- data/lib/send_grid_mailer/engine.rb +4 -2
- data/lib/send_grid_mailer/logger.rb +10 -5
- data/lib/send_grid_mailer/mailer_base_ext.rb +13 -2
- data/lib/send_grid_mailer/version.rb +1 -1
- data/send_grid_mailer.gemspec +12 -6
- data/spec/dummy/Rakefile +1 -1
- data/spec/dummy/app/assets/config/manifest.js +3 -0
- data/spec/dummy/app/assets/stylesheets/application.css +3 -3
- data/spec/dummy/app/channels/application_cable/channel.rb +4 -0
- data/spec/dummy/app/channels/application_cable/connection.rb +4 -0
- data/spec/dummy/app/controllers/application_controller.rb +0 -3
- data/spec/dummy/app/{assets/javascripts → javascript/packs}/application.js +3 -1
- data/spec/dummy/app/jobs/application_job.rb +7 -0
- data/spec/dummy/app/mailers/application_mailer.rb +1 -1
- data/spec/dummy/app/mailers/test_mailer.rb +12 -0
- data/spec/dummy/app/models/application_record.rb +3 -0
- data/spec/dummy/app/views/layouts/application.html.erb +10 -9
- data/spec/dummy/bin/rails +3 -3
- data/spec/dummy/bin/rake +2 -2
- data/spec/dummy/bin/setup +18 -14
- data/spec/dummy/config/application.rb +12 -22
- data/spec/dummy/config/boot.rb +3 -3
- data/spec/dummy/config/cable.yml +10 -0
- data/spec/dummy/config/database.yml +2 -2
- data/spec/dummy/config/environment.rb +1 -1
- data/spec/dummy/config/environments/development.rb +48 -18
- data/spec/dummy/config/environments/production.rb +63 -22
- data/spec/dummy/config/environments/test.rb +29 -12
- data/spec/dummy/config/initializers/application_controller_renderer.rb +8 -0
- data/spec/dummy/config/initializers/assets.rb +4 -3
- data/spec/dummy/config/initializers/backtrace_silencers.rb +4 -3
- data/spec/dummy/config/initializers/content_security_policy.rb +28 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +2 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +3 -1
- data/spec/dummy/config/initializers/permissions_policy.rb +11 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +2 -2
- data/spec/dummy/config/locales/en.yml +11 -1
- data/spec/dummy/config/puma.rb +43 -0
- data/spec/dummy/config/routes.rb +1 -54
- data/spec/dummy/config/storage.yml +34 -0
- data/spec/dummy/config.ru +3 -1
- data/spec/dummy/public/404.html +6 -6
- data/spec/dummy/public/422.html +6 -6
- data/spec/dummy/public/500.html +6 -6
- data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
- data/spec/dummy/public/apple-touch-icon.png +0 -0
- data/spec/dummy/spec/lib/send_grid_mailer/definition_spec.rb +52 -23
- data/spec/dummy/spec/mailers/test_mailer_spec.rb +547 -384
- data/spec/rails_helper.rb +5 -7
- metadata +124 -38
- data/.hound.yml +0 -4
- data/.travis.yml +0 -15
- data/spec/dummy/bin/bundle +0 -3
- data/spec/dummy/config/initializers/session_store.rb +0 -3
- data/spec/dummy/config/secrets.yml +0 -22
- data/spec/dummy/db/schema.rb +0 -16
- data/spec/dummy/spec/support/test_helpers.rb +0 -5
data/spec/dummy/config/routes.rb
CHANGED
@@ -1,56 +1,3 @@
|
|
1
1
|
Rails.application.routes.draw do
|
2
|
-
|
3
|
-
# See how all your routes lay out with "rake routes".
|
4
|
-
|
5
|
-
# You can have the root of your site routed with "root"
|
6
|
-
# root 'welcome#index'
|
7
|
-
|
8
|
-
# Example of regular route:
|
9
|
-
# get 'products/:id' => 'catalog#view'
|
10
|
-
|
11
|
-
# Example of named route that can be invoked with purchase_url(id: product.id)
|
12
|
-
# get 'products/:id/purchase' => 'catalog#purchase', as: :purchase
|
13
|
-
|
14
|
-
# Example resource route (maps HTTP verbs to controller actions automatically):
|
15
|
-
# resources :products
|
16
|
-
|
17
|
-
# Example resource route with options:
|
18
|
-
# resources :products do
|
19
|
-
# member do
|
20
|
-
# get 'short'
|
21
|
-
# post 'toggle'
|
22
|
-
# end
|
23
|
-
#
|
24
|
-
# collection do
|
25
|
-
# get 'sold'
|
26
|
-
# end
|
27
|
-
# end
|
28
|
-
|
29
|
-
# Example resource route with sub-resources:
|
30
|
-
# resources :products do
|
31
|
-
# resources :comments, :sales
|
32
|
-
# resource :seller
|
33
|
-
# end
|
34
|
-
|
35
|
-
# Example resource route with more complex sub-resources:
|
36
|
-
# resources :products do
|
37
|
-
# resources :comments
|
38
|
-
# resources :sales do
|
39
|
-
# get 'recent', on: :collection
|
40
|
-
# end
|
41
|
-
# end
|
42
|
-
|
43
|
-
# Example resource route with concerns:
|
44
|
-
# concern :toggleable do
|
45
|
-
# post 'toggle'
|
46
|
-
# end
|
47
|
-
# resources :posts, concerns: :toggleable
|
48
|
-
# resources :photos, concerns: :toggleable
|
49
|
-
|
50
|
-
# Example resource route within a namespace:
|
51
|
-
# namespace :admin do
|
52
|
-
# # Directs /admin/products/* to Admin::ProductsController
|
53
|
-
# # (app/controllers/admin/products_controller.rb)
|
54
|
-
# resources :products
|
55
|
-
# end
|
2
|
+
mount SendGridMailer::Engine => "/send_grid_mailer"
|
56
3
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
test:
|
2
|
+
service: Disk
|
3
|
+
root: <%= Rails.root.join("tmp/storage") %>
|
4
|
+
|
5
|
+
local:
|
6
|
+
service: Disk
|
7
|
+
root: <%= Rails.root.join("storage") %>
|
8
|
+
|
9
|
+
# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
|
10
|
+
# amazon:
|
11
|
+
# service: S3
|
12
|
+
# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
|
13
|
+
# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
|
14
|
+
# region: us-east-1
|
15
|
+
# bucket: your_own_bucket
|
16
|
+
|
17
|
+
# Remember not to checkin your GCS keyfile to a repository
|
18
|
+
# google:
|
19
|
+
# service: GCS
|
20
|
+
# project: your_project
|
21
|
+
# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %>
|
22
|
+
# bucket: your_own_bucket
|
23
|
+
|
24
|
+
# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key)
|
25
|
+
# microsoft:
|
26
|
+
# service: AzureStorage
|
27
|
+
# storage_account_name: your_account_name
|
28
|
+
# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %>
|
29
|
+
# container: your_container_name
|
30
|
+
|
31
|
+
# mirror:
|
32
|
+
# service: Mirror
|
33
|
+
# primary: local
|
34
|
+
# mirrors: [ amazon, google, microsoft ]
|
data/spec/dummy/config.ru
CHANGED
data/spec/dummy/public/404.html
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
<title>The page you were looking for doesn't exist (404)</title>
|
5
5
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
6
6
|
<style>
|
7
|
-
|
7
|
+
.rails-default-error-page {
|
8
8
|
background-color: #EFEFEF;
|
9
9
|
color: #2E2F30;
|
10
10
|
text-align: center;
|
@@ -12,13 +12,13 @@
|
|
12
12
|
margin: 0;
|
13
13
|
}
|
14
14
|
|
15
|
-
div.dialog {
|
15
|
+
.rails-default-error-page div.dialog {
|
16
16
|
width: 95%;
|
17
17
|
max-width: 33em;
|
18
18
|
margin: 4em auto 0;
|
19
19
|
}
|
20
20
|
|
21
|
-
div.dialog > div {
|
21
|
+
.rails-default-error-page div.dialog > div {
|
22
22
|
border: 1px solid #CCC;
|
23
23
|
border-right-color: #999;
|
24
24
|
border-left-color: #999;
|
@@ -31,13 +31,13 @@
|
|
31
31
|
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
32
32
|
}
|
33
33
|
|
34
|
-
h1 {
|
34
|
+
.rails-default-error-page h1 {
|
35
35
|
font-size: 100%;
|
36
36
|
color: #730E15;
|
37
37
|
line-height: 1.5em;
|
38
38
|
}
|
39
39
|
|
40
|
-
div.dialog > p {
|
40
|
+
.rails-default-error-page div.dialog > p {
|
41
41
|
margin: 0 0 1em;
|
42
42
|
padding: 1em;
|
43
43
|
background-color: #F7F7F7;
|
@@ -54,7 +54,7 @@
|
|
54
54
|
</style>
|
55
55
|
</head>
|
56
56
|
|
57
|
-
<body>
|
57
|
+
<body class="rails-default-error-page">
|
58
58
|
<!-- This file lives in public/404.html -->
|
59
59
|
<div class="dialog">
|
60
60
|
<div>
|
data/spec/dummy/public/422.html
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
<title>The change you wanted was rejected (422)</title>
|
5
5
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
6
6
|
<style>
|
7
|
-
|
7
|
+
.rails-default-error-page {
|
8
8
|
background-color: #EFEFEF;
|
9
9
|
color: #2E2F30;
|
10
10
|
text-align: center;
|
@@ -12,13 +12,13 @@
|
|
12
12
|
margin: 0;
|
13
13
|
}
|
14
14
|
|
15
|
-
div.dialog {
|
15
|
+
.rails-default-error-page div.dialog {
|
16
16
|
width: 95%;
|
17
17
|
max-width: 33em;
|
18
18
|
margin: 4em auto 0;
|
19
19
|
}
|
20
20
|
|
21
|
-
div.dialog > div {
|
21
|
+
.rails-default-error-page div.dialog > div {
|
22
22
|
border: 1px solid #CCC;
|
23
23
|
border-right-color: #999;
|
24
24
|
border-left-color: #999;
|
@@ -31,13 +31,13 @@
|
|
31
31
|
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
32
32
|
}
|
33
33
|
|
34
|
-
h1 {
|
34
|
+
.rails-default-error-page h1 {
|
35
35
|
font-size: 100%;
|
36
36
|
color: #730E15;
|
37
37
|
line-height: 1.5em;
|
38
38
|
}
|
39
39
|
|
40
|
-
div.dialog > p {
|
40
|
+
.rails-default-error-page div.dialog > p {
|
41
41
|
margin: 0 0 1em;
|
42
42
|
padding: 1em;
|
43
43
|
background-color: #F7F7F7;
|
@@ -54,7 +54,7 @@
|
|
54
54
|
</style>
|
55
55
|
</head>
|
56
56
|
|
57
|
-
<body>
|
57
|
+
<body class="rails-default-error-page">
|
58
58
|
<!-- This file lives in public/422.html -->
|
59
59
|
<div class="dialog">
|
60
60
|
<div>
|
data/spec/dummy/public/500.html
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
<title>We're sorry, but something went wrong (500)</title>
|
5
5
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
6
6
|
<style>
|
7
|
-
|
7
|
+
.rails-default-error-page {
|
8
8
|
background-color: #EFEFEF;
|
9
9
|
color: #2E2F30;
|
10
10
|
text-align: center;
|
@@ -12,13 +12,13 @@
|
|
12
12
|
margin: 0;
|
13
13
|
}
|
14
14
|
|
15
|
-
div.dialog {
|
15
|
+
.rails-default-error-page div.dialog {
|
16
16
|
width: 95%;
|
17
17
|
max-width: 33em;
|
18
18
|
margin: 4em auto 0;
|
19
19
|
}
|
20
20
|
|
21
|
-
div.dialog > div {
|
21
|
+
.rails-default-error-page div.dialog > div {
|
22
22
|
border: 1px solid #CCC;
|
23
23
|
border-right-color: #999;
|
24
24
|
border-left-color: #999;
|
@@ -31,13 +31,13 @@
|
|
31
31
|
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
32
32
|
}
|
33
33
|
|
34
|
-
h1 {
|
34
|
+
.rails-default-error-page h1 {
|
35
35
|
font-size: 100%;
|
36
36
|
color: #730E15;
|
37
37
|
line-height: 1.5em;
|
38
38
|
}
|
39
39
|
|
40
|
-
div.dialog > p {
|
40
|
+
.rails-default-error-page div.dialog > p {
|
41
41
|
margin: 0 0 1em;
|
42
42
|
padding: 1em;
|
43
43
|
background-color: #F7F7F7;
|
@@ -54,7 +54,7 @@
|
|
54
54
|
</style>
|
55
55
|
</head>
|
56
56
|
|
57
|
-
<body>
|
57
|
+
<body class="rails-default-error-page">
|
58
58
|
<!-- This file lives in public/500.html -->
|
59
59
|
<div class="dialog">
|
60
60
|
<div>
|
File without changes
|
File without changes
|
@@ -1,23 +1,22 @@
|
|
1
1
|
require "rails_helper"
|
2
2
|
|
3
3
|
describe SendGridMailer::Definition do
|
4
|
-
let(:
|
5
|
-
let(:
|
4
|
+
let(:definition) { described_class.new }
|
5
|
+
let(:personalization) { definition.send(:personalization) }
|
6
|
+
let(:mail) { definition.send(:mail) }
|
6
7
|
|
7
8
|
describe "#template_id" do
|
8
9
|
it "sets tempalte id in sengrid mail object" do
|
9
|
-
|
10
|
+
definition.set_template_id("X")
|
10
11
|
expect(mail.template_id).to eq("X")
|
11
12
|
end
|
12
13
|
end
|
13
14
|
|
14
15
|
describe "#substitute" do
|
15
|
-
|
16
|
-
@substitution = subject.substitute("%subject%", "Hi!")
|
17
|
-
end
|
16
|
+
let!(:substitution) { definition.substitute("%definition%", "Hi!") }
|
18
17
|
|
19
18
|
it "creates substitution with valid data" do
|
20
|
-
expect(
|
19
|
+
expect(substitution).to eq("%definition%" => "Hi!")
|
21
20
|
end
|
22
21
|
|
23
22
|
it "adds substitution to personalization object" do
|
@@ -25,21 +24,43 @@ describe SendGridMailer::Definition do
|
|
25
24
|
end
|
26
25
|
|
27
26
|
it "adds substitution to collection" do
|
28
|
-
|
27
|
+
definition.substitute("%body%", "blah")
|
29
28
|
expect(personalization.substitutions.size).to eq(2)
|
30
29
|
end
|
31
30
|
end
|
32
31
|
|
32
|
+
describe "#dynamic_template_data" do
|
33
|
+
let!(:substitution) { definition.dynamic_template_data(key: 'value') }
|
34
|
+
|
35
|
+
it "creates substitution with valid data" do
|
36
|
+
expect(substitution).to eq(key: 'value')
|
37
|
+
end
|
38
|
+
|
39
|
+
it "adds substitution to personalization object" do
|
40
|
+
expect(personalization.dynamic_template_data.size).to eq(1)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "add dynamic_data to data hash" do
|
44
|
+
definition.dynamic_template_data(other_key: 'other_value')
|
45
|
+
expect(personalization.dynamic_template_data.size).to eq(2)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "merges new keys into dynamic_data hash" do
|
49
|
+
definition.dynamic_template_data(other_key: 'other_value')
|
50
|
+
expect(personalization.dynamic_template_data).to eq(key: 'value', other_key: 'other_value')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
33
54
|
describe "#set_sender" do
|
34
55
|
it "adds sender to mail object" do
|
35
|
-
|
56
|
+
definition.set_sender("sender@platan.us")
|
36
57
|
expect(mail.from).to eq("email" => "sender@platan.us")
|
37
58
|
end
|
38
59
|
end
|
39
60
|
|
40
61
|
describe "#set_sender" do
|
41
62
|
it "adds sender with format to mail object" do
|
42
|
-
|
63
|
+
definition.set_sender("Sender Name <sender@platan.us>")
|
43
64
|
expect(mail.from).to eq("email" => "sender@platan.us", "name" => "Sender Name")
|
44
65
|
end
|
45
66
|
end
|
@@ -49,57 +70,65 @@ describe SendGridMailer::Definition do
|
|
49
70
|
let(:m2) { "ldlsegovia@gmail.com" }
|
50
71
|
|
51
72
|
it "adds recipients using splat operator" do
|
52
|
-
|
73
|
+
definition.set_recipients(:to, m1, m2)
|
53
74
|
expect(personalization.tos).to eq([{ "email" => m1 }, { "email" => m2 }])
|
54
75
|
end
|
55
76
|
|
56
77
|
it "adds recipients passing emails array" do
|
57
|
-
|
78
|
+
definition.set_recipients(:to, [m1, m2])
|
58
79
|
expect(personalization.tos).to eq([{ "email" => m1 }, { "email" => m2 }])
|
59
80
|
end
|
60
81
|
|
61
82
|
it "adds bcc recipient" do
|
62
|
-
|
83
|
+
definition.set_recipients(:bcc, m1)
|
63
84
|
expect(personalization.bccs).to eq([{ "email" => m1 }])
|
64
85
|
end
|
65
86
|
|
66
87
|
it "adds cc recipient" do
|
67
|
-
|
88
|
+
definition.set_recipients(:cc, m1)
|
68
89
|
expect(personalization.ccs).to eq([{ "email" => m1 }])
|
69
90
|
end
|
70
91
|
end
|
71
92
|
|
72
|
-
describe "#
|
73
|
-
it "adds
|
74
|
-
|
93
|
+
describe "#set_definition" do
|
94
|
+
it "adds definition to personalization object" do
|
95
|
+
definition.set_subject("Hi!")
|
75
96
|
expect(personalization.subject).to eq("Hi!")
|
76
97
|
end
|
77
98
|
end
|
78
99
|
|
79
100
|
describe "#set_content" do
|
80
101
|
it "adds content to mail object" do
|
81
|
-
|
102
|
+
definition.set_content("X")
|
82
103
|
expect(mail.contents).to eq([{ "type" => "text/plain", "value" => "X" }])
|
83
104
|
end
|
84
105
|
|
85
106
|
it "adds content with different type" do
|
86
|
-
|
107
|
+
definition.set_content("X", "other/type")
|
87
108
|
expect(mail.contents).to eq([{ "type" => "other/type", "value" => "X" }])
|
88
109
|
end
|
89
110
|
end
|
90
111
|
|
91
112
|
describe "#add_header" do
|
92
113
|
it "adds headers to personalization object" do
|
93
|
-
|
94
|
-
|
114
|
+
definition.add_header("HEADER1", "VALUE1")
|
115
|
+
definition.add_header("HEADER2", "VALUE2")
|
95
116
|
expect(personalization.headers).to eq("HEADER1" => "VALUE1", "HEADER2" => "VALUE2")
|
96
117
|
end
|
97
118
|
end
|
98
119
|
|
120
|
+
describe "#add_category" do
|
121
|
+
it "adds categories to mail object" do
|
122
|
+
definition.add_category("category1")
|
123
|
+
definition.add_category("category2")
|
124
|
+
expect(mail.categories).to eq(["category1", "category2"])
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
99
128
|
describe "#add_attachment" do
|
100
129
|
it "adds file to mail object" do
|
101
|
-
file = File.read(fixture_file_upload("image.png"
|
102
|
-
|
130
|
+
file = File.read(fixture_file_upload("spec/dummy/spec/assets/image.png"))
|
131
|
+
definition.add_attachment(file, "platanus.png", "image/png")
|
103
132
|
attachment = mail.attachments.first
|
104
133
|
expect(attachment["type"]).to match("image/png")
|
105
134
|
expect(attachment["disposition"]).to match("inline")
|