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.
@@ -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.
@@ -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
@@ -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
@@ -0,0 +1,3 @@
1
+ if defined? ActionMailer::Base
2
+ ActionMailer::Base.send(:include, Lettr::ActionMailer)
3
+ end
@@ -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
@@ -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
+
@@ -0,0 +1,7 @@
1
+ class Lettr::Mailer < ActionMailer::Base
2
+ include Lettr::ActionMailer
3
+
4
+ alias perform_delivery_smtp perform_delivery_lettr
5
+ alias perform_delivery_sendmail perform_delivery_lettr
6
+ alias perform_delivery_test perform_delivery_lettr
7
+ end
@@ -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
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :newsletter_boy do
3
+ # # Task goes here
4
+ # 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
+