restpack_email_service 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.travis.yml +21 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +14 -0
- data/Rakefile +2 -0
- data/config/database.yml +8 -0
- data/db/migrate/20131010102904_create_email_configurations.rb +15 -0
- data/db/migrate/20131012115851_create_email_templates.rb +16 -0
- data/lib/restpack_email_service.rb +2 -0
- data/lib/restpack_email_service/commands/configuration/create.rb +22 -0
- data/lib/restpack_email_service/commands/configuration/list.rb +12 -0
- data/lib/restpack_email_service/commands/configuration/update.rb +46 -0
- data/lib/restpack_email_service/commands/template/create.rb +23 -0
- data/lib/restpack_email_service/commands/template/list.rb +13 -0
- data/lib/restpack_email_service/commands/template/update.rb +46 -0
- data/lib/restpack_email_service/configuration.rb +12 -0
- data/lib/restpack_email_service/jobs/email/send.rb +93 -0
- data/lib/restpack_email_service/jobs/email/send_raw.rb +53 -0
- data/lib/restpack_email_service/models/configuration.rb +10 -0
- data/lib/restpack_email_service/models/template.rb +36 -0
- data/lib/restpack_email_service/serializers/configuration.rb +12 -0
- data/lib/restpack_email_service/serializers/template.rb +12 -0
- data/lib/restpack_email_service/tasks/db.rake +39 -0
- data/lib/restpack_email_service/tasks/tasks.rb +7 -0
- data/lib/restpack_email_service/version.rb +7 -0
- data/restpack_email_service.gemspec +32 -0
- data/spec/commands/configuration/create_spec.rb +5 -0
- data/spec/commands/configuration/list_spec.rb +8 -0
- data/spec/commands/configuration/update_spec.rb +5 -0
- data/spec/commands/template/create_spec.rb +5 -0
- data/spec/commands/template/list_spec.rb +8 -0
- data/spec/commands/template/update_spec.rb +5 -0
- data/spec/factories/api_configuration.rb +13 -0
- data/spec/factories/api_template.rb +13 -0
- data/spec/factories/template.rb +9 -0
- data/spec/jobs/email/send_raw_spec.rb +5 -0
- data/spec/jobs/email/send_spec.rb +66 -0
- data/spec/models/configuration_spec.rb +9 -0
- data/spec/models/template_spec.rb +7 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/templates/_footer.html.liquid +3 -0
- data/spec/templates/_footer.text.liquid +1 -0
- data/spec/templates/_header.html.liquid +3 -0
- data/spec/templates/_header.text.liquid +1 -0
- data/spec/templates/group.invitation.html.liquid +5 -0
- data/spec/templates/group.invitation.subject.liquid +1 -0
- data/spec/templates/group.invitation.text.liquid +5 -0
- data/templates/_footer.html.liquid +1 -0
- data/templates/_footer.text.liquid +2 -0
- data/templates/_header.html.liquid +1 -0
- data/templates/_header.text.liquid +2 -0
- data/templates/diagnostics.html.liquid +1 -0
- data/templates/diagnostics.subject.liquid +1 -0
- data/templates/diagnostics.text.liquid +1 -0
- data/templates/group.invitation.html.liquid +23 -0
- data/templates/group.invitation.subject.liquid +1 -0
- data/templates/group.invitation.text.liquid +5 -0
- metadata +263 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b502ee058c2cdfe1e1e8bd1be7a414d214e1c64e
|
4
|
+
data.tar.gz: f9c8baa8a6ac8af77dea4c39055d434cc0a38ee2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e4df948c3add701a906843908ae08319a2369d1dbc14ff35d82677e5ffd94ced3f45aee4914f6c653f7139c8cd9c93dbbc67b830aebda107df63e517f741e248
|
7
|
+
data.tar.gz: 50b5e71cbcbf2b4846062987d950224e2f88c9957828c2f7fe0f23df1db84376d3a8c1da175af569dab30e9f2f9a0ef5afeec2d5d7ddd7a21b3ae667fcc7b74a
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 2.0.0
|
4
|
+
#http://reefpoints.dockyard.com/ruby/2013/03/29/running-postgresql-9-2-on-travis-ci.html
|
5
|
+
before_script:
|
6
|
+
- sudo /etc/init.d/postgresql stop
|
7
|
+
- sudo cp /etc/postgresql/9.1/main/pg_hba.conf ./
|
8
|
+
- sudo apt-get remove postgresql postgresql-9.1 -qq --purge
|
9
|
+
- source /etc/lsb-release
|
10
|
+
- echo "deb http://apt.postgresql.org/pub/repos/apt/ $DISTRIB_CODENAME-pgdg main" > pgdg.list
|
11
|
+
- sudo mv pgdg.list /etc/apt/sources.list.d/
|
12
|
+
- wget --quiet -O - http://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc | sudo apt-key add -
|
13
|
+
- sudo apt-get update
|
14
|
+
- sudo apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" install postgresql-9.2 postgresql-contrib-9.2 -qq
|
15
|
+
- sudo /etc/init.d/postgresql stop
|
16
|
+
- sudo cp ./pg_hba.conf /etc/postgresql/9.2/main
|
17
|
+
- sudo /etc/init.d/postgresql start
|
18
|
+
- psql -c 'create database restpack_email_service_test;' -U postgres
|
19
|
+
- psql -c 'create role travis login;' -U postgres
|
20
|
+
|
21
|
+
script: bundle exec rake test
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Gavin Joyce
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
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:
|
12
|
+
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# restpack_email_service
|
2
|
+
|
3
|
+
[![Build Status](https://travis-ci.org/RestPack/restpack_email_service.png?branch=master)](https://travis-ci.org/RestPack/restpack_email_service) [![Code Climate](https://codeclimate.com/github/RestPack/restpack_email_service.png)](https://codeclimate.com/github/RestPack/restpack_email_service) [![Dependency Status](https://gemnasium.com/RestPack/restpack_email_service.png)](https://gemnasium.com/RestPack/restpack_email_service) [![Gem Version](https://badge.fury.io/rb/restpack_email_service.png)](http://badge.fury.io/rb/restpack_email_service)
|
4
|
+
|
5
|
+
**Work In Progress**
|
6
|
+
|
7
|
+
This gem provides services for sending and receiving Emails.
|
8
|
+
|
9
|
+
## Development Setup
|
10
|
+
|
11
|
+
1. install postgres
|
12
|
+
2. create a `restpack_email_service_test` database
|
13
|
+
3. bundle
|
14
|
+
4. rake
|
data/Rakefile
ADDED
data/config/database.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
class CreateEmailConfigurations < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :restpack_email_configurations do |t|
|
4
|
+
t.integer :application_id, :null => false
|
5
|
+
t.integer :domain_id
|
6
|
+
t.string :smtp_server, :null => false, :limit => 1024
|
7
|
+
t.string :smtp_username, :null => false, :limit => 1024
|
8
|
+
t.string :smtp_password, :null => false, :limit => 1024
|
9
|
+
t.integer :smtp_port
|
10
|
+
t.string :default_from, :null => false, :limit => 512
|
11
|
+
|
12
|
+
t.timestamps
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class CreateEmailTemplates < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :restpack_email_templates do |t|
|
4
|
+
t.integer :application_id, :null => false
|
5
|
+
t.integer :domain_id
|
6
|
+
t.string :identifier, :null => false, :limit => 256
|
7
|
+
t.string :from, :limit => 512
|
8
|
+
t.string :subject_template, :null => false, :limit => 256
|
9
|
+
t.string :text_template, :limit => 65536
|
10
|
+
t.string :html_template, :limit => 65536
|
11
|
+
t.json :data, :null => false
|
12
|
+
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Commands::Email::Configuration
|
2
|
+
class Create < RestPack::Service::Commands::Create
|
3
|
+
required do
|
4
|
+
array :configurations do
|
5
|
+
hash do
|
6
|
+
required do
|
7
|
+
integer :application_id
|
8
|
+
string :smtp_server
|
9
|
+
string :smtp_username
|
10
|
+
string :smtp_password
|
11
|
+
string :default_from
|
12
|
+
end
|
13
|
+
|
14
|
+
optional do
|
15
|
+
integer :domain_id
|
16
|
+
integer :smtp_port
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Commands::Email::Configuration
|
2
|
+
class Update < RestPack::Service::Command
|
3
|
+
required do
|
4
|
+
array :configurations do
|
5
|
+
hash do
|
6
|
+
required do
|
7
|
+
integer :id
|
8
|
+
integer :application_id
|
9
|
+
string :smtp_server
|
10
|
+
integer :smtp_port
|
11
|
+
string :smtp_username
|
12
|
+
string :smtp_password
|
13
|
+
string :default_from
|
14
|
+
end
|
15
|
+
|
16
|
+
optional do
|
17
|
+
integer :domain_id
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def execute
|
24
|
+
#TODO: GJ: wrap in transaction
|
25
|
+
#TODO: GJ: extract to base class
|
26
|
+
result = {
|
27
|
+
configurations: []
|
28
|
+
}
|
29
|
+
|
30
|
+
inputs[:configurations].each do |item|
|
31
|
+
model = Models::Email::Configuration.find_by_id_and_application_id(
|
32
|
+
item[:id], item[:application_id]
|
33
|
+
)
|
34
|
+
|
35
|
+
if model
|
36
|
+
model.update_attributes(item)
|
37
|
+
result[:configurations] << Serializers::Email::Configuration.as_json(model)
|
38
|
+
else
|
39
|
+
status :not_found
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
result
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Commands::Email::Template
|
2
|
+
class Create < RestPack::Service::Commands::Create
|
3
|
+
required do
|
4
|
+
array :templates do
|
5
|
+
hash do
|
6
|
+
required do
|
7
|
+
integer :application_id
|
8
|
+
string :identifier
|
9
|
+
string :subject_template
|
10
|
+
end
|
11
|
+
|
12
|
+
optional do
|
13
|
+
integer :domain_id
|
14
|
+
string :from
|
15
|
+
string :text_template
|
16
|
+
string :html_template
|
17
|
+
model :data, class: Hash
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Commands::Email::Template
|
2
|
+
class Update < RestPack::Service::Command
|
3
|
+
required do
|
4
|
+
array :email_templates do
|
5
|
+
hash do
|
6
|
+
required do
|
7
|
+
integer :id
|
8
|
+
integer :application_id
|
9
|
+
string :identifier
|
10
|
+
string :subject_template
|
11
|
+
end
|
12
|
+
|
13
|
+
optional do
|
14
|
+
integer :domain_id
|
15
|
+
string :from
|
16
|
+
string :text_template
|
17
|
+
string :html_template
|
18
|
+
model :data, class: Hash
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def execute
|
25
|
+
#TODO: GJ: wrap in transaction
|
26
|
+
result = {
|
27
|
+
email_templates: []
|
28
|
+
}
|
29
|
+
|
30
|
+
inputs[:email_templates].each do |email_template_inputs|
|
31
|
+
email_template = Models::Email:Template.find_by_id_and_application_id(
|
32
|
+
email_template_inputs[:id], email_template_inputs[:application_id]
|
33
|
+
)
|
34
|
+
|
35
|
+
if email_template
|
36
|
+
email_template.update_attributes(email_template_inputs)
|
37
|
+
result[:email_templates] << Serializers::Email::Template.as_json(email_template)
|
38
|
+
else
|
39
|
+
status :not_found
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
return result
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'sidekiq'
|
2
|
+
|
3
|
+
module Jobs::Email
|
4
|
+
class Send
|
5
|
+
include Sidekiq::Worker
|
6
|
+
|
7
|
+
def perform(params)
|
8
|
+
params.deep_symbolize_keys!
|
9
|
+
|
10
|
+
template = get_template(params)
|
11
|
+
|
12
|
+
if template
|
13
|
+
params[:subject] = template.render_subject(params[:data])
|
14
|
+
params[:text_body] = template.render_text(params[:data])
|
15
|
+
params[:html_body] = template.render_html(params[:data])
|
16
|
+
|
17
|
+
if template.from
|
18
|
+
params[:from] ||= template.from
|
19
|
+
end
|
20
|
+
|
21
|
+
send_raw.perform(params)
|
22
|
+
else
|
23
|
+
#TODO: GJ: logging exception
|
24
|
+
raise "Invalid template: #{params['template']}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def send_raw
|
31
|
+
Jobs::Email::SendRaw.new
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_template(params)
|
35
|
+
application_id = params[:application_id]
|
36
|
+
template = resolve_template(application_id, params[:template])
|
37
|
+
inject_header_and_footer(template, application_id)
|
38
|
+
|
39
|
+
template
|
40
|
+
end
|
41
|
+
|
42
|
+
def resolve_template(application_id, identifier)
|
43
|
+
template = Models::Email::Template.where(
|
44
|
+
application_id: application_id,
|
45
|
+
identifier: identifier
|
46
|
+
).take
|
47
|
+
|
48
|
+
template ||= Models::Email::Template.new
|
49
|
+
|
50
|
+
if template.subject_template.blank?
|
51
|
+
template.subject_template = load_default_template(identifier, 'subject')
|
52
|
+
end
|
53
|
+
|
54
|
+
if template.text_template.blank?
|
55
|
+
template.text_template = load_default_template(identifier, 'text')
|
56
|
+
end
|
57
|
+
|
58
|
+
if template.html_template.blank?
|
59
|
+
template.html_template = load_default_template(identifier, 'html')
|
60
|
+
end
|
61
|
+
|
62
|
+
template
|
63
|
+
end
|
64
|
+
|
65
|
+
def load_default_template(identifier, format='html')
|
66
|
+
filepath = File.expand_path("#{template_path}/#{identifier}.#{format}.liquid", __FILE__)
|
67
|
+
if File.exists? filepath
|
68
|
+
return File.read(filepath)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def template_path
|
73
|
+
'../../../../../templates'
|
74
|
+
end
|
75
|
+
|
76
|
+
def inject_header_and_footer(template, application_id)
|
77
|
+
if template
|
78
|
+
header = resolve_template(application_id, '_header')
|
79
|
+
footer = resolve_template(application_id, '_footer')
|
80
|
+
|
81
|
+
if template.html_template
|
82
|
+
template.html_template = template.html_template.gsub('{{header}}', header.html_template)
|
83
|
+
template.html_template = template.html_template.gsub('{{footer}}', footer.html_template)
|
84
|
+
end
|
85
|
+
|
86
|
+
if template.text_template
|
87
|
+
template.text_template = template.text_template.gsub('{{header}}', header.text_template)
|
88
|
+
template.text_template = template.text_template.gsub('{{footer}}', footer.text_template)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'sidekiq'
|
2
|
+
require 'mail'
|
3
|
+
|
4
|
+
module Jobs::Email
|
5
|
+
class SendRaw
|
6
|
+
include Sidekiq::Worker
|
7
|
+
|
8
|
+
def perform(params)
|
9
|
+
params.deep_symbolize_keys!
|
10
|
+
configuration = get_configuration(params)
|
11
|
+
|
12
|
+
Mail.defaults do
|
13
|
+
delivery_method :smtp, {
|
14
|
+
address: configuration[:smtp_server],
|
15
|
+
port: configuration[:smtp_port],
|
16
|
+
user_name: configuration[:smtp_username],
|
17
|
+
password: configuration[:smtp_password],
|
18
|
+
enable_starttls_auto: true
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
mail = Mail.new do
|
23
|
+
to params[:to]
|
24
|
+
from params[:from] || configuration[:default_from]
|
25
|
+
subject params[:subject]
|
26
|
+
|
27
|
+
text_part do
|
28
|
+
body params[:text_body]
|
29
|
+
end
|
30
|
+
|
31
|
+
if params[:html_body]
|
32
|
+
html_part do
|
33
|
+
content_type 'text/html; charset=UTF-8'
|
34
|
+
body params[:html_body]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
mail.deliver
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def get_configuration(params)
|
45
|
+
config = Serializers::Email::Configuration.resource(
|
46
|
+
application_id: params[:application_id]
|
47
|
+
)[:configurations]
|
48
|
+
|
49
|
+
raise "Email is not setup for this application" if config.empty?
|
50
|
+
return config.first
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module Models::Email
|
2
|
+
class Configuration < ActiveRecord::Base
|
3
|
+
self.table_name = :restpack_email_configurations
|
4
|
+
|
5
|
+
attr_accessible :application_id, :domain_id, :smtp_server, :smtp_username,
|
6
|
+
:smtp_password, :smtp_port, :default_from
|
7
|
+
validates_presence_of :application_id, :smtp_server, :smtp_username,
|
8
|
+
:smtp_password, :default_from
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'liquid'
|
2
|
+
|
3
|
+
module Models::Email
|
4
|
+
class Template < ActiveRecord::Base
|
5
|
+
self.table_name = :restpack_email_templates
|
6
|
+
|
7
|
+
attr_accessible :application_id, :identifier, :from, :subject_template,
|
8
|
+
:text_template, :html_template, :data
|
9
|
+
validates_presence_of :application_id, :identifier, :subject_template,
|
10
|
+
:text_template, :html_template
|
11
|
+
|
12
|
+
before_save -> {
|
13
|
+
self.data ||= {}
|
14
|
+
}
|
15
|
+
|
16
|
+
def render_subject(data)
|
17
|
+
render(subject_template, data)
|
18
|
+
end
|
19
|
+
def render_text(data)
|
20
|
+
render(text_template, data)
|
21
|
+
end
|
22
|
+
def render_html(data)
|
23
|
+
render(html_template, data)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def render(template, data)
|
29
|
+
return nil unless template
|
30
|
+
|
31
|
+
data.deep_stringify_keys! if data
|
32
|
+
rendered = Liquid::Template.parse(template).render(data)
|
33
|
+
rendered.strip
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Serializers::Email
|
2
|
+
class Configuration
|
3
|
+
include RestPack::Serializer
|
4
|
+
|
5
|
+
self.model_class = Models::Email::Configuration
|
6
|
+
self.key = :configurations
|
7
|
+
|
8
|
+
attributes :id, :application_id, :domain_id, :smtp_server,
|
9
|
+
:smtp_username, :smtp_password, :smtp_port, :default_from
|
10
|
+
can_filter_by :application_id
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Serializers::Email
|
2
|
+
class Template
|
3
|
+
include RestPack::Serializer
|
4
|
+
|
5
|
+
self.model_class = Models::Email::Template
|
6
|
+
self.key = :templates
|
7
|
+
|
8
|
+
attributes :id, :application_id, :identifier, :subject_template,
|
9
|
+
:text_template, :html_template, :data
|
10
|
+
can_filter_by :application_id
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
namespace :restpack do
|
2
|
+
desc "Run any outstanding RestPack migrations"
|
3
|
+
task :migrate do
|
4
|
+
Rake::Task["restpack:email:migrate"].invoke
|
5
|
+
end
|
6
|
+
|
7
|
+
desc "List RestPack configuration"
|
8
|
+
task :configuration do
|
9
|
+
Rake::Task["restpack:email:configuration"].invoke
|
10
|
+
end
|
11
|
+
|
12
|
+
namespace :email do
|
13
|
+
desc "Run any outstanding RestPack::Core migrations"
|
14
|
+
task :migrate => ["connection"] do
|
15
|
+
source_migrations_path = File.dirname(__FILE__) + "/../../../db/migrate"
|
16
|
+
target_migrations_path = "db/migrate"
|
17
|
+
|
18
|
+
ActiveRecord::Migration.verbose = true
|
19
|
+
ActiveRecord::Migrator.migrate(source_migrations_path)
|
20
|
+
|
21
|
+
if File.directory?(target_migrations_path)
|
22
|
+
FileUtils.cp_r(Dir["#{source_migrations_path}/*"], target_migrations_path)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
task :connection do
|
27
|
+
config = YAML.load(IO.read('config/database.yml'))
|
28
|
+
environment = ENV['RAILS_ENV'] || ENV['DB'] || 'development'
|
29
|
+
ActiveRecord::Base.establish_connection config[environment]
|
30
|
+
end
|
31
|
+
|
32
|
+
desc "List RestPack::Email::Service configuration"
|
33
|
+
task :configuration do
|
34
|
+
p "RestPack::Email::Service Configuration"
|
35
|
+
p "--------------------------------"
|
36
|
+
p "TODO"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'restpack_email_service/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "restpack_email_service"
|
8
|
+
spec.version = RestPack::Email::Service::VERSION
|
9
|
+
spec.authors = ["Gavin Joyce"]
|
10
|
+
spec.email = ["gavinjoyce@gmail.com"]
|
11
|
+
spec.description = %q{Email service}
|
12
|
+
spec.summary = %q{Send and receive emails}
|
13
|
+
spec.homepage = "https://github.com/RestPack"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "restpack_service"
|
22
|
+
spec.add_dependency "mail"
|
23
|
+
spec.add_dependency "liquid"
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
26
|
+
spec.add_development_dependency "database_cleaner", "~> 1.0.1"
|
27
|
+
spec.add_development_dependency "rake"
|
28
|
+
spec.add_development_dependency "rspec"
|
29
|
+
spec.add_development_dependency "bump"
|
30
|
+
spec.add_development_dependency "shoulda-matchers", "~> 1.4.2"
|
31
|
+
spec.add_development_dependency "factory_girl", "~> 4.0"
|
32
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :api_configuration, class: Hash do
|
3
|
+
sequence(:application_id)
|
4
|
+
|
5
|
+
sequence(:smtp_server) {|n| "smtp.domain#{n}.com" }
|
6
|
+
sequence(:smtp_username) {|n| "username_#{n}" }
|
7
|
+
sequence(:smtp_password) {|n| "password_#{n}" }
|
8
|
+
sequence(:default_from) {|n| "defaultfrom@domain#{n}.com" }
|
9
|
+
|
10
|
+
initialize_with { attributes }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :api_template, class: Hash do
|
3
|
+
sequence(:application_id)
|
4
|
+
|
5
|
+
sequence(:identifier) {|n| "template#{n}" }
|
6
|
+
sequence(:subject_template) {|n| "This is the subject #{n}" }
|
7
|
+
sequence(:html_template) {|n| "This is the <b>html</b> template #{n}" }
|
8
|
+
sequence(:text_template) {|n| "This is the text tempalte #{n}" }
|
9
|
+
|
10
|
+
initialize_with { attributes }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
@@ -0,0 +1,9 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :template, :class => Models::Email::Template do
|
3
|
+
sequence(:application_id)
|
4
|
+
sequence(:identifier) {|n| "template.#{n}" }
|
5
|
+
sequence(:subject_template) {|n| "This is the subject (#{n})" }
|
6
|
+
sequence(:text_template) {|n| "This is the text template (#{n})" }
|
7
|
+
sequence(:html_template) {|n| "This is the <b>html</b> template (#{n})" }
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Jobs::Email::Send do
|
4
|
+
let(:expected_raw_params) { {} }
|
5
|
+
before do
|
6
|
+
send_raw = double('send_raw')
|
7
|
+
send_raw.should_receive(:perform).with(expected_raw_params)
|
8
|
+
subject.stub(:send_raw).and_return(send_raw)
|
9
|
+
subject.stub(:template_path).and_return('../../../../../spec/templates')
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'custom templates' do
|
13
|
+
context 'simple template' do
|
14
|
+
let(:template) {
|
15
|
+
create(:template, subject_template: 'subject', text_template: 'text', html_template: 'html')
|
16
|
+
}
|
17
|
+
let(:expected_raw_params) { {
|
18
|
+
application_id: template[:application_id], template: template[:identifier],
|
19
|
+
subject: 'subject', text_body: 'text', html_body: 'html'
|
20
|
+
} }
|
21
|
+
|
22
|
+
it 'sends an email' do
|
23
|
+
subject.perform({ application_id: template.application_id, template: template.identifier })
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'with a default email address' do
|
28
|
+
let(:template) {
|
29
|
+
create(:template, subject_template: 'subject',
|
30
|
+
text_template: 'text', html_template: 'html', from: 'gavinjoyce@gmail.com')
|
31
|
+
}
|
32
|
+
let(:expected_raw_params) { {
|
33
|
+
application_id: template[:application_id], template: template[:identifier],
|
34
|
+
subject: 'subject', text_body: 'text', html_body: 'html', from: 'gavinjoyce@gmail.com'
|
35
|
+
} }
|
36
|
+
|
37
|
+
it 'sends an email' do
|
38
|
+
subject.perform({ application_id: template.application_id, template: template.identifier })
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'with a default template' do
|
45
|
+
let(:data) { {
|
46
|
+
inviter_name: 'Gavin', group_name: 'MyHome.ie',
|
47
|
+
invitation: {
|
48
|
+
id: 999
|
49
|
+
}
|
50
|
+
} }
|
51
|
+
let(:expected_raw_params) { {
|
52
|
+
application_id: 142857, template: 'group.invitation',
|
53
|
+
subject: "Gavin has invited you to the MyHome.ie group",
|
54
|
+
text_body: "header text\n\n\ninvitation to ID: 999\n\nfooter text",
|
55
|
+
html_body: "<h1>header html</h1>\n\n<hr />\n\n\ninvitation to ID: 999\n\n<hr />\n\n<h2>footer html</h2>",
|
56
|
+
data: data
|
57
|
+
} }
|
58
|
+
|
59
|
+
it 'sends an email' do
|
60
|
+
subject.perform({
|
61
|
+
application_id: 142857, template: 'group.invitation',
|
62
|
+
data: data
|
63
|
+
})
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Models::Email::Configuration do
|
4
|
+
it { should validate_presence_of(:application_id) }
|
5
|
+
it { should validate_presence_of(:smtp_server) }
|
6
|
+
it { should validate_presence_of(:smtp_username) }
|
7
|
+
it { should validate_presence_of(:smtp_password) }
|
8
|
+
it { should validate_presence_of(:default_from) }
|
9
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'restpack_service/support/spec_helper'
|
2
|
+
require 'restpack_email_service'
|
3
|
+
|
4
|
+
config = YAML.load_file('./config/database.yml')
|
5
|
+
ActiveRecord::Base.establish_connection(ENV['DATABASE_URL'] || config['test'])
|
6
|
+
|
7
|
+
migrations_path = File.dirname(__FILE__) + "/../db/migrate"
|
8
|
+
migrator = ActiveRecord::Migrator.new(:up, migrations_path)
|
9
|
+
migrator.migrate
|
10
|
+
|
11
|
+
FactoryGirl.find_definitions
|
12
|
+
|
13
|
+
DatabaseCleaner.strategy = :transaction
|
14
|
+
|
15
|
+
RSpec.configure do |config|
|
16
|
+
config.include FactoryGirl::Syntax::Methods
|
17
|
+
|
18
|
+
config.before(:each) do
|
19
|
+
DatabaseCleaner.start
|
20
|
+
end
|
21
|
+
|
22
|
+
config.after(:each) do
|
23
|
+
DatabaseCleaner.clean
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
footer text
|
@@ -0,0 +1 @@
|
|
1
|
+
header text
|
@@ -0,0 +1 @@
|
|
1
|
+
{{inviter_name}} has invited you to the {{group_name}} group
|
@@ -0,0 +1 @@
|
|
1
|
+
<h1>DEFAULT HTML FOOTER</h1>
|
@@ -0,0 +1 @@
|
|
1
|
+
<h1>DEFAULT HTML HEADER</h1>
|
@@ -0,0 +1 @@
|
|
1
|
+
this is the <b>diagnostocs</b> email
|
@@ -0,0 +1 @@
|
|
1
|
+
[RestPack] Diagnostics Email
|
@@ -0,0 +1 @@
|
|
1
|
+
this is the diagnostocs email
|
@@ -0,0 +1,23 @@
|
|
1
|
+
{{header}}
|
2
|
+
|
3
|
+
<h4>{{inviter}} wants you to join <span style="color: darkgreen">{{group.name}}</span> on ThingRoulette.</h4>
|
4
|
+
|
5
|
+
<div style="margin:20px">
|
6
|
+
<a style="display:inline-block;padding:7px 15px;background-color:#32b12c;color:#fff;font-size:16px;font-weight:bold;border-radius:2px;border:solid 1px #23891f;white-space:nowrap;text-decoration:none" href="{{accept_url}}" target="_blank">Yes Please</a>
|
7
|
+
|
|
8
|
+
<a style="display:inline-block;padding:7px 15px;background-color:#d44b38;color:#fff;font-size:16px;font-weight:bold;border-radius:2px;border:solid 1px #c43b28;white-space:nowrap;text-decoration:none" href="{{reject_url}}" target="_blank">No Thanks</a>
|
9
|
+
</div>
|
10
|
+
|
11
|
+
{{footer}}
|
12
|
+
|
13
|
+
|
14
|
+
<hr />
|
15
|
+
{
|
16
|
+
"inviter": "Gavin Joyce",
|
17
|
+
"accept_url": "http://auth.restpack.org:8012/groups/rsvp?group_id=142857&key=ABCDEFG",
|
18
|
+
"reject_url": "http://auth.restpack.org:8012/groups/rsvp?group_id=142857&reject=1&key=ABCDEFG",
|
19
|
+
"group": {
|
20
|
+
"id": 142857,
|
21
|
+
"name": "Some Group"
|
22
|
+
}
|
23
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
this is the subject
|
metadata
ADDED
@@ -0,0 +1,263 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: restpack_email_service
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gavin Joyce
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-11-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: restpack_service
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: mail
|
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: liquid
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
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: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.3'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.3'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: database_cleaner
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.0.1
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ~>
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.0.1
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: bump
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: shoulda-matchers
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ~>
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 1.4.2
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ~>
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 1.4.2
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: factory_girl
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ~>
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '4.0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ~>
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '4.0'
|
153
|
+
description: Email service
|
154
|
+
email:
|
155
|
+
- gavinjoyce@gmail.com
|
156
|
+
executables: []
|
157
|
+
extensions: []
|
158
|
+
extra_rdoc_files: []
|
159
|
+
files:
|
160
|
+
- .gitignore
|
161
|
+
- .travis.yml
|
162
|
+
- Gemfile
|
163
|
+
- LICENSE.txt
|
164
|
+
- README.md
|
165
|
+
- Rakefile
|
166
|
+
- config/database.yml
|
167
|
+
- db/migrate/20131010102904_create_email_configurations.rb
|
168
|
+
- db/migrate/20131012115851_create_email_templates.rb
|
169
|
+
- lib/restpack_email_service.rb
|
170
|
+
- lib/restpack_email_service/commands/configuration/create.rb
|
171
|
+
- lib/restpack_email_service/commands/configuration/list.rb
|
172
|
+
- lib/restpack_email_service/commands/configuration/update.rb
|
173
|
+
- lib/restpack_email_service/commands/template/create.rb
|
174
|
+
- lib/restpack_email_service/commands/template/list.rb
|
175
|
+
- lib/restpack_email_service/commands/template/update.rb
|
176
|
+
- lib/restpack_email_service/configuration.rb
|
177
|
+
- lib/restpack_email_service/jobs/email/send.rb
|
178
|
+
- lib/restpack_email_service/jobs/email/send_raw.rb
|
179
|
+
- lib/restpack_email_service/models/configuration.rb
|
180
|
+
- lib/restpack_email_service/models/template.rb
|
181
|
+
- lib/restpack_email_service/serializers/configuration.rb
|
182
|
+
- lib/restpack_email_service/serializers/template.rb
|
183
|
+
- lib/restpack_email_service/tasks/db.rake
|
184
|
+
- lib/restpack_email_service/tasks/tasks.rb
|
185
|
+
- lib/restpack_email_service/version.rb
|
186
|
+
- restpack_email_service.gemspec
|
187
|
+
- spec/commands/configuration/create_spec.rb
|
188
|
+
- spec/commands/configuration/list_spec.rb
|
189
|
+
- spec/commands/configuration/update_spec.rb
|
190
|
+
- spec/commands/template/create_spec.rb
|
191
|
+
- spec/commands/template/list_spec.rb
|
192
|
+
- spec/commands/template/update_spec.rb
|
193
|
+
- spec/factories/api_configuration.rb
|
194
|
+
- spec/factories/api_template.rb
|
195
|
+
- spec/factories/template.rb
|
196
|
+
- spec/jobs/email/send_raw_spec.rb
|
197
|
+
- spec/jobs/email/send_spec.rb
|
198
|
+
- spec/models/configuration_spec.rb
|
199
|
+
- spec/models/template_spec.rb
|
200
|
+
- spec/spec_helper.rb
|
201
|
+
- spec/templates/_footer.html.liquid
|
202
|
+
- spec/templates/_footer.text.liquid
|
203
|
+
- spec/templates/_header.html.liquid
|
204
|
+
- spec/templates/_header.text.liquid
|
205
|
+
- spec/templates/group.invitation.html.liquid
|
206
|
+
- spec/templates/group.invitation.subject.liquid
|
207
|
+
- spec/templates/group.invitation.text.liquid
|
208
|
+
- templates/_footer.html.liquid
|
209
|
+
- templates/_footer.text.liquid
|
210
|
+
- templates/_header.html.liquid
|
211
|
+
- templates/_header.text.liquid
|
212
|
+
- templates/diagnostics.html.liquid
|
213
|
+
- templates/diagnostics.subject.liquid
|
214
|
+
- templates/diagnostics.text.liquid
|
215
|
+
- templates/group.invitation.html.liquid
|
216
|
+
- templates/group.invitation.subject.liquid
|
217
|
+
- templates/group.invitation.text.liquid
|
218
|
+
homepage: https://github.com/RestPack
|
219
|
+
licenses:
|
220
|
+
- MIT
|
221
|
+
metadata: {}
|
222
|
+
post_install_message:
|
223
|
+
rdoc_options: []
|
224
|
+
require_paths:
|
225
|
+
- lib
|
226
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
227
|
+
requirements:
|
228
|
+
- - '>='
|
229
|
+
- !ruby/object:Gem::Version
|
230
|
+
version: '0'
|
231
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
232
|
+
requirements:
|
233
|
+
- - '>='
|
234
|
+
- !ruby/object:Gem::Version
|
235
|
+
version: '0'
|
236
|
+
requirements: []
|
237
|
+
rubyforge_project:
|
238
|
+
rubygems_version: 2.0.7
|
239
|
+
signing_key:
|
240
|
+
specification_version: 4
|
241
|
+
summary: Send and receive emails
|
242
|
+
test_files:
|
243
|
+
- spec/commands/configuration/create_spec.rb
|
244
|
+
- spec/commands/configuration/list_spec.rb
|
245
|
+
- spec/commands/configuration/update_spec.rb
|
246
|
+
- spec/commands/template/create_spec.rb
|
247
|
+
- spec/commands/template/list_spec.rb
|
248
|
+
- spec/commands/template/update_spec.rb
|
249
|
+
- spec/factories/api_configuration.rb
|
250
|
+
- spec/factories/api_template.rb
|
251
|
+
- spec/factories/template.rb
|
252
|
+
- spec/jobs/email/send_raw_spec.rb
|
253
|
+
- spec/jobs/email/send_spec.rb
|
254
|
+
- spec/models/configuration_spec.rb
|
255
|
+
- spec/models/template_spec.rb
|
256
|
+
- spec/spec_helper.rb
|
257
|
+
- spec/templates/_footer.html.liquid
|
258
|
+
- spec/templates/_footer.text.liquid
|
259
|
+
- spec/templates/_header.html.liquid
|
260
|
+
- spec/templates/_header.text.liquid
|
261
|
+
- spec/templates/group.invitation.html.liquid
|
262
|
+
- spec/templates/group.invitation.subject.liquid
|
263
|
+
- spec/templates/group.invitation.text.liquid
|