lettr 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.
- data/MIT-LICENSE +20 -0
- data/README.md +94 -0
- data/Rakefile +29 -0
- data/init.rb +3 -0
- data/lib/lettr.rb +90 -0
- data/lib/lettr/action_mailer.rb +30 -0
- data/lib/lettr/api_mailing.rb +58 -0
- data/lib/lettr/base.rb +34 -0
- data/lib/lettr/collection.rb +28 -0
- data/lib/lettr/deliverable.rb +46 -0
- data/lib/lettr/delivery.rb +35 -0
- data/lib/lettr/mailer.rb +7 -0
- data/lib/lettr/object_converter.rb +69 -0
- data/lib/lettr/recipient.rb +22 -0
- data/lib/lettr/rendered_mailing.rb +60 -0
- data/lib/lettr/resource.rb +68 -0
- data/lib/lettr/whitelist.rb +17 -0
- data/lib/tasks/newsletter_boy.rake +4 -0
- metadata +142 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 [name of plugin creator]
|
2
|
+
|
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:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
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
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
# Lettr
|
2
|
+
Deliver your Emails inside your application through the lettr.de API.
|
3
|
+
|
4
|
+
## Usage
|
5
|
+
There are currently 5 ways of using this gem.
|
6
|
+
|
7
|
+
### Delivery Method
|
8
|
+
Just set the Delivery Method of ActionMailer to :lettr, and all Mailings from Action Mailer will be delivered through our API.
|
9
|
+
|
10
|
+
config.action_mailer.delivery_method = :lettr
|
11
|
+
|
12
|
+
### Lettr::Mailer
|
13
|
+
Let your mailer class inherit from Lettr::Mailer instead of ActionMailer::Base.
|
14
|
+
|
15
|
+
class BookingMailer < Lettr::Mailer
|
16
|
+
FROM = 'intervillas <info@intervillas-florida.com>'
|
17
|
+
def submission_mail(booking)
|
18
|
+
recipients booking.email
|
19
|
+
from FROM
|
20
|
+
subject I18n.t('booking_mailer.ihre_anfrage')
|
21
|
+
body :booking => booking
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
### Manual Mailing
|
26
|
+
|
27
|
+
Lettr.test_mail(:recipient => 'tg@digineo.de', :subject => 'hi', :test => 'some text', :html => 'some html').deliver
|
28
|
+
|
29
|
+
### With templates stored at lettr.de
|
30
|
+
|
31
|
+
#### and a hash
|
32
|
+
Provide a hash containing the variables, that you used in your template.
|
33
|
+
|
34
|
+
Lettr.test_mail(:test => { :variable_1 => 'foo', :variable_2 => 'bar' }).deliver
|
35
|
+
|
36
|
+
#### and an object, which responds to :to_nb_hash
|
37
|
+
|
38
|
+
class TestClass
|
39
|
+
def to_nb_hash
|
40
|
+
{ :variable_1 => 'foo', :variable_2 => 'bar' }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
test_object = TestClass.new
|
45
|
+
|
46
|
+
Lettr.test_mail(:test => test_object ).deliver
|
47
|
+
|
48
|
+
#### automagic
|
49
|
+
If your provided object does not respond to :to_nb_hash, Lettr will try to automatically serialize it based on the variables you used inside your template.
|
50
|
+
Given the following Class Definition:
|
51
|
+
|
52
|
+
class TestClass
|
53
|
+
def variable_1
|
54
|
+
'foo'
|
55
|
+
end
|
56
|
+
def variable_2
|
57
|
+
'bar'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
And the following Template:
|
62
|
+
|
63
|
+
"{{test.variable_1}} - {{test.variable_2}}"
|
64
|
+
|
65
|
+
When you do a request to the Lettr Api
|
66
|
+
|
67
|
+
test_object = TestClass.new
|
68
|
+
Lettr.test_mail(:test => test_object ).deliver
|
69
|
+
|
70
|
+
Lettr will invoke the methods :variable_1 and :variable_2 on test_object and serialize their return values for the request.
|
71
|
+
So the request will result in the following Mailing:
|
72
|
+
|
73
|
+
"foo - bar"
|
74
|
+
|
75
|
+
##### Whitelisting Methods
|
76
|
+
For extra Security it is recommended that you extend your Class with the Lettr::Whitelist module.
|
77
|
+
It provides a class-level helper method to allow any instance method in your templates.
|
78
|
+
|
79
|
+
class TestClass
|
80
|
+
extend Lettr::Whitelist
|
81
|
+
|
82
|
+
nb_white_list :variable_1
|
83
|
+
|
84
|
+
def variable_1
|
85
|
+
'foo'
|
86
|
+
end
|
87
|
+
def variable_2
|
88
|
+
'bar'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
In this example the call to :variable_1 will be ok, but the call to :variable_2 will raise an Exception.
|
93
|
+
|
94
|
+
Copyright (c) 2010 Digineo GmbH, released under the MIT license
|
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
require 'spec/rake/spectask'
|
5
|
+
|
6
|
+
desc 'Default: run specs.'
|
7
|
+
task :default => :specs
|
8
|
+
|
9
|
+
#desc 'Test the newsletter_boy plugin.'
|
10
|
+
#Rake::TestTask.new(:test) do |t|
|
11
|
+
#t.libs << 'lib'
|
12
|
+
#t.libs << 'test'
|
13
|
+
#t.pattern = 'test/**/*_test.rb'
|
14
|
+
#t.verbose = true
|
15
|
+
#end
|
16
|
+
|
17
|
+
desc "Run all specs"
|
18
|
+
Spec::Rake::SpecTask.new('specs') do |t|
|
19
|
+
t.spec_files = FileList['spec/*_spec.rb']
|
20
|
+
end
|
21
|
+
|
22
|
+
desc 'Generate documentation for the newsletter_boy plugin.'
|
23
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
24
|
+
rdoc.rdoc_dir = 'rdoc'
|
25
|
+
rdoc.title = 'Lettr'
|
26
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
27
|
+
rdoc.rdoc_files.include('README')
|
28
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
29
|
+
end
|
data/init.rb
ADDED
data/lib/lettr.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
module Lettr
|
4
|
+
|
5
|
+
require 'lettr/base'
|
6
|
+
require 'lettr/resource'
|
7
|
+
require 'lettr/recipient'
|
8
|
+
require 'lettr/deliverable'
|
9
|
+
require 'lettr/object_converter'
|
10
|
+
require 'lettr/api_mailing'
|
11
|
+
require 'lettr/delivery'
|
12
|
+
require 'lettr/collection'
|
13
|
+
require 'lettr/rendered_mailing'
|
14
|
+
require 'lettr/whitelist'
|
15
|
+
|
16
|
+
mattr_accessor :host
|
17
|
+
mattr_accessor :attributes
|
18
|
+
mattr_accessor :protocol
|
19
|
+
mattr_accessor :api_mailings
|
20
|
+
|
21
|
+
self.attributes ||= %w{ gender firstname lastname street ccode pcode city }
|
22
|
+
self.protocol ||= 'https'
|
23
|
+
self.host ||= 'www.newsletterboy.de'
|
24
|
+
self.api_mailings = {}
|
25
|
+
|
26
|
+
def self.credentials=(credentials)
|
27
|
+
Base.user = credentials[:user]
|
28
|
+
Base.pass = credentials[:pass]
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.subscribe(recipient)
|
32
|
+
raise 'Object muss über das Attribut :email verfügen.' unless recipient.respond_to? :email
|
33
|
+
rec = Recipient.new recipient.email
|
34
|
+
attributes.each do |attribute|
|
35
|
+
if recipient.respond_to? attribute
|
36
|
+
rec.send("#{attribute}=", recipient.send(attribute))
|
37
|
+
end
|
38
|
+
end
|
39
|
+
rec.approved = true
|
40
|
+
unless rec.save
|
41
|
+
raise rec.errors.join(' ')
|
42
|
+
end
|
43
|
+
rec
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.unsubscribe(email)
|
47
|
+
Recipient.delete_by_email(email)
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.load_api_mailing_or_fail_loud *args
|
51
|
+
identifier = args[0]
|
52
|
+
api_mailing = self.api_mailings[identifier] ||= ApiMailing.find(identifier)
|
53
|
+
options = args[1]
|
54
|
+
api_mailing.delivery_options = options
|
55
|
+
return api_mailing
|
56
|
+
rescue RestClient::ResourceNotFound => e
|
57
|
+
_create_rendered_mail( *args )
|
58
|
+
end
|
59
|
+
|
60
|
+
def self._check_options_for_rendered_mail! options
|
61
|
+
[:subject, :recipient].each do |opt|
|
62
|
+
raise ArgumentError.new ":#{opt} is required" unless options.has_key?( opt )
|
63
|
+
end
|
64
|
+
raise ArgumentError.new ":html or :text is required" unless (options.has_key?( :text ) || options.has_key?( :html ))
|
65
|
+
end
|
66
|
+
|
67
|
+
def self._create_rendered_mail *args
|
68
|
+
_check_options_for_rendered_mail! args[1]
|
69
|
+
mailing = RenderedMailing.find args[0].to_s
|
70
|
+
mailing.attributes = args[1].merge(:identifier => args[0].to_s)
|
71
|
+
mailing
|
72
|
+
rescue RestClient::ResourceNotFound
|
73
|
+
mailing = RenderedMailing.new args[1].merge(:identifier => args[0].to_s)
|
74
|
+
unless mailing.save
|
75
|
+
raise ArgumentError.new mailing.errors.join(' ')
|
76
|
+
end
|
77
|
+
mailing
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.api_mailings
|
81
|
+
@@api_mailings
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.method_missing *args, &block
|
85
|
+
load_api_mailing_or_fail_loud *args
|
86
|
+
rescue RestClient::ResourceNotFound
|
87
|
+
super
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Lettr::ActionMailer
|
2
|
+
|
3
|
+
private
|
4
|
+
|
5
|
+
def perform_delivery_lettr mail
|
6
|
+
lettr_request_hashes = []
|
7
|
+
mail.to.each do |recipient|
|
8
|
+
lettr_request_hash = {}
|
9
|
+
lettr_request_hash[:recipient] = recipient
|
10
|
+
lettr_request_hash[:subject] = mail.subject
|
11
|
+
mail.parts.each do |part|
|
12
|
+
case part.content_type
|
13
|
+
when 'text/html'
|
14
|
+
lettr_request_hash[:html] = part.body
|
15
|
+
when 'text/plain'
|
16
|
+
lettr_request_hash[:text] = part.body
|
17
|
+
else
|
18
|
+
lettr_request_hash[:attachments] ||= []
|
19
|
+
lettr_request_hash[:attachments] << part.body
|
20
|
+
end
|
21
|
+
end
|
22
|
+
lettr_request_hashes << lettr_request_hash
|
23
|
+
end
|
24
|
+
identifier = @template
|
25
|
+
lettr_request_hashes.each do |lettr_request_hash|
|
26
|
+
Lettr.send(identifier, lettr_request_hash).deliver
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
Lettr::ApiMailing = Struct.new(:identifier, :subject, :variables) do
|
2
|
+
include Lettr::Resource
|
3
|
+
include Lettr::ObjectConverter
|
4
|
+
include Lettr::Deliverable
|
5
|
+
|
6
|
+
self.path = 'api_mailings'
|
7
|
+
|
8
|
+
attr_writer :delivery_options
|
9
|
+
|
10
|
+
def initialize attributes={}
|
11
|
+
attributes['api_mailing'].each do |key, value|
|
12
|
+
send("#{key}=", value)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def delivery_options= options
|
17
|
+
@recipient = options.delete(:recipient)
|
18
|
+
@delivery_options = options
|
19
|
+
@delivery_options.stringify_keys!
|
20
|
+
end
|
21
|
+
|
22
|
+
def reload
|
23
|
+
self.send(:initialize, 'api_mailing' => self.class.find(identifier).attributes)
|
24
|
+
end
|
25
|
+
|
26
|
+
def append_used_variables
|
27
|
+
@hash.merge! :variables => variables
|
28
|
+
end
|
29
|
+
|
30
|
+
def group_variables
|
31
|
+
@vars = {}
|
32
|
+
variables.each do |var|
|
33
|
+
methods = var.match(/^(\w+)\..+/)
|
34
|
+
@vars[methods[1]] ||= []
|
35
|
+
@vars[methods[1]] << var
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def handle_options
|
40
|
+
# handle options
|
41
|
+
@delivery_options.each do |name, object|
|
42
|
+
case
|
43
|
+
when object.is_a?( Hash )
|
44
|
+
# variablen als @hash übergeben
|
45
|
+
@hash.merge!( name => object )
|
46
|
+
when object.respond_to?( :to_nb_hash )
|
47
|
+
# object liefert variablen
|
48
|
+
@hash.merge!( name => object.to_nb_hash)
|
49
|
+
when object.is_a?( String )
|
50
|
+
@files.merge!( name => File.new(object, 'rb'))
|
51
|
+
else
|
52
|
+
# do magic stuff
|
53
|
+
@hash.merge!(options_to_hash(name))
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
data/lib/lettr/base.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
class Lettr::Base
|
2
|
+
DEFAULT_HEADERS = { :accept => :json }
|
3
|
+
|
4
|
+
cattr_accessor :site, :user, :pass, :content_type
|
5
|
+
attr_reader :client
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@client = RestClient::Resource.new self.class.site_url, self.class.user, self.class.pass
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.site_url
|
12
|
+
"#{Lettr.protocol}://#{Lettr.host}/"
|
13
|
+
end
|
14
|
+
|
15
|
+
def save object
|
16
|
+
path = object.collection_path
|
17
|
+
payload = object.to_payload
|
18
|
+
payload.merge! :files => object.files if object.respond_to?(:files) && object.files
|
19
|
+
client[path].post(payload, DEFAULT_HEADERS)
|
20
|
+
end
|
21
|
+
|
22
|
+
def destroy object
|
23
|
+
client[object.path].delete DEFAULT_HEADERS
|
24
|
+
end
|
25
|
+
|
26
|
+
def find path
|
27
|
+
ActiveSupport::JSON.decode(client[path].get DEFAULT_HEADERS)
|
28
|
+
end
|
29
|
+
|
30
|
+
def [] path
|
31
|
+
client[path]
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class Lettr::Collection
|
2
|
+
def initialize collection, context
|
3
|
+
@collection = collection
|
4
|
+
@vars = []
|
5
|
+
@context = context
|
6
|
+
end
|
7
|
+
|
8
|
+
def add_variable var
|
9
|
+
@vars << var
|
10
|
+
end
|
11
|
+
|
12
|
+
def evaluate
|
13
|
+
@collection.each do |element|
|
14
|
+
hash = {}
|
15
|
+
@vars.each do |var|
|
16
|
+
var = var.split('.').last
|
17
|
+
if element.class.respond_to? :is_whitelisted?
|
18
|
+
raise SecurityError, "method #{var} in class #{element.class} not whitelisted" unless element.class.is_whitelisted?(var)
|
19
|
+
end
|
20
|
+
hash[var] = element.send(var)
|
21
|
+
end
|
22
|
+
@context << hash
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Lettr::Deliverable
|
2
|
+
|
3
|
+
def self.included base
|
4
|
+
base.class_eval do
|
5
|
+
attr_accessor :recipient
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def recipient?
|
10
|
+
!!@recipient
|
11
|
+
end
|
12
|
+
|
13
|
+
def deliver
|
14
|
+
fail ArgumentError, 'Empfänger nicht übergeben' unless recipient?
|
15
|
+
rec = build_delivery_record
|
16
|
+
rec.save
|
17
|
+
if rec.errors.any?
|
18
|
+
# invalidate cache and retry
|
19
|
+
old_recipient = @hash[:recipient]
|
20
|
+
reload
|
21
|
+
recipient = old_recipient
|
22
|
+
rec = build_delivery_record
|
23
|
+
rec.save
|
24
|
+
end
|
25
|
+
rec
|
26
|
+
end
|
27
|
+
|
28
|
+
def build_delivery_record
|
29
|
+
build_initial_delivery_hash
|
30
|
+
group_variables if respond_to? :group_variables
|
31
|
+
handle_options
|
32
|
+
append_used_variables if respond_to? :append_used_variables
|
33
|
+
|
34
|
+
# perform delivery request
|
35
|
+
rec = Lettr::Delivery.new @hash, @files
|
36
|
+
rec
|
37
|
+
end
|
38
|
+
|
39
|
+
def build_initial_delivery_hash
|
40
|
+
@hash = {}
|
41
|
+
@files = {}
|
42
|
+
@hash[ :recipient ] = recipient
|
43
|
+
@hash[ :api_mailing_id ] = identifier
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class Lettr::Delivery
|
2
|
+
include Lettr::Resource
|
3
|
+
attr_reader :files
|
4
|
+
|
5
|
+
def initialize a_hash, files
|
6
|
+
super
|
7
|
+
@params = a_hash
|
8
|
+
@files = files
|
9
|
+
end
|
10
|
+
|
11
|
+
def attributes
|
12
|
+
@params
|
13
|
+
end
|
14
|
+
|
15
|
+
def save
|
16
|
+
unless super
|
17
|
+
dump_json
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def dump_json
|
22
|
+
if defined? Rails
|
23
|
+
path = File.join(Rails.root, 'log')
|
24
|
+
File.open(File.join(path, "lettr-delivery-#{Time.now}.json"), 'w') do |f|
|
25
|
+
f.write attributes.to_json
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def collection_path
|
31
|
+
"api_mailings/#{attributes[:api_mailing_id]}/deliveries"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
data/lib/lettr/mailer.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
module Lettr::ObjectConverter
|
2
|
+
|
3
|
+
def options_to_hash name
|
4
|
+
hash = {}
|
5
|
+
@collections = {}
|
6
|
+
@vars[name.to_s].each do |var|
|
7
|
+
methods = var.split('.')
|
8
|
+
handle_methods(methods, hash)
|
9
|
+
end
|
10
|
+
evaluate_collections
|
11
|
+
hash
|
12
|
+
end
|
13
|
+
|
14
|
+
def handle_methods methods, hash
|
15
|
+
method_call = methods.last
|
16
|
+
context = hash
|
17
|
+
object_context = @delivery_options
|
18
|
+
methods.each_with_index do |method, index|
|
19
|
+
case method
|
20
|
+
# collection variable
|
21
|
+
when /(\w+)\[([\w\.]+)\]/
|
22
|
+
collection_name = $1
|
23
|
+
variable_name = $2
|
24
|
+
if method == method_call
|
25
|
+
handle_new_collection context, object_context, collection_name, variable_name
|
26
|
+
else
|
27
|
+
if is_collection_variable? methods[index+1]
|
28
|
+
handle_collection_variable( methods[index+1], methods.join('.') )
|
29
|
+
break
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# methoden aufruf (letztes element in der kette)
|
34
|
+
when method_call
|
35
|
+
if object_context.class.respond_to? :is_whitelisted?
|
36
|
+
raise SecurityError, "method #{method_call} in class #{object_context.class} not whitelisted" unless object_context.class.is_whitelisted?(method)
|
37
|
+
else
|
38
|
+
warn "no whitelist in class #{object_context.class}"
|
39
|
+
end
|
40
|
+
context[method] = object_context.send(method)
|
41
|
+
# zwischenaufruf
|
42
|
+
else
|
43
|
+
context[method] = {} unless context[method]
|
44
|
+
context = context[method]
|
45
|
+
object_context = index == 0 ? object_context[method] : object_context.send(method)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def handle_new_collection context, object_context, collection_name, variable_name
|
51
|
+
collection = object_context.send(collection_name)
|
52
|
+
context[collection_name] = []
|
53
|
+
@collections[variable_name] = Lettr::Collection.new collection, context[collection_name]
|
54
|
+
end
|
55
|
+
|
56
|
+
def evaluate_collections
|
57
|
+
@collections.each do |key, collection|
|
58
|
+
collection.evaluate
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def is_collection_variable? variable_name
|
63
|
+
@collections.has_key?( variable_name )
|
64
|
+
end
|
65
|
+
|
66
|
+
def handle_collection_variable variable_name, full_variable_name
|
67
|
+
@collections[variable_name].add_variable(full_variable_name)
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Lettr::Recipient = Struct.new( :email, :id, :gender, :firstname, :lastname, :street, :ccode, :pcode, :city, :approved ) do
|
2
|
+
include Lettr::Resource
|
3
|
+
self.path = 'recipients'
|
4
|
+
|
5
|
+
def initialize email
|
6
|
+
super
|
7
|
+
self.email = email
|
8
|
+
end
|
9
|
+
|
10
|
+
def path
|
11
|
+
"#{self.class.path}/#{id}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def collection_path
|
15
|
+
self.class.path
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.delete_by_email email
|
19
|
+
client["#{path}/destroy_by_email"].delete :email => email
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
Lettr::RenderedMailing = Struct.new(:identifier, :subject, :html, :text, :files) do
|
2
|
+
include Lettr::Resource
|
3
|
+
include Lettr::Deliverable
|
4
|
+
|
5
|
+
self.path = 'rendered_mailings'
|
6
|
+
|
7
|
+
attr_writer :created_at
|
8
|
+
attr_accessor :recipient
|
9
|
+
|
10
|
+
def initialize attributes={}
|
11
|
+
super
|
12
|
+
if as = attributes.delete('rendered_mailing')
|
13
|
+
as.each do |k, v|
|
14
|
+
if %w{ identifier subject html text files }.include? k
|
15
|
+
send("#{k}=", v)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
attributes.each do |key, value|
|
20
|
+
send("#{key}=", value)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def attributes= attributes
|
25
|
+
attributes.each do |key, value|
|
26
|
+
send("#{key}=", value)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def handle_options
|
31
|
+
attributes.each do |key, value|
|
32
|
+
if key == :files
|
33
|
+
@files.merge! value if value
|
34
|
+
else
|
35
|
+
@hash.merge! key => value
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_payload
|
41
|
+
{ self.resource_name => attributes_for_create }
|
42
|
+
end
|
43
|
+
|
44
|
+
def path
|
45
|
+
"#{self.class.path}/#{identifier}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def collection_path
|
49
|
+
self.class.path
|
50
|
+
end
|
51
|
+
|
52
|
+
def attributes_for_create
|
53
|
+
as = {}
|
54
|
+
attributes.each do |key, value|
|
55
|
+
as.merge! key => value unless %w{html text files}.include? key.to_s
|
56
|
+
end
|
57
|
+
as
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Lettr::Resource
|
2
|
+
|
3
|
+
def self.included base
|
4
|
+
base.extend ClassMethods
|
5
|
+
base.cattr_accessor :path
|
6
|
+
base.send(:attr_accessor, :errors)
|
7
|
+
base.send(:attr_accessor, :id)
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def find id
|
12
|
+
new(client.find resource_path(id))
|
13
|
+
end
|
14
|
+
|
15
|
+
def client
|
16
|
+
@client ||= Lettr::Base.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def resource_path id
|
20
|
+
"#{path}/#{id}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize *args
|
25
|
+
@errors = []
|
26
|
+
end
|
27
|
+
|
28
|
+
def save
|
29
|
+
res = client.save self
|
30
|
+
self.id = ActiveSupport::JSON.decode(res)[resource_name]['id'] unless res.blank?
|
31
|
+
true
|
32
|
+
rescue RestClient::UnprocessableEntity => e
|
33
|
+
self.errors = ActiveSupport::JSON.decode(e.response)
|
34
|
+
false
|
35
|
+
end
|
36
|
+
|
37
|
+
def client
|
38
|
+
self.class.client
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_payload
|
42
|
+
{ self.resource_name => self.attributes }
|
43
|
+
end
|
44
|
+
|
45
|
+
def destroy
|
46
|
+
client.destroy self
|
47
|
+
end
|
48
|
+
|
49
|
+
def resource_name
|
50
|
+
self.class.to_s.demodulize.underscore
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_json
|
54
|
+
{ resource_name => attributes }.to_json
|
55
|
+
end
|
56
|
+
|
57
|
+
def path
|
58
|
+
"#{self.class.path}/#{id}"
|
59
|
+
end
|
60
|
+
|
61
|
+
def attributes
|
62
|
+
attributes = {}
|
63
|
+
each_pair do |key, value|
|
64
|
+
attributes.merge! key => value
|
65
|
+
end
|
66
|
+
attributes
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Lettr::Whitelist
|
2
|
+
|
3
|
+
def self.extended model
|
4
|
+
model.class_inheritable_accessor :lettr_whitelist
|
5
|
+
model.lettr_whitelist ||= []
|
6
|
+
end
|
7
|
+
|
8
|
+
# fügt methoden zur whitelist hinzu
|
9
|
+
# nb_white_list :number, :test, :name
|
10
|
+
def lettr_white_list *args
|
11
|
+
self.lettr_whitelist = args.map(&:to_s)
|
12
|
+
end
|
13
|
+
|
14
|
+
def is_whitelisted? method
|
15
|
+
lettr_whitelist.include? method.to_s
|
16
|
+
end
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lettr
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 0
|
10
|
+
version: 1.0.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Digineo GmbH
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-11-02 00:00:00 +01:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rest-client
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 13
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 6
|
33
|
+
- 1
|
34
|
+
version: 1.6.1
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rspec
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - <
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 3
|
46
|
+
segments:
|
47
|
+
- 2
|
48
|
+
- 0
|
49
|
+
version: "2.0"
|
50
|
+
type: :development
|
51
|
+
version_requirements: *id002
|
52
|
+
- !ruby/object:Gem::Dependency
|
53
|
+
name: webmock
|
54
|
+
prerelease: false
|
55
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
hash: 3
|
61
|
+
segments:
|
62
|
+
- 0
|
63
|
+
version: "0"
|
64
|
+
type: :development
|
65
|
+
version_requirements: *id003
|
66
|
+
- !ruby/object:Gem::Dependency
|
67
|
+
name: vcr
|
68
|
+
prerelease: false
|
69
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
70
|
+
none: false
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
hash: 3
|
75
|
+
segments:
|
76
|
+
- 0
|
77
|
+
version: "0"
|
78
|
+
type: :development
|
79
|
+
version_requirements: *id004
|
80
|
+
description: NewsletterBoy Api
|
81
|
+
email: kontakt@digineo.de
|
82
|
+
executables: []
|
83
|
+
|
84
|
+
extensions: []
|
85
|
+
|
86
|
+
extra_rdoc_files: []
|
87
|
+
|
88
|
+
files:
|
89
|
+
- lib/lettr/action_mailer.rb
|
90
|
+
- lib/lettr/whitelist.rb
|
91
|
+
- lib/lettr/collection.rb
|
92
|
+
- lib/lettr/resource.rb
|
93
|
+
- lib/lettr/object_converter.rb
|
94
|
+
- lib/lettr/recipient.rb
|
95
|
+
- lib/lettr/mailer.rb
|
96
|
+
- lib/lettr/delivery.rb
|
97
|
+
- lib/lettr/deliverable.rb
|
98
|
+
- lib/lettr/rendered_mailing.rb
|
99
|
+
- lib/lettr/base.rb
|
100
|
+
- lib/lettr/api_mailing.rb
|
101
|
+
- lib/lettr.rb
|
102
|
+
- lib/tasks/newsletter_boy.rake
|
103
|
+
- README.md
|
104
|
+
- Rakefile
|
105
|
+
- MIT-LICENSE
|
106
|
+
- init.rb
|
107
|
+
has_rdoc: true
|
108
|
+
homepage: http://digineo.de
|
109
|
+
licenses: []
|
110
|
+
|
111
|
+
post_install_message:
|
112
|
+
rdoc_options: []
|
113
|
+
|
114
|
+
require_paths:
|
115
|
+
- lib
|
116
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
117
|
+
none: false
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
hash: 3
|
122
|
+
segments:
|
123
|
+
- 0
|
124
|
+
version: "0"
|
125
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
126
|
+
none: false
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
hash: 3
|
131
|
+
segments:
|
132
|
+
- 0
|
133
|
+
version: "0"
|
134
|
+
requirements: []
|
135
|
+
|
136
|
+
rubyforge_project:
|
137
|
+
rubygems_version: 1.3.7
|
138
|
+
signing_key:
|
139
|
+
specification_version: 3
|
140
|
+
summary: NewsletterBoy Api
|
141
|
+
test_files: []
|
142
|
+
|