talktome 0.2.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 2817b7e3a3e6d077e889d0d53ac368195785af09
4
- data.tar.gz: e5d9c60306e644301a1029739f16041f3b740be2
2
+ SHA256:
3
+ metadata.gz: c02c611e3628b2f56012103e2c8ae0a5bb600ee9e11a24a7c7acf748475c9380
4
+ data.tar.gz: f1dadedcddd3f434298359293ef656be2f14396c7d9dd8c597ea5db2bb7a138b
5
5
  SHA512:
6
- metadata.gz: 8cf1e843cfd0ce3187bc693889ed5baf7e0deeddff436cf483ec0af6f20f6698e5d91eea60717f990b270f274bddd1ff959e75a1dca8fc7e5ad7325873c31f56
7
- data.tar.gz: f312d5300c8eeacee34bd90097d61bd996246081b0400e013f59a63147a374719a59c904b3bd191481fc9d08e1417c5eebf266374931273a448e05b047ff0c8f
6
+ metadata.gz: 76e3843b6ec151090b9c88f26180a620d82bb737360fbb43b8f70f6f10d559401bf822f626cfde81c3edd43df253388ded9ca8761ce849c2af55262eb6e66503
7
+ data.tar.gz: 5f6558c21f2eeebd114a876232be0eb2c6dfdde84d7862d105c6da2400ee55d367f1428289e572a02c64fb5e8056e4e8999a9bb28de0b2af1199c1dd5613bc73
data/LICENSE.md CHANGED
@@ -1,22 +1,20 @@
1
- # The MIT Licence
1
+ Copyright (c) 2017-2021 - Enspirit SPRL (Bernard Lambeau)
2
2
 
3
- Copyright (c) 2017 - Enspirit SPRL (Bernard Lambeau)
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
4
10
 
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
12
13
 
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,3 +1,141 @@
1
1
  # Talktome - Talk to users easily
2
2
 
3
- ...
3
+ [![Build Status](https://travis-ci.com/enspirit/talktome.svg?branch=master)](https://travis-ci.com/enspirit/talktome)
4
+
5
+ Talktome helps talking to users (by email for now, but later we aim to add support
6
+ for various notification systems) easily. As a ruby gem to be used programmatically,
7
+ or as a docker container exposing web services (different use cases, see below).
8
+
9
+ ## Using Talktome programmatically
10
+
11
+ Using Talktome programmatically is useful to send transactional emails to users.
12
+
13
+ ```
14
+ require 'talktome'
15
+ CLIENT = Talktome::Client::Local.new(path_to_templates)
16
+
17
+ # later on
18
+ CLIENT.talktome(template_name, user, template_info, strategies)
19
+
20
+ # typically, the will send an email to foo@bar.com instantiating
21
+ # the email found in path_to_templates/hello/email.md and
22
+ # instantiated using mustache and markdown
23
+ CLIENT.talktome("hello", {email: 'foo@bar.com'}, {}, [:email])
24
+ ```
25
+
26
+ ## Using Talktome using the docker image
27
+
28
+ The docker image aims at supporting another category of use cases, such as providing
29
+ a reusable backend for contact forms.
30
+
31
+ ```
32
+ docker run \
33
+ -p4567:4567 \
34
+ -e TALKTOME_EMAIL_DEFAULT_FROM=info@mydomain.com
35
+ -e TALKTOME_EMAIL_DEFAULT_TO=support@mydomain.com
36
+ enspirit/talktome
37
+ ```
38
+
39
+ Send an contact-us email through the web api using curl, as follows:
40
+
41
+ ```
42
+ curl -XPOST \
43
+ -H'Content-Type: application/json' \
44
+ -d'{"reply_to": "someone@foo.bar", "message": "Hello"}' \
45
+ http://127.0.0.1:4567/contact-us/
46
+ ```
47
+
48
+ This web API does not allow specifying `from` and `to` as input data to avoid
49
+ exposing a way to send SPAM easily.
50
+
51
+ ### Overriding templates (and having more than one endpoint)
52
+
53
+ The default image comes with a single contact-us email template used by Enspirit.
54
+ Feel free to override it by providing one or more email templates.
55
+
56
+ You can mount a volume with email templates into `/app/templates/`, which will
57
+ be used for the available endpoints. For instance, the following `templates/`
58
+ folder will expose two endpoints with possibly different behaviors (according
59
+ to the templates themselves):
60
+
61
+ ```
62
+ templates/
63
+ contact-us/
64
+ email.md
65
+ report-issue/
66
+ email.md
67
+ ```
68
+
69
+ Two usual ways to do so in docker: commandline or Dockerfile. On commandline,
70
+ use the following option:
71
+
72
+ ```
73
+ -v ${PWD}/my-templates:/app/templates
74
+ ```
75
+
76
+ In a Dockerfile, add your templates:
77
+
78
+ ```
79
+ FROM enspirit/talktome
80
+
81
+ COPY ./templates /app/templates
82
+ ```
83
+
84
+ ## Configuring Talktome
85
+
86
+ The easiest way to configure Talktome is through environment variables. The following
87
+ ones are supported:
88
+
89
+ ```
90
+ TALKTOME_DEBUG when set enables the dumping of sent messages to ./tmp folder
91
+
92
+ TALKTOME_EMAIL_DELIVERY smtp, file or test (see ruby Mail library)
93
+ TALKTOME_EMAIL_DEFAULT_FROM default From: to use for email sending
94
+ TALKTOME_EMAIL_DEFAULT_REPLYTO default Reply-To: to use for email sending
95
+ TALKTOME_EMAIL_DEFAULT_TO default To: to use for email sending
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
+
102
+ TALKTOME_SMTP_ADDRESS host address for smtp sending
103
+ TALKTOME_SMTP_PORT port of smtp server to use
104
+ TALKTOME_SMTP_DOMAIN sending domain
105
+ TALKTOME_SMTP_USER user for smtp authentication
106
+ TALKTOME_SMTP_PASSWORD password for smtp authentication
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
110
+ ```
111
+
112
+ ## Hacking Talktome
113
+
114
+ In pure Ruby:
115
+
116
+ ```
117
+ bundle install
118
+ bundle exec rake test
119
+ ```
120
+
121
+ Or using docker, please then use the `make` targets initially cooked for Jenkins:
122
+
123
+ ```
124
+ make image
125
+ make test
126
+ ```
127
+
128
+ ## Contributing
129
+
130
+ Please use github issues for questions and bugs, and pull requests for
131
+ submitting improvement proposals and new features.
132
+
133
+ ## Contributors
134
+
135
+ Enspirit (https://enspirit.be) and Klaro App (https://klaro.cards) are
136
+ both actively using, contributing and funding work on this library.
137
+ Please contact Bernard Lambeau for any question.
138
+
139
+ ## Licence
140
+
141
+ Webspicy is distributed under a MIT Licence, by Enspirit SRL.
data/lib/talktome.rb CHANGED
@@ -4,25 +4,39 @@ require 'mustache'
4
4
  require 'redcarpet'
5
5
  module Talktome
6
6
 
7
+ # Root folder of the project structure
8
+ ROOT_FOLDER = Path.backfind('.[Gemfile]') or raise("Missing Gemfile")
9
+
10
+ def env(which, default = nil)
11
+ if ENV.has_key?(which)
12
+ got = ENV[which].to_s.strip
13
+ return got unless got.empty?
14
+ end
15
+ default
16
+ end
17
+ module_function :env
18
+
19
+ def with_env(which, &bl)
20
+ env(which).tap{|x|
21
+ bl.call(x) unless x.nil?
22
+ }
23
+ end
24
+ module_function :with_env
25
+
26
+ def set_env(which, value, &bl)
27
+ old, ENV[which] = ENV[which], value
28
+ bl.call.tap{
29
+ ENV[which] = old
30
+ }
31
+ end
32
+ module_function :set_env
33
+
7
34
  def redcarpet
8
35
  @redcarpet ||= Redcarpet::Markdown.new(Redcarpet::Render::HTML, extensions = {})
9
36
  end
10
37
  module_function :redcarpet
11
38
 
12
- #
13
39
  # Infer all client and strategy options from environment variables.
14
- # The following ones are recognized:
15
- #
16
- # - TALKTOME_DEBUG: when set (to anything) enables the dumping of sent
17
- # messages to the debug folder
18
- # - TALKTOME_EMAIL_DELIVERY: "smtp", "file" or "test"
19
- # - TALKTOME_EMAIL_DEFAULT_FROM: default from address to use for email sending
20
- # - TALKTOME_SMTP_ADDRESS: host address for smtp sending
21
- # - TALKTOME_SMTP_PORT: port of smtp server to use
22
- # - TALKTOME_SMTP_DOMAIN: sending domain
23
- # - TALKTOME_SMTP_USER: user for smtp authentication
24
- # - TALKTOME_SMTP_PASSWORD: user for smtp authentication
25
- #
26
40
  def auto_options(folder)
27
41
  options = {}
28
42
  debug_folder = folder/"tmp"
@@ -40,10 +54,11 @@ module Talktome
40
54
 
41
55
  email_config.merge!({
42
56
  address: ENV['TALKTOME_SMTP_ADDRESS'],
43
- port: ENV['TALKTOME_SMTP_PORT'],
57
+ port: ENV['TALKTOME_SMTP_PORT'].to_i,
44
58
  domain: ENV['TALKTOME_SMTP_DOMAIN'],
45
59
  user_name: ENV['TALKTOME_SMTP_USER'],
46
- password: ENV['TALKTOME_SMTP_PASSWORD']
60
+ password: ENV['TALKTOME_SMTP_PASSWORD'],
61
+ enable_starttls_auto: (ENV['TALKTOME_SMTP_STARTTLS_AUTO'] != 'false')
47
62
  }) if email_delivery == :smtp
48
63
 
49
64
  email_config.merge!({
@@ -52,9 +67,21 @@ module Talktome
52
67
 
53
68
  options[:strategies][:email] = ::Talktome::Strategy::Email.new{|email|
54
69
  email.delivery_method(email_delivery, email_config)
55
- email.from(ENV['TALKTOME_EMAIL_DEFAULT_FROM']) if ENV['TALKTOME_EMAIL_DEFAULT_FROM']
70
+ with_env('TALKTOME_EMAIL_DEFAULT_FROM'){|default|
71
+ email.from(default)
72
+ }
73
+ with_env('TALKTOME_EMAIL_DEFAULT_TO'){|default|
74
+ email.to(default)
75
+ }
76
+ with_env('TALKTOME_EMAIL_DEFAULT_REPLYTO'){|default|
77
+ email.reply_to(default)
78
+ }
56
79
  }
57
80
 
81
+ if layouts_folder = ENV['TALKTOME_LAYOUTS_FOLDER']
82
+ options[:layouts] = Path(layouts_folder)
83
+ end
84
+
58
85
  options
59
86
  end
60
87
  module_function :auto_options
@@ -0,0 +1,78 @@
1
+ require 'sinatra'
2
+ require 'finitio'
3
+ require 'rack/robustness'
4
+ module Talktome
5
+ class App < Sinatra::Application
6
+
7
+ use Rack::Robustness do |g|
8
+ g.catch_all
9
+ g.status 500
10
+ g.content_type 'text/plain'
11
+ g.body{ "An error occured." }
12
+ end
13
+
14
+ set :raise_errors, true
15
+ set :show_exceptions, false
16
+
17
+ VALIDATION_SCHEMA = ::Finitio.system(<<~FIO)
18
+ @import finitio/data
19
+ Email = String(s | s =~ /^[^@]+@[^@]+$/ )
20
+ {
21
+ to :? Email
22
+ reply_to :? Email
23
+ ... : .Object
24
+ }
25
+ FIO
26
+
27
+ TALKTOME = Talktome::Client::Local.new(ROOT_FOLDER/'templates')
28
+
29
+ post %r{/([a-z-]+)/} do |action|
30
+ begin
31
+ as_array = info.map{|k,v| {'key' => k.capitalize, 'value' => v}}
32
+ subject = Talktome.env('TALKTOME_EMAIL_SUBJECT', 'Someone wants to reach you!')
33
+ footer = Talktome.env('TALKTOME_EMAIL_FOOTER', "Truly yours,\n
34
+ Sent by [Enspirit.be](https://enspirit.be/), contact us if you need help with any IT task.")
35
+ user = load_user_from_info!
36
+ TALKTOME.talktome(action, user, info.merge(allvars: as_array, subject: subject, footer: footer), [:email]){|email|
37
+ email.reply_to = info[:reply_to] if info.has_key?(:reply_to)
38
+ }
39
+ [ 200, { "Content-Type" => "text/plain"}, ["Ok"] ]
40
+ rescue JSON::ParserError
41
+ fail!("Invalid data")
42
+ rescue Finitio::Error => ex
43
+ fail!(ex.message)
44
+ rescue ::Talktome::InvalidEmailError => ex
45
+ fail!("Invalid email address")
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ def info
52
+ @info ||= VALIDATION_SCHEMA.dress(JSON.parse(request.body.read)).tap{|info|
53
+ not_a_robot!(info)
54
+ }
55
+ end
56
+
57
+ def load_user_from_info!
58
+ if to = info[:to]
59
+ secret = Talktome.env('TALKTOME_BEARER_SECRET')
60
+ fail!("Missing secret", 400) unless secret
61
+ fail!("Invalid secret", 401) unless "Bearer #{secret}" == env["HTTP_AUTHORIZATION"]
62
+ { email: info[:to] }
63
+ else
64
+ {}
65
+ end
66
+ end
67
+
68
+ def fail!(message, status = 400)
69
+ halt([ status, { "Content-Type" => "text/plain"}, [message] ])
70
+ end
71
+
72
+ def not_a_robot!(info)
73
+ # `reply_to_confirm` is a honeypot field, if it's filled it means it's a bot and an error is thrown
74
+ raise ::Talktome::InvalidEmailError if info[:reply_to_confirm] && info[:reply_to_confirm] =~ /^[^@]+@[^@]+$/
75
+ end
76
+
77
+ end # class App
78
+ end # module Talktome
@@ -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 }
@@ -1,4 +1,5 @@
1
1
  module Talktome
2
2
  class Error < StandardError; end
3
3
  class InvalidMessageError < Error; end
4
+ class InvalidEmailError < Error; end
4
5
  end
@@ -9,10 +9,23 @@ module Talktome
9
9
  end
10
10
 
11
11
  def send_message(message, user)
12
+ # Take a base email, with all info coming from the environment (if set)
12
13
  mail = base_email
13
- mail.to = user[:email]
14
- mail.reply_to = message.metadata["reply_to"] if message.metadata.has_key?("reply_to")
15
- mail.subject = message.metadata["subject"]
14
+
15
+ # Override environment defaults with template behavior, for flexibility
16
+ [
17
+ :to,
18
+ :reply_to,
19
+ :subject
20
+ ].each do |which|
21
+ if arg = message.metadata[which.to_s]
22
+ mail.send(:"#{which}=", arg)
23
+ end
24
+ end
25
+
26
+ # If the user is actually known from source code behavior, override the
27
+ # `mail.to` to send the email to that particular person.
28
+ mail.to = user[:email] if user.has_key?(:email)
16
29
 
17
30
  case message.extension
18
31
  when 'md', 'html', 'htm'
@@ -1,6 +1,6 @@
1
1
  module Talktome
2
2
  module Version
3
- MAJOR = 0
3
+ MAJOR = 1
4
4
  MINOR = 2
5
5
  TINY = 0
6
6
  end
@@ -0,0 +1,166 @@
1
+ require 'spec_helper'
2
+
3
+ module Talktome
4
+ describe App do
5
+ include Rack::Test::Methods
6
+
7
+ let(:app) {
8
+ Talktome::App.new
9
+ }
10
+
11
+ before(:each) do
12
+ ENV['TALKTOME_EMAIL_DEFAULT_TO'] = "to@talktome.com"
13
+ ENV['TALKTOME_EMAIL_DEFAULT_FROM'] = "from@talktome.com"
14
+ Mail::TestMailer.deliveries.clear
15
+ end
16
+
17
+ context 'POST /contact-us/, the basic contract' do
18
+
19
+ it 'works' do
20
+ post "/contact-us/", {
21
+ reply_to: 'hello@visitor.com',
22
+ message: 'Hello from visitor',
23
+ key: 'value',
24
+ }.to_json, { "CONTENT_TYPE" => "application/json" }
25
+ expect(last_response).to be_ok
26
+ expect(Mail::TestMailer.deliveries.length).to eql(1)
27
+ expect(Mail::TestMailer.deliveries.first.to).to eql(["to@talktome.com"])
28
+ expect(Mail::TestMailer.deliveries.first.from).to eql(["from@talktome.com"])
29
+ expect(Mail::TestMailer.deliveries.first.subject).to eql("Someone wants to reach you!")
30
+ expect(Mail::TestMailer.deliveries.first.html_part.body).to include("<li>Key: value</li>")
31
+ expect(Mail::TestMailer.deliveries.first.html_part.body).to include("Truly yours")
32
+ end
33
+
34
+ it 'allows to use environment variable to tune the subject and the footer' do
35
+ Talktome.set_env('TALKTOME_EMAIL_SUBJECT', "Subject from environment") do
36
+ Talktome.set_env('TALKTOME_EMAIL_FOOTER', "Footer from environment") do
37
+ post "/contact-us/", {
38
+ reply_to: 'info@domain.com',
39
+ message: 'This is the message.'
40
+ }.to_json, { "CONTENT_TYPE" => "application/json" }
41
+ expect(last_response).to be_ok
42
+ expect(Mail::TestMailer.deliveries.length).to eql(1)
43
+ expect(Mail::TestMailer.deliveries.first.subject).to eql("Subject from environment")
44
+ expect(Mail::TestMailer.deliveries.first.html_part.body).to include("Footer from environment")
45
+ end
46
+ end
47
+ end
48
+
49
+ it 'allows to use a token authentification to bypass default security measures, for e.g. passing the :to' do
50
+ Talktome.set_env('TALKTOME_BEARER_SECRET', "Some secret") do
51
+ header 'Authorization', 'Bearer Some secret'
52
+ post "/contact-us/", {
53
+ to: 'hello@visitor.com',
54
+ reply_to: 'hello@visitor.com',
55
+ message: 'Hello from visitor',
56
+ key: 'value',
57
+ }.to_json, { "CONTENT_TYPE" => "application/json" }
58
+ expect(last_response).to be_ok
59
+ expect(Mail::TestMailer.deliveries.length).to eql(1)
60
+ expect(Mail::TestMailer.deliveries.first.to).to eql(["hello@visitor.com"])
61
+ expect(Mail::TestMailer.deliveries.first.from).to eql(["from@talktome.com"])
62
+ end
63
+ end
64
+
65
+ it 'detects invalid emails' do
66
+ post "/contact-us/", {
67
+ reply_to: 'helloatvisitor.com',
68
+ message: 'Hello from visitor'
69
+ }.to_json, { "CONTENT_TYPE" => "application/json" }
70
+ expect(last_response.status).to eql(400)
71
+ expect(Mail::TestMailer.deliveries.length).to eql(0)
72
+ end
73
+
74
+ it "detects invalid bodies" do
75
+ post "/contact-us/", body: "foobar"
76
+ expect(last_response.status).to eql(400)
77
+ expect(Mail::TestMailer.deliveries.length).to eql(0)
78
+ end
79
+
80
+ it "detects stupid bots at least" do
81
+ post "/contact-us/", {
82
+ reply_to: 'hello@visitor.com',
83
+ message: 'Hello from visitor',
84
+ reply_to_confirm: 'hello@visitor.com'
85
+ }.to_json, { "CONTENT_TYPE" => "application/json" }
86
+ expect(last_response.status).to eql(400)
87
+ expect(Mail::TestMailer.deliveries.length).to eql(0)
88
+ end
89
+
90
+ it 'forbids usage of :to unless a secret is provided' do
91
+ post "/contact-us/", {
92
+ to: 'hello@visitor.com',
93
+ reply_to: 'hello@visitor.com',
94
+ message: 'Hello from visitor',
95
+ key: 'value',
96
+ }.to_json, { "CONTENT_TYPE" => "application/json" }
97
+ expect(last_response.status).to eql(400)
98
+ expect(Mail::TestMailer.deliveries.length).to eql(0)
99
+ end
100
+
101
+ it 'does not allow setting the :to without a valid AUTH token' do
102
+ Talktome.set_env('TALKTOME_BEARER_SECRET', "Invalid secret") do
103
+ post "/contact-us/", {
104
+ to: 'hello@visitor.com',
105
+ reply_to: 'hello@visitor.com',
106
+ message: 'Hello from visitor',
107
+ key: 'value',
108
+ }.to_json, { "CONTENT_TYPE" => "application/json" }
109
+ expect(last_response.status).to eql(401)
110
+ expect(Mail::TestMailer.deliveries.length).to eql(0)
111
+ end
112
+ end
113
+
114
+ it 'requires a valid Email for :to' do
115
+ post "/contact-us/", {
116
+ to: nil,
117
+ reply_to: 'hello@visitor.com',
118
+ message: 'Hello from visitor',
119
+ key: 'value',
120
+ }.to_json, { "CONTENT_TYPE" => "application/json" }
121
+ expect(last_response.status).to eql(400)
122
+
123
+ post "/contact-us/", {
124
+ to: "notavalidemail",
125
+ reply_to: 'hello@visitor.com',
126
+ message: 'Hello from visitor',
127
+ key: 'value',
128
+ }.to_json, { "CONTENT_TYPE" => "application/json" }
129
+ expect(last_response.status).to eql(400)
130
+ end
131
+
132
+ end
133
+
134
+ context 'POST /contact-us/, regarding the Reply-To' do
135
+ class ::Talktome::Message::Template
136
+ def raise_on_context_miss?
137
+ false
138
+ end
139
+ end
140
+
141
+ around(:each) do |bl|
142
+ Talktome.set_env('TALKTOME_EMAIL_DEFAULT_REPLYTO', "replyto@talktome.com", &bl)
143
+ end
144
+
145
+ it 'takes the default value from environment if set' do
146
+ post "/contact-us/", {
147
+ message: 'Hello from visitor'
148
+ }.to_json, { "CONTENT_TYPE" => "application/json" }
149
+ expect(last_response).to be_ok
150
+ expect(Mail::TestMailer.deliveries.length).to eql(1)
151
+ expect(Mail::TestMailer.deliveries.first.reply_to).to eql(["replyto@talktome.com"])
152
+ end
153
+
154
+ it "lets override it by passing a replyTo field" do
155
+ post "/contact-us/", {
156
+ reply_to: 'hello@visitor.com',
157
+ message: 'Hello from visitor'
158
+ }.to_json, { "CONTENT_TYPE" => "application/json" }
159
+ expect(last_response).to be_ok
160
+ expect(Mail::TestMailer.deliveries.length).to eql(1)
161
+ expect(Mail::TestMailer.deliveries.first.reply_to).to eql(["hello@visitor.com"])
162
+ end
163
+ end
164
+
165
+ end
166
+ end
@@ -29,7 +29,7 @@ module Talktome
29
29
  strategy.clear!
30
30
  }
31
31
 
32
- context "without templates" do
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 templates" do
44
+ context "with layouts under the :layouts option key" do
45
45
  let(:options) {
46
46
  {
47
- templates: Path.dir/"../fixtures/templates"
47
+ layouts: Path.dir/"../fixtures/layouts"
48
48
  }
49
49
  }
50
50
 
@@ -63,6 +63,19 @@ 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
+ end
78
+
66
79
  end
67
80
  end
68
81
  end
File without changes
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
2
  require 'talktome'
3
+ require 'talktome/app'
4
+ require 'rack/test'
3
5
 
4
6
  module SpecHelpers
5
7
  end
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: 0.2.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bernard Lambeau
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-20 00:00:00.000000000 Z
11
+ date: 2021-05-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -16,42 +16,56 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '10'
19
+ version: '13'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '10'
26
+ version: '13'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '3.6'
33
+ version: '3.10'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '3.6'
40
+ version: '3.10'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rack-test
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 0.6.3
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 0.6.3
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: path
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - ">="
46
60
  - !ruby/object:Gem::Version
47
- version: '1.3'
61
+ version: '2.0'
48
62
  type: :runtime
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
66
  - - ">="
53
67
  - !ruby/object:Gem::Version
54
- version: '1.3'
68
+ version: '2.0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: mail
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -100,6 +114,60 @@ dependencies:
100
114
  - - "~>"
101
115
  - !ruby/object:Gem::Version
102
116
  version: '3'
117
+ - !ruby/object:Gem::Dependency
118
+ name: sinatra
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '2.0'
124
+ - - "<"
125
+ - !ruby/object:Gem::Version
126
+ version: '3.0'
127
+ type: :runtime
128
+ prerelease: false
129
+ version_requirements: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '2.0'
134
+ - - "<"
135
+ - !ruby/object:Gem::Version
136
+ version: '3.0'
137
+ - !ruby/object:Gem::Dependency
138
+ name: finitio
139
+ requirement: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ version: 0.10.0
144
+ - - "<"
145
+ - !ruby/object:Gem::Version
146
+ version: 0.11.0
147
+ type: :runtime
148
+ prerelease: false
149
+ version_requirements: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: 0.10.0
154
+ - - "<"
155
+ - !ruby/object:Gem::Version
156
+ version: 0.11.0
157
+ - !ruby/object:Gem::Dependency
158
+ name: rack-robustness
159
+ requirement: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - "~>"
162
+ - !ruby/object:Gem::Version
163
+ version: '1.1'
164
+ type: :runtime
165
+ prerelease: false
166
+ version_requirements: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - "~>"
169
+ - !ruby/object:Gem::Version
170
+ version: '1.1'
103
171
  description: Talktome helps you talk to users by email, messaging, sms, etc. It abstracts
104
172
  the messaging mechanisms and lets you manage message templates easily.
105
173
  email: blambeau@gmail.com
@@ -112,6 +180,7 @@ files:
112
180
  - README.md
113
181
  - Rakefile
114
182
  - lib/talktome.rb
183
+ - lib/talktome/app.rb
115
184
  - lib/talktome/client.rb
116
185
  - lib/talktome/client/local.rb
117
186
  - lib/talktome/error.rb
@@ -120,8 +189,9 @@ files:
120
189
  - lib/talktome/strategy/debug.rb
121
190
  - lib/talktome/strategy/email.rb
122
191
  - lib/talktome/version.rb
192
+ - spec/app/test_app.rb
123
193
  - spec/client/test_local.rb
124
- - spec/fixtures/templates/email.html
194
+ - spec/fixtures/layouts/email.html
125
195
  - spec/fixtures/welcome/email.md
126
196
  - spec/fixtures/welcome/footer.mustache
127
197
  - spec/message/test_initialize.rb
@@ -150,8 +220,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
220
  - !ruby/object:Gem::Version
151
221
  version: '0'
152
222
  requirements: []
153
- rubyforge_project:
154
- rubygems_version: 2.6.11
223
+ rubygems_version: 3.2.15
155
224
  signing_key:
156
225
  specification_version: 4
157
226
  summary: Talktome helps you talk to users by email, messaging, sms, etc.