inboxer 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ ---
2
+ BUNDLE_PATH: vendor
3
+ BUNDLE_DISABLE_SHARED_GEMS: '1'
@@ -0,0 +1,2 @@
1
+ vendor/ruby
2
+ pkg
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,69 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ inboxer (0.0.1)
5
+ gli
6
+ hpricot
7
+ phantomjs.rb
8
+ pony
9
+ premailer
10
+
11
+ GEM
12
+ remote: http://rubygems.org/
13
+ specs:
14
+ addressable (2.2.8)
15
+ crack (0.3.1)
16
+ css_parser (1.2.6)
17
+ addressable
18
+ rdoc
19
+ diff-lcs (1.1.3)
20
+ email_spec (1.2.1)
21
+ mail (~> 2.2)
22
+ rspec (~> 2.0)
23
+ gli (1.6.0)
24
+ hpricot (0.8.6)
25
+ htmlentities (4.3.1)
26
+ i18n (0.6.0)
27
+ json (1.7.3)
28
+ mail (2.4.4)
29
+ i18n (>= 0.4.0)
30
+ mime-types (~> 1.16)
31
+ treetop (~> 1.4.8)
32
+ mime-types (1.19)
33
+ phantomjs-mac (0.0.3)
34
+ phantomjs.rb (0.0.4)
35
+ phantomjs-mac
36
+ polyglot (0.3.3)
37
+ pony (1.4)
38
+ mail (> 2.0)
39
+ premailer (1.7.3)
40
+ css_parser (>= 1.1.9)
41
+ htmlentities (>= 4.0.0)
42
+ rake (0.9.2.2)
43
+ rdoc (3.12)
44
+ json (~> 1.4)
45
+ rspec (2.10.0)
46
+ rspec-core (~> 2.10.0)
47
+ rspec-expectations (~> 2.10.0)
48
+ rspec-mocks (~> 2.10.0)
49
+ rspec-core (2.10.1)
50
+ rspec-expectations (2.10.0)
51
+ diff-lcs (~> 1.1.3)
52
+ rspec-mocks (2.10.1)
53
+ treetop (1.4.10)
54
+ polyglot
55
+ polyglot (>= 0.3.1)
56
+ webmock (1.8.7)
57
+ addressable (>= 2.2.7)
58
+ crack (>= 0.1.7)
59
+
60
+ PLATFORMS
61
+ ruby
62
+
63
+ DEPENDENCIES
64
+ email_spec
65
+ inboxer!
66
+ rake
67
+ rdoc
68
+ rspec
69
+ webmock
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Gareth Rushgrove
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 NONINFRINGEMENT.
17
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,80 @@
1
+ Command line utility to send emails of web pages to specified email addresses.
2
+
3
+ Lets say you have some dashboards showing up-to-date information about,
4
+ well, anything. But sometimes going to view the dashboards is too much
5
+ effort and what you want it a regular email report. Or maybe your boss
6
+ wants a nice weekly or month summary.
7
+
8
+ # Usage
9
+
10
+ > inboxer
11
+ Send emails of HTML pages to mailing list based on configuration file
12
+
13
+ usage: inboxer [global options] command [command options]
14
+
15
+ Version: 0.0.1
16
+
17
+ Global Options:
18
+ --help - Show this message
19
+
20
+ Commands:
21
+ help - Shows list of commands or help for one command
22
+ send - Send all emails described in configuration file
23
+ view - Display what is going to happen
24
+
25
+ So, given a yaml configuration file like so:
26
+
27
+ -
28
+ URL: http://example.com/1/
29
+ Subject: Example report 1
30
+ Recipients:
31
+ - test1@example.com
32
+ - test2@example.com
33
+ -
34
+ URL: http://example.com/2/
35
+ Subject: Example report 2
36
+ Recipients:
37
+ - test1@example.com
38
+
39
+ We can run inboxer against it:
40
+
41
+ inboxer send example.yml
42
+
43
+ You would tend to have separate yaml files for different frequencies
44
+ (say daily, weekly, monthly) and then setup a cron to trigger those at
45
+ the relevant times.
46
+
47
+ The default is to send an html and inline css version of the page via
48
+ email. As an alternative you can also send a pdf.
49
+
50
+ inboxer pdf example.yml
51
+
52
+ # Installation
53
+
54
+ inboxer is written in ruby and available as a gem. I'd recommend
55
+ using bundler but you can also just install with:
56
+
57
+ gem install inboxer
58
+
59
+ # License
60
+
61
+ Copyright (c) 2012 Gareth Rushgrove
62
+
63
+ Permission is hereby granted, free of charge, to any person obtaining
64
+ a copy of this software and associated documentation files (the
65
+ "Software"), to deal in the Software without restriction, including
66
+ without limitation the rights to use, copy, modify, merge, publish,
67
+ distribute, sublicense, and/or sell copies of the Software, and to
68
+ permit persons to whom the Software is furnished to do so, subject to
69
+ the following conditions:
70
+
71
+ The above copyright notice and this permission notice shall be
72
+ included in all copies or substantial portions of the Software.
73
+
74
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
75
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
76
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
77
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
78
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
79
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
80
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env rake
2
+ require 'bundler/gem_tasks'
3
+ require 'rspec/core/rake_task'
4
+
5
+ desc "Run rspec tests"
6
+ RSpec::Core::RakeTask.new(:spec) do |t|
7
+ t.pattern = 'spec/*_spec.rb'
8
+ t.rspec_opts = "--color --format documentation"
9
+ end
10
+
11
+ desc "Run rspec tests"
12
+ task :default => [:spec]
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'gli'
5
+ require 'yaml'
6
+ require 'pony'
7
+ require 'premailer'
8
+ require 'inboxer'
9
+
10
+ include GLI
11
+
12
+ program_desc 'Send emails of HTML pages to mailing list based on configuration file'
13
+
14
+ version Inboxer::VERSION
15
+
16
+ desc 'Display what is going to happen'
17
+ command :view do |c|
18
+ c.action do |global_options, options, args|
19
+ raise "Must supply configuration file as argument" unless args.size == 1
20
+ puts "A nested set of web addresses to capture and the email addresses to send them to"
21
+ puts
22
+ puts File.open(args.first).read
23
+ end
24
+ end
25
+
26
+ desc 'Send all emails described in configuration file'
27
+ command :send do |c|
28
+ c.action do |global_options, options, args|
29
+ raise "Must supply configuration file as argument" unless args.size == 1
30
+ report = Inboxer::Reporter.new(args.first)
31
+ report.send!
32
+ end
33
+ end
34
+
35
+ desc 'Send all emails described in configuration file as PDF'
36
+ command :pdf do |c|
37
+ c.action do |global_options, options, args|
38
+ raise "Must supply configuration file as argument" unless args.size == 1
39
+ report = Inboxer::Reporter.new(args.first)
40
+ report.send_pdf!
41
+ end
42
+ end
43
+
44
+
45
+ exit GLI.run(ARGV)
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/inboxer/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Gareth Rushgrove"]
6
+ gem.email = ["gareth@morethanseven.net"]
7
+ gem.homepage = 'https://github.com/garethr/inboxer'
8
+ gem.summary = 'Send web pages to your inbox as html or PDF'
9
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
10
+ gem.files = `git ls-files`.split("\n")
11
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
12
+ gem.name = "inboxer"
13
+ gem.require_paths = ["lib"]
14
+ gem.version = Inboxer::VERSION
15
+
16
+ gem.add_dependency('pony')
17
+ gem.add_dependency('hpricot')
18
+ gem.add_dependency('gli')
19
+ gem.add_dependency('premailer')
20
+ gem.add_dependency('phantomjs.rb')
21
+ gem.add_development_dependency('rake')
22
+ gem.add_development_dependency('rdoc')
23
+ gem.add_development_dependency('rspec')
24
+ gem.add_development_dependency('webmock')
25
+ gem.add_development_dependency('email_spec')
26
+ end
@@ -0,0 +1,45 @@
1
+ require "inboxer/version"
2
+
3
+ require 'yaml'
4
+ require 'pony'
5
+ require 'premailer'
6
+ require 'phantomjs.rb'
7
+
8
+ module Inboxer
9
+
10
+ class Reporter
11
+
12
+ def initialize(filename)
13
+ @yml = YAML::load(File.open(filename))
14
+ end
15
+
16
+ def send!
17
+ @yml.each do |report|
18
+ premailer = Premailer.new(report['URL'], :warn_level => Premailer::Warnings::SAFE)
19
+ report['Recipients'].each do |email|
20
+ Pony.mail(:to => email, :from => report['From'],
21
+ :subject => report['Subject'], :html_body => premailer.to_inline_css,
22
+ :headers => {'X-Software' => 'Inboxer'}
23
+ )
24
+ end
25
+ end
26
+ end
27
+
28
+ def send_pdf!
29
+ @yml.each do |report|
30
+ report['Recipients'].each do |email|
31
+ script = File.expand_path('../rasterize.js', __FILE__)
32
+ file = "/tmp/output.#{rand(36**8).to_s(36)}.pdf"
33
+ output = Phantomjs.run(script, report['URL'], file)
34
+ Pony.mail(:to => email, :from => report['From'],
35
+ :subject => report['Subject'], :body => report['Content'],
36
+ :attachments => {'report.pdf' => File.read(file)},
37
+ :headers => {'X-Software' => 'Inboxer'}
38
+ )
39
+ end
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ end
@@ -0,0 +1,3 @@
1
+ module Inboxer
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,21 @@
1
+ var page = require('webpage').create(),
2
+ address, output, size;
3
+
4
+ if (phantom.args.length < 2 || phantom.args.length > 3) {
5
+ console.log('Usage: rasterize.js URL filename');
6
+ phantom.exit();
7
+ } else {
8
+ address = phantom.args[0];
9
+ output = phantom.args[1];
10
+ page.viewportSize = { width: 600, height: 600 };
11
+ page.open(address, function (status) {
12
+ if (status !== 'success') {
13
+ console.log('Unable to load the address!');
14
+ } else {
15
+ window.setTimeout(function () {
16
+ page.render(output);
17
+ phantom.exit();
18
+ }, 200);
19
+ }
20
+ });
21
+ }
@@ -0,0 +1,11 @@
1
+ -
2
+ URL: http://example.com/1/
3
+ Subject: Example report 1
4
+ Recipients:
5
+ - test1@example.com
6
+ - test2@example.com
7
+ -
8
+ URL: http://example.com/2/
9
+ Subject: Example report 2
10
+ Recipients:
11
+ - test1@example.com
@@ -0,0 +1,6 @@
1
+ -
2
+ URL: http://example.com
3
+ Subject: Example report
4
+ From: from@example.com
5
+ Recipients:
6
+ - test@example.com
@@ -0,0 +1,73 @@
1
+ require_relative 'spec_helper'
2
+
3
+ require 'inboxer'
4
+
5
+ def run_report(fixture='spec/fixtures/single.yml')
6
+ report = Inboxer::Reporter.new(fixture)
7
+ report.send!
8
+ end
9
+
10
+ def run_pdf_report
11
+ report = Inboxer::Reporter.new('spec/fixtures/single.yml')
12
+ report.send_pdf!
13
+ end
14
+
15
+ def run_report_with_multiple_entries
16
+ run_report 'spec/fixtures/multiple.yml'
17
+ end
18
+
19
+ describe 'Running a report with sample data' do
20
+ before do
21
+ @content = "sample content"
22
+ @mailbox = "test@example.com"
23
+ stub_request(:get, "http://example.com/").to_return(:body => @content)
24
+ run_report
25
+ end
26
+
27
+ it 'should send an email' do
28
+ unread_emails_for(@mailbox).size.should == 1
29
+ end
30
+
31
+ it 'the email should contain content from the response' do
32
+ open_last_email_for(@mailbox)
33
+ current_email.should have_body_text @content
34
+ end
35
+
36
+ it 'should have the set subject' do
37
+ open_last_email_for(@mailbox)
38
+ current_email.should have_subject "Example report"
39
+ end
40
+
41
+ it 'should be from the specified address' do
42
+ open_last_email_for(@mailbox)
43
+ current_email.should be_delivered_from "from@example.com"
44
+ end
45
+
46
+ it 'should set an identifying header' do
47
+ open_last_email_for(@mailbox)
48
+ current_email.should have_header("X-Software", "Inboxer")
49
+ end
50
+ end
51
+
52
+ describe 'Running a report with multiple entries' do
53
+ before do
54
+ stub_request(:get, "http://example.com/1/").to_return(:body => "test1")
55
+ stub_request(:get, "http://example.com/2/").to_return(:body => "test2")
56
+ run_report_with_multiple_entries
57
+ end
58
+
59
+ it 'should send several emails' do
60
+ unread_emails_for("test1@example.com").size.should == 2
61
+ unread_emails_for("test2@example.com").size.should == 1
62
+ end
63
+
64
+ it 'should send emails which contain content from the response' do
65
+ open_last_email_for "test1@example.com"
66
+ current_email.should have_subject "Example report 2"
67
+ current_email.should have_body_text "test2"
68
+ open_last_email_for "test2@example.com"
69
+ current_email.should have_subject "Example report 1"
70
+ current_email.should have_body_text "test1"
71
+ end
72
+
73
+ end
@@ -0,0 +1,11 @@
1
+ require 'pony'
2
+ require 'email_spec'
3
+
4
+ RSpec.configure do |config|
5
+ config.mock_with :rspec
6
+ config.include(EmailSpec::Helpers)
7
+ config.include(EmailSpec::Matchers)
8
+ end
9
+
10
+ require 'webmock/rspec'
11
+ WebMock.disable_net_connect!
metadata ADDED
@@ -0,0 +1,182 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: inboxer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Gareth Rushgrove
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-10 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: pony
16
+ requirement: &70299174733000 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70299174733000
25
+ - !ruby/object:Gem::Dependency
26
+ name: hpricot
27
+ requirement: &70299174731800 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70299174731800
36
+ - !ruby/object:Gem::Dependency
37
+ name: gli
38
+ requirement: &70299174729960 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70299174729960
47
+ - !ruby/object:Gem::Dependency
48
+ name: premailer
49
+ requirement: &70299174728220 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *70299174728220
58
+ - !ruby/object:Gem::Dependency
59
+ name: phantomjs.rb
60
+ requirement: &70299174724420 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: *70299174724420
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: &70299174722140 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70299174722140
80
+ - !ruby/object:Gem::Dependency
81
+ name: rdoc
82
+ requirement: &70299174719820 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *70299174719820
91
+ - !ruby/object:Gem::Dependency
92
+ name: rspec
93
+ requirement: &70299174708520 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: *70299174708520
102
+ - !ruby/object:Gem::Dependency
103
+ name: webmock
104
+ requirement: &70299174706820 !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: *70299174706820
113
+ - !ruby/object:Gem::Dependency
114
+ name: email_spec
115
+ requirement: &70299174705500 !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ! '>='
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ type: :development
122
+ prerelease: false
123
+ version_requirements: *70299174705500
124
+ description:
125
+ email:
126
+ - gareth@morethanseven.net
127
+ executables:
128
+ - inboxer
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - .bundle/config
133
+ - .gitignore
134
+ - Gemfile
135
+ - Gemfile.lock
136
+ - LICENSE
137
+ - README.md
138
+ - Rakefile
139
+ - bin/inboxer
140
+ - inboxer.gemspec
141
+ - lib/inboxer.rb
142
+ - lib/inboxer/version.rb
143
+ - lib/rasterize.js
144
+ - spec/fixtures/multiple.yml
145
+ - spec/fixtures/single.yml
146
+ - spec/reporter_spec.rb
147
+ - spec/spec_helper.rb
148
+ homepage: https://github.com/garethr/inboxer
149
+ licenses: []
150
+ post_install_message:
151
+ rdoc_options: []
152
+ require_paths:
153
+ - lib
154
+ required_ruby_version: !ruby/object:Gem::Requirement
155
+ none: false
156
+ requirements:
157
+ - - ! '>='
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ segments:
161
+ - 0
162
+ hash: 2227123263043891155
163
+ required_rubygems_version: !ruby/object:Gem::Requirement
164
+ none: false
165
+ requirements:
166
+ - - ! '>='
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
169
+ segments:
170
+ - 0
171
+ hash: 2227123263043891155
172
+ requirements: []
173
+ rubyforge_project:
174
+ rubygems_version: 1.8.10
175
+ signing_key:
176
+ specification_version: 3
177
+ summary: Send web pages to your inbox as html or PDF
178
+ test_files:
179
+ - spec/fixtures/multiple.yml
180
+ - spec/fixtures/single.yml
181
+ - spec/reporter_spec.rb
182
+ - spec/spec_helper.rb