talktome 0.2.1 → 1.0.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b12474ba945a8c289bc358c4e654667ac7684618b3c19f3babd74dcd6c4dd2dd
4
- data.tar.gz: e3a4ebaaa0796bae48cc52e978c3aee64aade68cd80c654616171f9bf49da783
3
+ metadata.gz: d6ec4ba471da7a770b79a04a0f30cd58514f0d43b72d66b15074f2fa984887bd
4
+ data.tar.gz: 8a58f1a1e7af3440a8066e11b2fa44e4aa606c595c5b9d9e6952dd0b22d6fb97
5
5
  SHA512:
6
- metadata.gz: a64d48bc5544b99ae7868a10d2435b390526ccf9a95fc0ca323952264cb933749d20aea08365b3d9f995143df7514f7624e40dc69b2398791750149db2abc21e
7
- data.tar.gz: 9253bdbe2c08c1b75a6eeb9bb4a5e0dbfb6402365d9e925fe64282e872e034bd71da900eb235fe8e674ecd6e586b3a73a81a832775267c21b10f4f5ad1365a95
6
+ metadata.gz: 7340d04e04977b3d1a4a5def53d02b141a108e67514886f57d0d22dc87dfe340fe3a52d8f4552e7bd074229ba841256bb8006bfc900485b48cd8f0aa86522b39
7
+ data.tar.gz: 961f6e4931782c5b0f0e732c9ab3a5ea0578efe76e0346bbd8782f3b21a3a8ecd58731b51e3d3dd2e32ccb0c2d9ef48f3081f1e2f810722fbb6320348deef796
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,134 @@
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_SMTP_ADDRESS host address for smtp sending
98
+ TALKTOME_SMTP_PORT port of smtp server to use
99
+ TALKTOME_SMTP_DOMAIN sending domain
100
+ TALKTOME_SMTP_USER user for smtp authentication
101
+ TALKTOME_SMTP_PASSWORD password for smtp authentication
102
+ TALKTOME_SMTP_STARTTLS_AUTO true or false (see ruby Mail library)
103
+ ```
104
+
105
+ ## Hacking Talktome
106
+
107
+ In pure Ruby:
108
+
109
+ ```
110
+ bundle install
111
+ bundle exec rake test
112
+ ```
113
+
114
+ Or using docker, please then use the `make` targets initially cooked for Jenkins:
115
+
116
+ ```
117
+ make image
118
+ make test
119
+ ```
120
+
121
+ ## Contributing
122
+
123
+ Please use github issues for questions and bugs, and pull requests for
124
+ submitting improvement proposals and new features.
125
+
126
+ ## Contributors
127
+
128
+ Enspirit (https://enspirit.be) and Klaro App (https://klaro.cards) are
129
+ both actively using, contributing and funding work on this library.
130
+ Please contact Bernard Lambeau for any question.
131
+
132
+ ## Licence
133
+
134
+ 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 unless old.nil?
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,7 +67,15 @@ 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
 
58
81
  options
@@ -0,0 +1,61 @@
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
+ reply_to :? Email
22
+ ... : .Object
23
+ }
24
+ FIO
25
+
26
+ TALKTOME = Talktome::Client::Local.new(ROOT_FOLDER/'templates')
27
+
28
+ post %r{/([a-z-]+)/} do |action|
29
+ begin
30
+ TALKTOME.talktome(action, {}, info, [:email]){|email|
31
+ email.reply_to = info[:reply_to] if info.has_key?(:reply_to)
32
+ }
33
+ [ 200, { "Content-Type" => "text/plain"}, ["Ok"] ]
34
+ rescue JSON::ParserError
35
+ fail!("Invalid data")
36
+ rescue Finitio::Error => ex
37
+ fail!(ex.message)
38
+ rescue ::Talktome::InvalidEmailError => ex
39
+ fail!("Invalid email address")
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def info
46
+ @info ||= VALIDATION_SCHEMA.dress(JSON.parse(request.body.read)).tap{|info|
47
+ not_a_robot!(info)
48
+ }
49
+ end
50
+
51
+ def fail!(message)
52
+ [ 400, { "Content-Type" => "text/plain"}, [message] ]
53
+ end
54
+
55
+ def not_a_robot!(info)
56
+ # `reply_to_confirm` is a honeypot field, if it's filled it means it's a bot and an error is thrown
57
+ raise ::Talktome::InvalidEmailError if info[:reply_to_confirm] && info[:reply_to_confirm] =~ /^[^@]+@[^@]+$/
58
+ end
59
+
60
+ end # class App
61
+ end # module Talktome
@@ -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 = users(user).map{|u| u[: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'
@@ -37,10 +50,6 @@ module Talktome
37
50
 
38
51
  private
39
52
 
40
- def users(user)
41
- user.is_a?(Array) ? user : [user]
42
- end
43
-
44
53
  def base_email
45
54
  default_email = Mail.new
46
55
  @defaulter.call(default_email) if @defaulter
@@ -1,8 +1,8 @@
1
1
  module Talktome
2
2
  module Version
3
- MAJOR = 0
4
- MINOR = 2
5
- TINY = 1
3
+ MAJOR = 1
4
+ MINOR = 0
5
+ TINY = 0
6
6
  end
7
7
  VERSION = "#{Version::MAJOR}.#{Version::MINOR}.#{Version::TINY}"
8
8
  end
@@ -0,0 +1,90 @@
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
+ }.to_json, { "CONTENT_TYPE" => "application/json" }
24
+ expect(last_response).to be_ok
25
+ expect(Mail::TestMailer.deliveries.length).to eql(1)
26
+ expect(Mail::TestMailer.deliveries.first.to).to eql(["to@talktome.com"])
27
+ expect(Mail::TestMailer.deliveries.first.from).to eql(["from@talktome.com"])
28
+ expect(Mail::TestMailer.deliveries.first.subject).to eql("Someone wants to reach you!")
29
+ end
30
+
31
+ it 'detects invalid emails' do
32
+ post "/contact-us/", {
33
+ reply_to: 'helloatvisitor.com',
34
+ message: 'Hello from visitor'
35
+ }.to_json, { "CONTENT_TYPE" => "application/json" }
36
+ expect(last_response.status).to eql(400)
37
+ expect(Mail::TestMailer.deliveries.length).to eql(0)
38
+ end
39
+
40
+ it "detects invalid bodies" do
41
+ post "/contact-us/", body: "foobar"
42
+ expect(last_response.status).to eql(400)
43
+ expect(Mail::TestMailer.deliveries.length).to eql(0)
44
+ end
45
+
46
+ it "detects stupid bots at least" do
47
+ post "/contact-us/", {
48
+ reply_to: 'hello@visitor.com',
49
+ message: 'Hello from visitor',
50
+ reply_to_confirm: 'hello@visitor.com'
51
+ }.to_json, { "CONTENT_TYPE" => "application/json" }
52
+ expect(last_response.status).to eql(400)
53
+ expect(Mail::TestMailer.deliveries.length).to eql(0)
54
+ end
55
+
56
+ end
57
+
58
+ context 'POST /contact-us/, regarding the Reply-To' do
59
+ class ::Talktome::Message::Template
60
+ def raise_on_context_miss?
61
+ false
62
+ end
63
+ end
64
+
65
+ around(:each) do |bl|
66
+ Talktome.set_env('TALKTOME_EMAIL_DEFAULT_REPLYTO', "replyto@talktome.com", &bl)
67
+ end
68
+
69
+ it 'takes the default value from environment if set' do
70
+ post "/contact-us/", {
71
+ message: 'Hello from visitor'
72
+ }.to_json, { "CONTENT_TYPE" => "application/json" }
73
+ expect(last_response).to be_ok
74
+ expect(Mail::TestMailer.deliveries.length).to eql(1)
75
+ expect(Mail::TestMailer.deliveries.first.reply_to).to eql(["replyto@talktome.com"])
76
+ end
77
+
78
+ it "lets override it by passing a replyTo field" do
79
+ post "/contact-us/", {
80
+ reply_to: 'hello@visitor.com',
81
+ message: 'Hello from visitor'
82
+ }.to_json, { "CONTENT_TYPE" => "application/json" }
83
+ expect(last_response).to be_ok
84
+ expect(Mail::TestMailer.deliveries.length).to eql(1)
85
+ expect(Mail::TestMailer.deliveries.first.reply_to).to eql(["hello@visitor.com"])
86
+ end
87
+ end
88
+
89
+ end
90
+ end
@@ -3,16 +3,8 @@ module Talktome
3
3
  class Client
4
4
  describe Local do
5
5
 
6
- let(:user) {
7
- { email: "user@test.com" }
8
- }
9
-
10
- let(:tpldata) {
11
- { who: "Test user" }
12
- }
13
-
14
- let(:folder) {
15
- Path.dir/"../fixtures"
6
+ let(:strategy) {
7
+ Strategy::Debug.new
16
8
  }
17
9
 
18
10
  let(:client){
@@ -21,92 +13,53 @@ module Talktome
21
13
  end
22
14
  }
23
15
 
24
- context 'with a debug strategy' do
25
- let(:strategy) {
26
- Strategy::Debug.new
27
- }
28
-
29
- before(:each) {
30
- strategy.clear!
31
- }
32
-
33
- context "without templates" do
34
- let(:options) {
35
- {}
36
- }
16
+ let(:folder) {
17
+ Path.dir/"../fixtures"
18
+ }
37
19
 
38
- it 'sends email when requested' do
39
- client.talktome("welcome", user, tpldata, [:email])
40
- expect(strategy.last.message).not_to be_nil
41
- expect(strategy.last.message.to_html).to eql("<h1>Hello Test user</h1>\n\n<p>Welcome to this email example!</p>\n\n<h3>Test user</h3>\n")
42
- end
20
+ let(:user) {
21
+ { email: "user@test.com" }
22
+ }
43
23
 
44
- it 'lets send the same email to multiple users' do
45
- client.talktome("welcome", [user], tpldata, [:email])
46
- expect(strategy.last.message).not_to be_nil
47
- expect(strategy.last.message.to_html).to eql("<h1>Hello Test user</h1>\n\n<p>Welcome to this email example!</p>\n\n<h3>Test user</h3>\n")
48
- end
49
- end
24
+ let(:tpldata) {
25
+ { who: "Test user" }
26
+ }
50
27
 
51
- context "with templates" do
52
- let(:options) {
53
- {
54
- templates: Path.dir/"../fixtures/templates"
55
- }
56
- }
28
+ before(:each) {
29
+ strategy.clear!
30
+ }
57
31
 
58
- it 'sends email when requested' do
59
- client.talktome("welcome", user, tpldata, [:email])
60
- expect(strategy.last.message).not_to be_nil
61
- 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")
62
- end
32
+ context "without templates" do
33
+ let(:options) {
34
+ {}
35
+ }
63
36
 
64
- it 'yields the callback with the email' do
65
- seen = nil
66
- client.talktome("welcome", user, tpldata, [:email]){|m|
67
- seen = m
68
- }
69
- expect(seen).not_to be_nil
70
- end
37
+ it 'sends email when requested' do
38
+ client.talktome("welcome", user, tpldata, [:email])
39
+ expect(strategy.last.message).not_to be_nil
40
+ expect(strategy.last.message.to_html).to eql("<h1>Hello Test user</h1>\n\n<p>Welcome to this email example!</p>\n\n<h3>Test user</h3>\n")
71
41
  end
72
42
  end
73
43
 
74
- context 'with an email strategy' do
75
- before do
76
- Mail.defaults do
77
- delivery_method :test
78
- end
79
- Mail::TestMailer.deliveries = []
80
- end
81
-
44
+ context "with templates" do
82
45
  let(:options) {
83
- {}
84
- }
85
-
86
- let(:strategy) {
87
- Strategy::Email.new({}){|m|
88
- m.from "hello@test.com"
46
+ {
47
+ templates: Path.dir/"../fixtures/templates"
89
48
  }
90
49
  }
91
50
 
92
51
  it 'sends email when requested' do
93
52
  client.talktome("welcome", user, tpldata, [:email])
94
- mail = Mail::TestMailer.deliveries.first
95
- expect(mail).not_to be_nil
96
- expect(mail.from).to eql(["hello@test.com"])
97
- expect(mail.to).to eql(["user@test.com"])
53
+ expect(strategy.last.message).not_to be_nil
54
+ 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")
98
55
  end
99
56
 
100
- it 'allows sending email to multiple users' do
101
- client.talktome("welcome", [
102
- { email: "user1@test.com" },
103
- { email: "user2@test.com" }
104
- ], tpldata, [:email])
105
- expect(Mail::TestMailer.deliveries.length).to eql(1)
106
- mail = Mail::TestMailer.deliveries.first
107
- expect(mail).not_to be_nil
108
- expect(mail.from).to eql(["hello@test.com"])
109
- expect(mail.to).to eql(["user1@test.com", "user2@test.com"])
57
+ it 'yields the callback with the email' do
58
+ seen = nil
59
+ client.talktome("welcome", user, tpldata, [:email]){|m|
60
+ seen = m
61
+ }
62
+ expect(seen).not_to be_nil
110
63
  end
111
64
  end
112
65
 
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.1
4
+ version: 1.0.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: 2020-05-19 00:00:00.000000000 Z
11
+ date: 2021-04-30 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,54 @@ 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.8.0
144
+ type: :runtime
145
+ prerelease: false
146
+ version_requirements: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - "~>"
149
+ - !ruby/object:Gem::Version
150
+ version: 0.8.0
151
+ - !ruby/object:Gem::Dependency
152
+ name: rack-robustness
153
+ requirement: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - "~>"
156
+ - !ruby/object:Gem::Version
157
+ version: '1.1'
158
+ type: :runtime
159
+ prerelease: false
160
+ version_requirements: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - "~>"
163
+ - !ruby/object:Gem::Version
164
+ version: '1.1'
103
165
  description: Talktome helps you talk to users by email, messaging, sms, etc. It abstracts
104
166
  the messaging mechanisms and lets you manage message templates easily.
105
167
  email: blambeau@gmail.com
@@ -112,6 +174,7 @@ files:
112
174
  - README.md
113
175
  - Rakefile
114
176
  - lib/talktome.rb
177
+ - lib/talktome/app.rb
115
178
  - lib/talktome/client.rb
116
179
  - lib/talktome/client/local.rb
117
180
  - lib/talktome/error.rb
@@ -120,6 +183,7 @@ files:
120
183
  - lib/talktome/strategy/debug.rb
121
184
  - lib/talktome/strategy/email.rb
122
185
  - lib/talktome/version.rb
186
+ - spec/app/test_app.rb
123
187
  - spec/client/test_local.rb
124
188
  - spec/fixtures/templates/email.html
125
189
  - spec/fixtures/welcome/email.md
@@ -150,7 +214,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
214
  - !ruby/object:Gem::Version
151
215
  version: '0'
152
216
  requirements: []
153
- rubygems_version: 3.1.2
217
+ rubygems_version: 3.0.8
154
218
  signing_key:
155
219
  specification_version: 4
156
220
  summary: Talktome helps you talk to users by email, messaging, sms, etc.