talktome 1.0.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +7 -0
- data/lib/talktome.rb +5 -1
- data/lib/talktome/app.rb +25 -7
- data/lib/talktome/client/local.rb +2 -2
- data/lib/talktome/error.rb +1 -0
- data/lib/talktome/version.rb +2 -2
- data/spec/app/test_app.rb +111 -1
- data/spec/client/test_local.rb +17 -3
- data/spec/fixtures/contact-us/email.md +13 -0
- data/spec/fixtures/{templates → layouts}/email.html +0 -0
- data/spec/fixtures/multi-lingual/en/email.md +13 -0
- metadata +16 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 59ff5a2d705d895d7b3e03e7b6d6a9df13e6a818df6198abb238b6b2b13f34a1
|
4
|
+
data.tar.gz: 8390299781fe6800b7e0e7b68fb5d0d504b4d90ee84c8c6452a1703b24ce2ad6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 60ad688912efaefcdc60847da49b07aaadf07fdfaed1036b4905db407ff7d97c3d190ae41f8d7b70537ddfd2a7cd2dd711aa2cd1f346f48c92f6e5cac94a9686
|
7
|
+
data.tar.gz: a05b855ab7e15f29b39f8d42eee139d193788c876077e7ff0a3fd3819bb38314005a1eced8ba83c7c0d919319cb61a0adcf945e44e00847e142f1282031bebd3
|
data/README.md
CHANGED
@@ -94,12 +94,19 @@ TALKTOME_EMAIL_DEFAULT_FROM default From: to use for email sending
|
|
94
94
|
TALKTOME_EMAIL_DEFAULT_REPLYTO default Reply-To: to use for email sending
|
95
95
|
TALKTOME_EMAIL_DEFAULT_TO default To: to use for email sending
|
96
96
|
|
97
|
+
TALKTOME_EMAIL_SUBJECT Set the subject of the default "contact us" email
|
98
|
+
TALKTOME_EMAIL_FOOTER Set the footer of the default "contact us" email
|
99
|
+
|
100
|
+
TALKTOME_LAYOUTS_FOLDER Set the folder to use for messaging layouts
|
101
|
+
|
97
102
|
TALKTOME_SMTP_ADDRESS host address for smtp sending
|
98
103
|
TALKTOME_SMTP_PORT port of smtp server to use
|
99
104
|
TALKTOME_SMTP_DOMAIN sending domain
|
100
105
|
TALKTOME_SMTP_USER user for smtp authentication
|
101
106
|
TALKTOME_SMTP_PASSWORD password for smtp authentication
|
102
107
|
TALKTOME_SMTP_STARTTLS_AUTO true or false (see ruby Mail library)
|
108
|
+
|
109
|
+
TALKTOME_BEARER_SECRET secret for the webapi, to let send emails to anyone
|
103
110
|
```
|
104
111
|
|
105
112
|
## Hacking Talktome
|
data/lib/talktome.rb
CHANGED
@@ -26,7 +26,7 @@ module Talktome
|
|
26
26
|
def set_env(which, value, &bl)
|
27
27
|
old, ENV[which] = ENV[which], value
|
28
28
|
bl.call.tap{
|
29
|
-
ENV[which] = old
|
29
|
+
ENV[which] = old
|
30
30
|
}
|
31
31
|
end
|
32
32
|
module_function :set_env
|
@@ -78,6 +78,10 @@ module Talktome
|
|
78
78
|
}
|
79
79
|
}
|
80
80
|
|
81
|
+
if layouts_folder = ENV['TALKTOME_LAYOUTS_FOLDER']
|
82
|
+
options[:layouts] = Path(layouts_folder)
|
83
|
+
end
|
84
|
+
|
81
85
|
options
|
82
86
|
end
|
83
87
|
module_function :auto_options
|
data/lib/talktome/app.rb
CHANGED
@@ -13,21 +13,26 @@ module Talktome
|
|
13
13
|
|
14
14
|
set :raise_errors, true
|
15
15
|
set :show_exceptions, false
|
16
|
+
set :talktome, Talktome::Client::Local.new(ROOT_FOLDER/'templates')
|
16
17
|
|
17
18
|
VALIDATION_SCHEMA = ::Finitio.system(<<~FIO)
|
18
19
|
@import finitio/data
|
19
20
|
Email = String(s | s =~ /^[^@]+@[^@]+$/ )
|
20
21
|
{
|
22
|
+
to :? Email
|
21
23
|
reply_to :? Email
|
22
24
|
... : .Object
|
23
25
|
}
|
24
26
|
FIO
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
post %r{/([a-z-]+)/} do |action|
|
28
|
+
post %r{/([a-z-]+([\/][a-z-]+)*)/} do |action, _|
|
29
29
|
begin
|
30
|
-
|
30
|
+
as_array = info.map{|k,v| {'key' => k.capitalize, 'value' => v}}
|
31
|
+
subject = Talktome.env('TALKTOME_EMAIL_SUBJECT', 'Someone wants to reach you!')
|
32
|
+
footer = Talktome.env('TALKTOME_EMAIL_FOOTER', "Truly yours,\n
|
33
|
+
Sent by [Enspirit.be](https://enspirit.be/), contact us if you need help with any IT task.")
|
34
|
+
user = load_user_from_info!
|
35
|
+
settings.talktome.talktome(action, user, info.merge(allvars: as_array, subject: subject, footer: footer), [:email]){|email|
|
31
36
|
email.reply_to = info[:reply_to] if info.has_key?(:reply_to)
|
32
37
|
}
|
33
38
|
[ 200, { "Content-Type" => "text/plain"}, ["Ok"] ]
|
@@ -35,8 +40,10 @@ module Talktome
|
|
35
40
|
fail!("Invalid data")
|
36
41
|
rescue Finitio::Error => ex
|
37
42
|
fail!(ex.message)
|
38
|
-
rescue ::Talktome::InvalidEmailError
|
43
|
+
rescue ::Talktome::InvalidEmailError
|
39
44
|
fail!("Invalid email address")
|
45
|
+
rescue ::Talktome::TemplateNotFoundError
|
46
|
+
fail!("No such template", 404)
|
40
47
|
end
|
41
48
|
end
|
42
49
|
|
@@ -48,8 +55,19 @@ module Talktome
|
|
48
55
|
}
|
49
56
|
end
|
50
57
|
|
51
|
-
def
|
52
|
-
|
58
|
+
def load_user_from_info!
|
59
|
+
if to = info[:to]
|
60
|
+
secret = Talktome.env('TALKTOME_BEARER_SECRET')
|
61
|
+
fail!("Missing secret", 400) unless secret
|
62
|
+
fail!("Invalid secret", 401) unless "Bearer #{secret}" == env["HTTP_AUTHORIZATION"]
|
63
|
+
{ email: info[:to] }
|
64
|
+
else
|
65
|
+
{}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def fail!(message, status = 400)
|
70
|
+
halt([ status, { "Content-Type" => "text/plain"}, [message] ])
|
53
71
|
end
|
54
72
|
|
55
73
|
def not_a_robot!(info)
|
@@ -17,7 +17,7 @@ module Talktome
|
|
17
17
|
|
18
18
|
def load_message!(identifier, strategies)
|
19
19
|
folder = self.folder/identifier
|
20
|
-
raise
|
20
|
+
raise TemplateNotFoundError, "No such message `#{identifier}`" unless folder.exists?
|
21
21
|
raise InvalidMessageError, "Message `#{identifier}` should be a folder" unless folder.directory?
|
22
22
|
strategies.each do |s|
|
23
23
|
if (file = folder.glob("#{s}.*").first) && file.file?
|
@@ -33,7 +33,7 @@ module Talktome
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def templater(strategy)
|
36
|
-
return nil unless tpl_folder = options[:templates]
|
36
|
+
return nil unless tpl_folder = options[:layouts] || options[:templates]
|
37
37
|
->(message, src, ctype) {
|
38
38
|
if (file = tpl_folder/"#{strategy}.#{ctype}").file?
|
39
39
|
data = { metadata: message.metadata, yield: src }
|
data/lib/talktome/error.rb
CHANGED
data/lib/talktome/version.rb
CHANGED
data/spec/app/test_app.rb
CHANGED
@@ -9,6 +9,7 @@ module Talktome
|
|
9
9
|
}
|
10
10
|
|
11
11
|
before(:each) do
|
12
|
+
Talktome::App.set :talktome, Talktome::Client::Local.new(Path.dir.parent/'fixtures')
|
12
13
|
ENV['TALKTOME_EMAIL_DEFAULT_TO'] = "to@talktome.com"
|
13
14
|
ENV['TALKTOME_EMAIL_DEFAULT_FROM'] = "from@talktome.com"
|
14
15
|
Mail::TestMailer.deliveries.clear
|
@@ -19,13 +20,47 @@ module Talktome
|
|
19
20
|
it 'works' do
|
20
21
|
post "/contact-us/", {
|
21
22
|
reply_to: 'hello@visitor.com',
|
22
|
-
message: 'Hello from visitor'
|
23
|
+
message: 'Hello from visitor',
|
24
|
+
key: 'value',
|
23
25
|
}.to_json, { "CONTENT_TYPE" => "application/json" }
|
24
26
|
expect(last_response).to be_ok
|
25
27
|
expect(Mail::TestMailer.deliveries.length).to eql(1)
|
26
28
|
expect(Mail::TestMailer.deliveries.first.to).to eql(["to@talktome.com"])
|
27
29
|
expect(Mail::TestMailer.deliveries.first.from).to eql(["from@talktome.com"])
|
28
30
|
expect(Mail::TestMailer.deliveries.first.subject).to eql("Someone wants to reach you!")
|
31
|
+
expect(Mail::TestMailer.deliveries.first.html_part.body).to include("<li>Key: value</li>")
|
32
|
+
expect(Mail::TestMailer.deliveries.first.html_part.body).to include("Truly yours")
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'allows to use environment variable to tune the subject and the footer' do
|
36
|
+
Talktome.set_env('TALKTOME_EMAIL_SUBJECT', "Subject from environment") do
|
37
|
+
Talktome.set_env('TALKTOME_EMAIL_FOOTER', "Footer from environment") do
|
38
|
+
post "/contact-us/", {
|
39
|
+
reply_to: 'info@domain.com',
|
40
|
+
message: 'This is the message.'
|
41
|
+
}.to_json, { "CONTENT_TYPE" => "application/json" }
|
42
|
+
expect(last_response).to be_ok
|
43
|
+
expect(Mail::TestMailer.deliveries.length).to eql(1)
|
44
|
+
expect(Mail::TestMailer.deliveries.first.subject).to eql("Subject from environment")
|
45
|
+
expect(Mail::TestMailer.deliveries.first.html_part.body).to include("Footer from environment")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'allows to use a token authentification to bypass default security measures, for e.g. passing the :to' do
|
51
|
+
Talktome.set_env('TALKTOME_BEARER_SECRET', "Some secret") do
|
52
|
+
header 'Authorization', 'Bearer Some secret'
|
53
|
+
post "/contact-us/", {
|
54
|
+
to: 'hello@visitor.com',
|
55
|
+
reply_to: 'hello@visitor.com',
|
56
|
+
message: 'Hello from visitor',
|
57
|
+
key: 'value',
|
58
|
+
}.to_json, { "CONTENT_TYPE" => "application/json" }
|
59
|
+
expect(last_response).to be_ok
|
60
|
+
expect(Mail::TestMailer.deliveries.length).to eql(1)
|
61
|
+
expect(Mail::TestMailer.deliveries.first.to).to eql(["hello@visitor.com"])
|
62
|
+
expect(Mail::TestMailer.deliveries.first.from).to eql(["from@talktome.com"])
|
63
|
+
end
|
29
64
|
end
|
30
65
|
|
31
66
|
it 'detects invalid emails' do
|
@@ -53,6 +88,48 @@ module Talktome
|
|
53
88
|
expect(Mail::TestMailer.deliveries.length).to eql(0)
|
54
89
|
end
|
55
90
|
|
91
|
+
it 'forbids usage of :to unless a secret is provided' do
|
92
|
+
post "/contact-us/", {
|
93
|
+
to: 'hello@visitor.com',
|
94
|
+
reply_to: 'hello@visitor.com',
|
95
|
+
message: 'Hello from visitor',
|
96
|
+
key: 'value',
|
97
|
+
}.to_json, { "CONTENT_TYPE" => "application/json" }
|
98
|
+
expect(last_response.status).to eql(400)
|
99
|
+
expect(Mail::TestMailer.deliveries.length).to eql(0)
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'does not allow setting the :to without a valid AUTH token' do
|
103
|
+
Talktome.set_env('TALKTOME_BEARER_SECRET', "Invalid secret") do
|
104
|
+
post "/contact-us/", {
|
105
|
+
to: 'hello@visitor.com',
|
106
|
+
reply_to: 'hello@visitor.com',
|
107
|
+
message: 'Hello from visitor',
|
108
|
+
key: 'value',
|
109
|
+
}.to_json, { "CONTENT_TYPE" => "application/json" }
|
110
|
+
expect(last_response.status).to eql(401)
|
111
|
+
expect(Mail::TestMailer.deliveries.length).to eql(0)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'requires a valid Email for :to' do
|
116
|
+
post "/contact-us/", {
|
117
|
+
to: nil,
|
118
|
+
reply_to: 'hello@visitor.com',
|
119
|
+
message: 'Hello from visitor',
|
120
|
+
key: 'value',
|
121
|
+
}.to_json, { "CONTENT_TYPE" => "application/json" }
|
122
|
+
expect(last_response.status).to eql(400)
|
123
|
+
|
124
|
+
post "/contact-us/", {
|
125
|
+
to: "notavalidemail",
|
126
|
+
reply_to: 'hello@visitor.com',
|
127
|
+
message: 'Hello from visitor',
|
128
|
+
key: 'value',
|
129
|
+
}.to_json, { "CONTENT_TYPE" => "application/json" }
|
130
|
+
expect(last_response.status).to eql(400)
|
131
|
+
end
|
132
|
+
|
56
133
|
end
|
57
134
|
|
58
135
|
context 'POST /contact-us/, regarding the Reply-To' do
|
@@ -86,5 +163,38 @@ module Talktome
|
|
86
163
|
end
|
87
164
|
end
|
88
165
|
|
166
|
+
context 'POST /multi-lingual/en/' do
|
167
|
+
|
168
|
+
it 'works' do
|
169
|
+
post "/multi-lingual/en/", {
|
170
|
+
reply_to: 'hello@visitor.com',
|
171
|
+
message: 'Hello from visitor',
|
172
|
+
key: 'value',
|
173
|
+
}.to_json, { "CONTENT_TYPE" => "application/json" }
|
174
|
+
expect(last_response.status).to eql(200)
|
175
|
+
expect(last_response).to be_ok
|
176
|
+
expect(Mail::TestMailer.deliveries.length).to eql(1)
|
177
|
+
expect(Mail::TestMailer.deliveries.first.to).to eql(["to@talktome.com"])
|
178
|
+
expect(Mail::TestMailer.deliveries.first.from).to eql(["from@talktome.com"])
|
179
|
+
expect(Mail::TestMailer.deliveries.first.subject).to eql("Someone wants to reach you!")
|
180
|
+
expect(Mail::TestMailer.deliveries.first.html_part.body).to include("<li>Key: value</li>")
|
181
|
+
expect(Mail::TestMailer.deliveries.first.html_part.body).to include("Truly yours")
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
context 'POST /xxx when the template does not exist' do
|
186
|
+
|
187
|
+
it 'return a 404 error when the template doesn\'t exist' do
|
188
|
+
post "/multi-lingual/fr/", {
|
189
|
+
reply_to: 'hello@visitor.com',
|
190
|
+
message: 'Hello from visitor',
|
191
|
+
key: 'value',
|
192
|
+
}.to_json, { "CONTENT_TYPE" => "application/json" }
|
193
|
+
|
194
|
+
expect(last_response.status).to eql(404)
|
195
|
+
expect(last_response.body).to match(/No such template/)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
89
199
|
end
|
90
200
|
end
|
data/spec/client/test_local.rb
CHANGED
@@ -29,7 +29,7 @@ module Talktome
|
|
29
29
|
strategy.clear!
|
30
30
|
}
|
31
31
|
|
32
|
-
context "without
|
32
|
+
context "without layouts" do
|
33
33
|
let(:options) {
|
34
34
|
{}
|
35
35
|
}
|
@@ -41,10 +41,10 @@ module Talktome
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
context "with
|
44
|
+
context "with layouts under the :layouts option key" do
|
45
45
|
let(:options) {
|
46
46
|
{
|
47
|
-
|
47
|
+
layouts: Path.dir/"../fixtures/layouts"
|
48
48
|
}
|
49
49
|
}
|
50
50
|
|
@@ -63,6 +63,20 @@ module Talktome
|
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
|
+
context "with layouts under the :templates option key (backward compatibility)" do
|
67
|
+
let(:options) {
|
68
|
+
{
|
69
|
+
templates: Path.dir/"../fixtures/layouts"
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
it 'sends email when requested' do
|
74
|
+
client.talktome("welcome", user, tpldata, [:email])
|
75
|
+
expect(strategy.last.message.to_html).to eql("<html><title>Hello Test user</title><body><h1>Hello Test user</h1>\n\n<p>Welcome to this email example!</p>\n\n<h3>Test user</h3>\n</body></html>\n")
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
66
80
|
end
|
67
81
|
end
|
68
82
|
end
|
File without changes
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: talktome
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bernard Lambeau
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-06-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -138,16 +138,22 @@ dependencies:
|
|
138
138
|
name: finitio
|
139
139
|
requirement: !ruby/object:Gem::Requirement
|
140
140
|
requirements:
|
141
|
-
- - "
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: 0.10.0
|
144
|
+
- - "<"
|
142
145
|
- !ruby/object:Gem::Version
|
143
|
-
version: 0.
|
146
|
+
version: 0.11.0
|
144
147
|
type: :runtime
|
145
148
|
prerelease: false
|
146
149
|
version_requirements: !ruby/object:Gem::Requirement
|
147
150
|
requirements:
|
148
|
-
- - "
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: 0.10.0
|
154
|
+
- - "<"
|
149
155
|
- !ruby/object:Gem::Version
|
150
|
-
version: 0.
|
156
|
+
version: 0.11.0
|
151
157
|
- !ruby/object:Gem::Dependency
|
152
158
|
name: rack-robustness
|
153
159
|
requirement: !ruby/object:Gem::Requirement
|
@@ -185,7 +191,9 @@ files:
|
|
185
191
|
- lib/talktome/version.rb
|
186
192
|
- spec/app/test_app.rb
|
187
193
|
- spec/client/test_local.rb
|
188
|
-
- spec/fixtures/
|
194
|
+
- spec/fixtures/contact-us/email.md
|
195
|
+
- spec/fixtures/layouts/email.html
|
196
|
+
- spec/fixtures/multi-lingual/en/email.md
|
189
197
|
- spec/fixtures/welcome/email.md
|
190
198
|
- spec/fixtures/welcome/footer.mustache
|
191
199
|
- spec/message/test_initialize.rb
|
@@ -214,7 +222,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
214
222
|
- !ruby/object:Gem::Version
|
215
223
|
version: '0'
|
216
224
|
requirements: []
|
217
|
-
rubygems_version: 3.
|
225
|
+
rubygems_version: 3.2.15
|
218
226
|
signing_key:
|
219
227
|
specification_version: 4
|
220
228
|
summary: Talktome helps you talk to users by email, messaging, sms, etc.
|