postageapp 0.0.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/.gitignore +3 -0
  2. data/LICENSE +1 -1
  3. data/README.md +176 -0
  4. data/Rakefile +14 -12
  5. data/VERSION +1 -1
  6. data/generators/postageapp/postageapp_generator.rb +34 -0
  7. data/generators/postageapp/templates/initializer.rb +3 -0
  8. data/generators/postageapp/templates/postageapp_tasks.rake +78 -0
  9. data/lib/generators/postageapp/postageapp_generator.rb +27 -0
  10. data/lib/postageapp.rb +56 -0
  11. data/lib/postageapp/configuration.rb +91 -0
  12. data/lib/postageapp/failed_request.rb +64 -0
  13. data/lib/postageapp/logger.rb +16 -0
  14. data/lib/postageapp/mailer.rb +48 -0
  15. data/lib/postageapp/mailer/mailer_2.rb +92 -0
  16. data/lib/postageapp/mailer/mailer_3.rb +192 -0
  17. data/lib/postageapp/rails.rb +14 -0
  18. data/lib/postageapp/request.rb +87 -0
  19. data/lib/postageapp/response.rb +39 -0
  20. data/lib/postageapp/utils.rb +30 -0
  21. data/lib/postageapp/version.rb +7 -0
  22. data/postageapp.gemspec +61 -7
  23. data/test/configuration_test.rb +66 -0
  24. data/test/failed_request_test.rb +79 -0
  25. data/test/helper.rb +66 -0
  26. data/test/mailer/action_mailer_2/notifier.rb +64 -0
  27. data/test/mailer/action_mailer_2/notifier/with_body_and_attachment.erb +1 -0
  28. data/test/mailer/action_mailer_2/notifier/with_html_and_text_views.text.html.erb +1 -0
  29. data/test/mailer/action_mailer_2/notifier/with_html_and_text_views.text.plain.erb +1 -0
  30. data/test/mailer/action_mailer_2/notifier/with_simple_view.erb +1 -0
  31. data/test/mailer/action_mailer_2/notifier/with_text_only_view.text.plain.erb +1 -0
  32. data/test/mailer/action_mailer_3/notifier.rb +98 -0
  33. data/test/mailer/action_mailer_3/notifier/with_html_and_text_views.html.erb +1 -0
  34. data/test/mailer/action_mailer_3/notifier/with_html_and_text_views.text.erb +1 -0
  35. data/test/mailer/action_mailer_3/notifier/with_old_api.html.erb +1 -0
  36. data/test/mailer/action_mailer_3/notifier/with_old_api.text.erb +1 -0
  37. data/test/mailer/action_mailer_3/notifier/with_simple_view.erb +1 -0
  38. data/test/mailer/action_mailer_3/notifier/with_text_only_view.text.erb +1 -0
  39. data/test/mailer_2_test.rb +87 -0
  40. data/test/mailer_3_test.rb +104 -0
  41. data/test/mailer_helper_methods_test.rb +24 -0
  42. data/test/postageapp_test.rb +18 -0
  43. data/test/rails_initialization_test.rb +29 -0
  44. data/test/request_integration_test.rb +78 -0
  45. data/test/request_test.rb +81 -0
  46. data/test/response_test.rb +40 -0
  47. metadata +84 -9
  48. data/README.rdoc +0 -17
  49. data/test/test_postageapp.rb +0 -7
data/.gitignore CHANGED
@@ -19,3 +19,6 @@ rdoc
19
19
  pkg
20
20
 
21
21
  ## PROJECT::SPECIFIC
22
+
23
+ test/tmp
24
+ test/log
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 Oleg
1
+ Copyright (c) 2009 The Working Group, Inc
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -0,0 +1,176 @@
1
+ PostageApp Gem
2
+ ==============
3
+
4
+ This is the gem used to integrate Ruby apps with PostageApp service.
5
+ Personalized, mass email sending can be offloaded to PostageApp via JSON based API.
6
+
7
+ Problems, questions, suggestions? Please go to: [help.postageapp.com](http://help.postageapp.com)
8
+
9
+ Installation
10
+ ------------
11
+
12
+ ### Rails 3.x
13
+ Add postageapp gem to your Gemfile:
14
+
15
+ gem 'postageapp'
16
+
17
+ Then from the Rails project's root run:
18
+
19
+ bundle install
20
+ script/rails generate postageapp --api-key PROJECT_API_KEY
21
+
22
+ ### Rails 2.x
23
+ In config/environment.rb add the following:
24
+
25
+ config.gem 'postageapp'
26
+
27
+ Then from the Rails project's root run:
28
+
29
+ rake gems:install
30
+ rake gems:unpack GEM=postageapp
31
+ script/generate postageapp --api-key PROJECT_API_KEY
32
+
33
+ ### Sinatra / Rack / Others
34
+ You'll need to install the gem first:
35
+
36
+ $ sudo gem install postageapp
37
+
38
+ And then it's as simple as doing something like this:
39
+
40
+ require 'postageapp'
41
+
42
+ PostageApp.configure do |config|
43
+ config.api_key = 'PROJECT_API_KEY'
44
+ end
45
+
46
+ Usage
47
+ -----
48
+ Here's an example of sending a message ([See full API documentation](http://TODO/)):
49
+
50
+ request = PostageApp::Request.new(:send_message, {
51
+ 'headers' => { 'from' => 'sender@example.com',
52
+ 'subject' => 'Email Subject' },
53
+ 'recipients' => 'recipient@example.com',
54
+ 'content' => {
55
+ 'text/plain' => 'text email content',
56
+ 'text/html' => 'html email content'
57
+ }
58
+ })
59
+ response = request.send
60
+
61
+ `PostageApp::Response` object allows you to check the status:
62
+
63
+ >> response.status
64
+ => 'ok'
65
+
66
+ Alternatively you may use:
67
+
68
+ >> response.fail?
69
+ => false
70
+ >> response.ok?
71
+ => true
72
+
73
+ Response usually comes back with data:
74
+
75
+ >> response.data
76
+ => { 'message' => { 'id' => '12345' }}
77
+
78
+ ### Recipient Override
79
+ Sometimes you don't want to send emails to real people in your application. For that there's an ability to override to what address all emails will be delivered. All you need to do is modify configuration block like this (in Rails projects it's usually found in `RAILS_ROOT/config/initializers/postageapp.rb`):
80
+
81
+ PostageApp.configure do |config|
82
+ config.api_key = 'PROJECT_API_KEY'
83
+ config.recipient_override = 'you@example.com' unless Rails.env.production?
84
+ end
85
+
86
+ ActionMailer Integration
87
+ ------------------------
88
+ You can quickly convert your existing mailers to use PostageApp service by simply changing `class MyMailer < ActionMailer::Base` to `class MyMailer < PostageApp::Mailer`. And don't forget to `require 'postageapp/mailer'`
89
+
90
+ ### Rails 3.x
91
+
92
+ Here's an example of a mailer in Rails 3 environment:
93
+
94
+ require 'postageapp/mailer'
95
+
96
+ class Notifier < PostageApp::Mailer
97
+
98
+ def signup_notification
99
+
100
+ attachments['example.zip'] = File.read('/path/to/example.zip')
101
+
102
+ headers['Special-Header'] = 'SpecialValue'
103
+
104
+ # PostageApp specific elements:
105
+ postage_template 'example_template'
106
+ postage_variables 'global_variable' => 'value'
107
+
108
+ mail(
109
+ :from => 'test@test.test',
110
+ :subject => 'Test Message',
111
+ :to => {
112
+ 'recipient_1@example.com' => { 'variable' => 'value' },
113
+ 'recipient_2@example.com' => { 'variable' => 'value' }
114
+ })
115
+ end
116
+ end
117
+
118
+ API of previous ActionMailer is partially supported under Rails 3 environment. Please note that it's not 100% integrated, some methods/syntax will not work. You may still define you mailers in this way (but really shouldn't):
119
+
120
+ require 'postageapp/mailer'
121
+
122
+ class Notifier < PostageApp::Mailer
123
+
124
+ def signup_notification
125
+ from 'test@test.test'
126
+ subject 'Test Email'
127
+ recipients 'test@test.test'
128
+ end
129
+ end
130
+
131
+ ### Rails 2.x
132
+
133
+ Here's an example of a mailer you'd set in in a Rails 2 environment:
134
+
135
+ require 'postageapp/mailer'
136
+
137
+ class Notifier < PostageApp::Mailer
138
+ def signup_notification
139
+
140
+ from 'system@example.com'
141
+ subject 'New Account Information'
142
+
143
+ # Recipients can be in any format API allows.
144
+ # Here's an example of a hash format
145
+ recipients ({
146
+ 'recipient_1@example.com' => { 'variable_name_1' => 'value',
147
+ 'variable_name_2' => 'value' },
148
+ 'recipient_2@example.com' => { 'variable_name_1' => 'value',
149
+ 'variable_name_2' => 'value' },
150
+ })
151
+
152
+ attachment :content_type => 'application/zip',
153
+ :filename => 'example.zip',
154
+ :body => File.read('/path/to/example.zip')
155
+
156
+ # PostageApp specific elements:
157
+ postage_template 'example_template'
158
+ postage_variables 'global_variable' => 'value'
159
+
160
+ end
161
+ end
162
+
163
+ Automatic resending in case of failure
164
+ --------------------------------------
165
+ For those ultra rare occasions when api.postageapp.com is not reachable this gem will temporarily store requests and then will attempt to resend them with the next successful connection. In Rails environment it will create a folder: `RAILS_ROOT/tmp/postageapp_failed_requests` and save all failed requests there. On successful resend file for that request will be deleted.
166
+
167
+ For projects other than Rails you'll need to tell where there project_root is at:
168
+
169
+ PostageApp.configure do |config|
170
+ config.api_key = 'PROJECT_API_KEY'
171
+ config.project_root = "/path/to/your/project"
172
+ end
173
+
174
+ Copyright
175
+ ---------
176
+ (C) 2010 [The Working Group, Inc](http://www.twg.ca/)
data/Rakefile CHANGED
@@ -4,23 +4,25 @@ require 'rake'
4
4
  begin
5
5
  require 'jeweler'
6
6
  Jeweler::Tasks.new do |gem|
7
- gem.name = "postageapp"
8
- gem.summary = "Easier way to send email from web apps"
9
- gem.description = "Gem that interfaces with PostageApp.com service to send emails from web apps"
10
- gem.email = "oleg@twg.ca"
11
- gem.homepage = "http://github.com/theworkinggroup/postageapp-gem"
12
- gem.authors = ["Oleg Khabarov, The Working Group Inc"]
13
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
7
+ gem.name = 'postageapp'
8
+ gem.summary = 'Easier way to send email from web apps'
9
+ gem.description = 'Gem that interfaces with PostageApp.com service to send emails from web apps'
10
+ gem.email = 'oleg@twg.ca'
11
+ gem.homepage = 'http://github.com/theworkinggroup/postageapp-gem'
12
+ gem.authors = ['Oleg Khabarov, The Working Group Inc']
13
+
14
+ gem.add_dependency 'json', '1.2.4' # newer versions crash at the moment
15
+ gem.add_development_dependency 'mocha', '>= 0.9.8'
14
16
  end
15
17
  Jeweler::GemcutterTasks.new
16
18
  rescue LoadError
17
- puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
19
+ puts 'Jeweler (or a dependency) not available. Install it with: gem install jeweler'
18
20
  end
19
21
 
20
22
  require 'rake/testtask'
21
23
  Rake::TestTask.new(:test) do |test|
22
24
  test.libs << 'lib' << 'test'
23
- test.pattern = 'test/**/test_*.rb'
25
+ test.pattern = 'test/**/*_test.rb'
24
26
  test.verbose = true
25
27
  end
26
28
 
@@ -28,12 +30,12 @@ begin
28
30
  require 'rcov/rcovtask'
29
31
  Rcov::RcovTask.new do |test|
30
32
  test.libs << 'test'
31
- test.pattern = 'test/**/test_*.rb'
33
+ test.pattern = 'test/**/*_test.rb'
32
34
  test.verbose = true
33
35
  end
34
36
  rescue LoadError
35
37
  task :rcov do
36
- abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
38
+ abort 'RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov'
37
39
  end
38
40
  end
39
41
 
@@ -44,7 +46,7 @@ task :default => :test
44
46
  require 'rake/rdoctask'
45
47
  Rake::RDocTask.new do |rdoc|
46
48
  version = File.exist?('VERSION') ? File.read('VERSION') : ""
47
-
49
+
48
50
  rdoc.rdoc_dir = 'rdoc'
49
51
  rdoc.title = "postageapp #{version}"
50
52
  rdoc.rdoc_files.include('README*')
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.0
1
+ 1.0.0
@@ -0,0 +1,34 @@
1
+ # Wrapper around rake manifest
2
+ Rails::Generator::Commands::Create.class_eval do
3
+ def rake(command)
4
+ system "rake #{command}"
5
+ end
6
+ end
7
+
8
+ # Rails 2 Generator
9
+ class PostageappGenerator < Rails::Generator::Base
10
+
11
+ def add_options!(opt)
12
+ opt.on('-k=key', '--api-key=key') do |value|
13
+ options[:api_key] = value
14
+ end
15
+ end
16
+
17
+ def manifest
18
+ if !options[:api_key]
19
+ puts 'Must pass --api-key with API key of your PostageApp.com project'
20
+ exit
21
+ end
22
+
23
+ record do |m|
24
+ m.template 'initializer.rb', 'config/initializers/postageapp.rb',
25
+ :assigns => { :api_key => options[:api_key] },
26
+ :collision => :force
27
+ m.directory 'lib/tasks'
28
+ m.file 'postageapp_tasks.rake', 'lib/tasks/postageapp_tasks.rake',
29
+ :collision => :force
30
+ m.rake 'postageapp:test'
31
+ end
32
+ end
33
+
34
+ end
@@ -0,0 +1,3 @@
1
+ PostageApp.configure do |config|
2
+ config.api_key = '<%= api_key %>'
3
+ end
@@ -0,0 +1,78 @@
1
+ namespace :postageapp do
2
+
3
+ desc 'Verify postageapp gem installation by requesting project info from PostageApp.com'
4
+ task :test => :environment do
5
+
6
+ puts "Attempting to contact #{PostageApp.configuration.host} ..."
7
+ response = PostageApp::Request.new(:get_project_info).send
8
+
9
+ if response.ok?
10
+ project_name = response.data['project']['name']
11
+ project_url = response.data['project']['url']
12
+ user_emails = response.data['project']['users']
13
+
14
+ puts %{
15
+ Found Project:
16
+ ----------------------------
17
+ Name: #{ project_name }
18
+ URL: #{ project_url }
19
+ Users: #{ user_emails.keys.join(', ') }
20
+ }
21
+
22
+ # Sending test email to all users in the project
23
+ # Most likely a single user if it's a new project
24
+ puts 'Sending test message to users in the project...'
25
+ r = send_test_message(user_emails)
26
+ if r.ok?
27
+ puts "Message was successfully sent!\n\n"
28
+ puts 'Your application is ready to use PostageApp!'
29
+ else
30
+ puts 'Failed to send test message. Please try again. Check logs if issue persists.'
31
+ puts 'This was the response:'
32
+ puts r.to_yaml
33
+ end
34
+
35
+ else
36
+ puts 'Failed to fetch information about your project. This was the response:'
37
+ puts response.to_yaml
38
+ end
39
+ end
40
+
41
+ end
42
+
43
+ HTML_MESSAGE = %{
44
+ <h3> Hello {{name}}, </h3>
45
+ <p> This is a html message generated by Postage plugin. </p>
46
+ <p> If you received this message it means that your application is properly configured and is ready to use PostageApp service. </p>
47
+ <p> Thank you, </p>
48
+ <p> The PostageApp Team </p>
49
+ }
50
+
51
+ TEXT_MESSAGE = %{
52
+ Hello {{name}}
53
+
54
+ This is a plain text message generated by Postage plugin.
55
+ If you received this message it means that your application is properly configured and is ready to use PostageApp service.
56
+
57
+ Thank you,
58
+ The PostageApp Team
59
+ }
60
+
61
+ def send_test_message(recipients)
62
+ recipients_with_variables = {}
63
+ recipients.each do |email, name|
64
+ recipients_with_variables[email] = { 'name' => name }
65
+ end
66
+
67
+ PostageApp::Request.new(:send_message,
68
+ :message => {
69
+ 'text/html' => HTML_MESSAGE,
70
+ 'text/plain' => TEXT_MESSAGE
71
+ },
72
+ :recipients => recipients_with_variables,
73
+ :headers => {
74
+ 'Subject' => '[PostageApp] Test Message',
75
+ 'From' => 'no-return@postageapp.com'
76
+ }
77
+ ).send
78
+ end
@@ -0,0 +1,27 @@
1
+ require 'rails/generators'
2
+
3
+ # Rails 3 Generator
4
+ class PostageappGenerator < Rails::Generators::Base
5
+
6
+ class_option :api_key, :aliases => ['-k=value', '--api-key=value'], :type => :string, :desc => 'Your PostageApp API key'
7
+
8
+ def self.source_root
9
+ @_hoptoad_source_root ||= File.expand_path('../../../../generators/postageapp/templates', __FILE__)
10
+ end
11
+
12
+ def install
13
+ if !options[:api_key]
14
+ puts 'Must pass --api-key with API key of your PostageApp.com project'
15
+ exit
16
+ end
17
+
18
+ template 'initializer.rb', 'config/initializers/postageapp.rb'
19
+ copy_file 'postageapp_tasks.rake', 'lib/tasks/postageapp_tasks.rake'
20
+ puts run('rake postageapp:test')
21
+ end
22
+
23
+ def api_key
24
+ options[:api_key]
25
+ end
26
+
27
+ end
@@ -0,0 +1,56 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+ require 'digest'
4
+ require 'logger'
5
+
6
+ require 'json'
7
+
8
+ require 'postageapp/utils'
9
+ require 'postageapp/version'
10
+ require 'postageapp/configuration'
11
+ require 'postageapp/logger'
12
+ require 'postageapp/request'
13
+ require 'postageapp/failed_request'
14
+ require 'postageapp/response'
15
+
16
+ module PostageApp
17
+
18
+ class Error < StandardError ; end
19
+
20
+ class << self
21
+
22
+ # Accessor for the PostageApp::Configuration object
23
+ attr_accessor :configuration
24
+
25
+ # Call this method to modify your configuration
26
+ #
27
+ # Example:
28
+ # PostageApp.configure do |config|
29
+ # config.api_key = '1234567890abcdef'
30
+ # config.recipient_override = 'test@test.test' if Rails.env.staging?
31
+ # end
32
+ def configure
33
+ self.configuration ||= Configuration.new
34
+ yield self.configuration
35
+ end
36
+
37
+ # Logger for the plugin
38
+ def logger
39
+ raise Error, 'Need configuration to be set before logger can be used' if !configuration
40
+ @logger ||= begin
41
+ configuration.logger || PostageApp::Logger.new(
42
+ if configuration.project_root
43
+ FileUtils.mkdir_p(File.join(File.expand_path(configuration.project_root), 'log'))
44
+ File.join(configuration.project_root, "log/postageapp_#{configuration.environment}.log")
45
+ else
46
+ STDOUT
47
+ end
48
+ )
49
+ end
50
+ end
51
+
52
+ end
53
+ end
54
+
55
+ # Loading Rails hook
56
+ require 'postageapp/rails' if defined?(Rails)