howlr 0.1.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,3 @@
1
+ === 0.1.0 :: 2008-03-10
2
+
3
+ * First public release.
@@ -0,0 +1,20 @@
1
+ CHANGELOG.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/howlr
6
+ bin/howlr-ctl
7
+ config.example.yml
8
+ examples/active_resource_client_example.rb
9
+ examples/php_client_example.php
10
+ lib/howlr.rb
11
+ lib/howlr/controllers.rb
12
+ lib/howlr/deliverers.rb
13
+ lib/howlr/deliverers/email/mailer/message.rhtml
14
+ lib/howlr/environment.rb
15
+ lib/howlr/message.rb
16
+ lib/howlr/version.rb
17
+ lib/howlr/views.rb
18
+ setup.rb
19
+ test/howlr_test.rb
20
+ test/test_helper.rb
@@ -0,0 +1,11 @@
1
+ = Howlr
2
+
3
+ The Howlr daemon provides RESTful interface for sending outgoing messages.
4
+ Messages are submitted via HTTP and dispatched to other protocols. Currently
5
+ only email (SMTP and Sendmail) is supported, but other delivery methods
6
+ (SMS, IM, etc.) are possible.
7
+
8
+
9
+ Please see Howlr's Google Code site for further information:
10
+
11
+ http://code.google.com/p/howlr/
@@ -0,0 +1,62 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/testtask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/rdoctask'
8
+ require 'rake/contrib/rubyforgepublisher'
9
+ require 'fileutils'
10
+ require 'hoe'
11
+ include FileUtils
12
+ require File.join(File.dirname(__FILE__), 'lib', 'howlr', 'version')
13
+
14
+ AUTHOR = "Matt Zukowski"
15
+ EMAIL = "matt@roughest.net"
16
+ DESCRIPTION = "Sends out emails/messages using a REST API."
17
+ GEM_NAME = "howlr"
18
+ RUBYFORGE_PROJECT = "howlr"
19
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
20
+
21
+ ENV['nodot'] = '1'
22
+
23
+ NAME = "howlr"
24
+ REV = nil
25
+ #REV = `svn info`[/Revision: (\d+)/, 1] rescue nil
26
+ VERS = ENV['VERSION'] || (Howlr::VERSION::STRING + (REV ? ".#{REV}" : ""))
27
+ CLEAN.include ['**/.*.sw?', '*.gem', '.config']
28
+ RDOC_OPTS = ['--quiet', '--title', "howlr #{VERS} documentation",
29
+ "--opname", "index.html",
30
+ "--line-numbers",
31
+ "--main", "README",
32
+ "--inline-source"]
33
+
34
+ class Hoe
35
+ def extra_deps
36
+ @extra_deps.reject { |x| Array(x).first == 'hoe' }
37
+ end
38
+ end
39
+
40
+ # Generate all the Rake tasks
41
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
42
+ hoe = Hoe.new(GEM_NAME, VERS) do |p|
43
+ p.author = AUTHOR
44
+ p.description = DESCRIPTION
45
+ p.email = EMAIL
46
+ p.summary = DESCRIPTION
47
+ p.url = HOMEPATH
48
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
49
+ p.test_globs = ["test/**/*_test.rb"]
50
+ p.clean_globs = CLEAN #An array of file patterns to delete on clean.
51
+
52
+ # == Optional
53
+ #p.changes - A description of the release's latest changes.
54
+ #p.extra_deps - An array of rubygem dependencies.
55
+ #p.spec_extras - A hash of extra values to set in the gemspec.
56
+
57
+ p.extra_deps = [
58
+ ['picnic', '~>0.6.2'],
59
+ ['reststop', '~>0.2.0']
60
+ ]
61
+ p.spec_extras = {:executables => ['howlr', 'howlr-ctl']}
62
+ end
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # ---------------------------------------------------------------------
4
+ # This file is part of Howlr (http://howlr.googlecode.com/).
5
+ #
6
+ # Howlr is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Howlr is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Howlr. If not, see <http://www.gnu.org/licenses/>.
18
+ # ---------------------------------------------------------------------
19
+
20
+ if File.exists?(picnic = File.expand_path(File.dirname(File.expand_path(__FILE__))+'/../vendor/picnic/lib'))
21
+ $: << picnic
22
+ elsif File.exists?(picnic = File.expand_path(File.dirname(File.expand_path(__FILE__))+'/../../picnic/lib'))
23
+ $: << picnic
24
+ else
25
+ require 'rubygems'
26
+ end
27
+
28
+ require 'picnic/cli'
29
+
30
+ cli = Picnic::Cli.new(
31
+ 'howlr',
32
+ :app_path => File.expand_path(File.dirname(File.expand_path(__FILE__)))
33
+ )
34
+
35
+ cli.handle_cli_input
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # ---------------------------------------------------------------------
4
+ # This file is part of Howlr (http://howlr.googlecode.com/).
5
+ #
6
+ # Howlr is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Howlr is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Howlr. If not, see <http://www.gnu.org/licenses/>.
18
+ # ---------------------------------------------------------------------
19
+
20
+ if File.exists?(picnic = File.expand_path(File.dirname(File.expand_path(__FILE__))+'/../vendor/picnic/lib'))
21
+ $: << picnic
22
+ elsif File.exists?(picnic = File.expand_path(File.dirname(File.expand_path(__FILE__))+'/../../picnic/lib'))
23
+ $: << picnic
24
+ else
25
+ require 'rubygems'
26
+ end
27
+
28
+ require 'picnic/service_control'
29
+
30
+ ctl = Picnic::ServiceControl.new('howlr')
31
+
32
+ ctl.handle_cli_input
@@ -0,0 +1,99 @@
1
+ # This is a configuration file for the Howlr RESTful messaging daemon.
2
+
3
+ # AN IMPORTANT NOTE ABOUT YAML CONFIGURATION FILES:
4
+ # !!! Be sure to use spaces instead of tabs for indentation, as YAML is very
5
+ # !!! sensitive to white-space inconsistencies!
6
+
7
+ ##### HTTP SERVER ###################################################################
8
+
9
+ # Under what HTTP environment are you running the Fluxr server? The following methods
10
+ # are currently supported:
11
+ #
12
+ # webrick -- simple stand-alone HTTP server; this is the default method
13
+ # mongrel -- fast stand-alone HTTP server; much faster than webrick, but
14
+ # you'll have to first install the mongrel gem
15
+ #
16
+
17
+ ### webrick example
18
+
19
+ server: webrick
20
+ port: 7008
21
+
22
+ ### webrick SSL example
23
+
24
+ #server: webrick
25
+ #port: 443
26
+ #ssl_cert: /path/to/your/ssl.pem
27
+
28
+ # if the private key is separate from cert:
29
+ #ssl_key: /path/to/your/private_key.pem
30
+
31
+
32
+ ### mongrel example
33
+
34
+ #server: mongrel
35
+ #port: 7008
36
+
37
+ # It is possible to run mongrel over SSL, but you will need to use a reverse proxy
38
+ # (try Pound or Apache).
39
+
40
+ ##### MAILER ##########################################################################
41
+
42
+ # By default, howlr will try to use the local sendmail server. This might work as-is,
43
+ # but chances are you'll probably have to use SMTP. Below is an example of an SMTP
44
+ # configuration.
45
+ #
46
+ # See http://api.rubyonrails.com/classes/ActionMailer/Base.html for detailed
47
+ # mailer configuration documentation.
48
+
49
+ #mailer:
50
+ # delivery_method: smtp
51
+ # smtp_settings:
52
+ # address: smtp.example.com
53
+ # user_name: foo
54
+ # password: bar
55
+ # authentication: :plain
56
+
57
+
58
+ ##### AUTHENTICATION ##################################################################
59
+
60
+ # Howlr supports two methods for authentication: Basic HTTP and CAS.
61
+
62
+ ### Basic HTTP Example
63
+ # Uset the following if you want Howlr to demand a username and password from the user
64
+ # using basic HTTP authentication clients. Note that this isn't very secure unless
65
+ # you run Taskr over HTTPS (see the webrick SSL example above).
66
+
67
+ #authentication:
68
+ # method: basic
69
+ # username: howlr
70
+ # password: howl!
71
+
72
+ ### CAS Example
73
+ # Uset the following if you want Howlr to demand a username and password using
74
+ # Single Sign-On CAS (Central Authentication System). For more information on CAS see
75
+ # http://code.google.com/p/rubycas-server/.
76
+ # The cas_base_url setting should be the URL of your CAS server.
77
+
78
+ #authenticatoin:
79
+ # method: cas
80
+ # cas_base_url: https://login.example.foo/cas
81
+
82
+
83
+ ##### LOGGING #########################################################################
84
+
85
+ # This log is where you'll want to look in case of problems.
86
+ #
87
+ # By default, we will try to create a log file named 'howlr.log' in the current
88
+ # directory (the directory where you're running howlr from). A better place to put
89
+ # the log is in /var/log, but you will have to run howlr as root or otherwise give
90
+ # it permissions.
91
+ #
92
+ # Set the level to DEBUG if you want more detailed logging. Other options are
93
+ # INFO, WARN, and ERROR.
94
+
95
+ log:
96
+ file: howlr.log
97
+ level: INFO
98
+ # file: /var/log/howlr.log
99
+ # level: DEBUG
@@ -0,0 +1,21 @@
1
+ require 'active_resource'
2
+
3
+ # Define the proxy class
4
+ class Message < ActiveResource::Base
5
+ self.site = 'http://localhost:7008'
6
+ end
7
+
8
+ message = Message.new
9
+ message.subject = "Howlr Test"
10
+ message.body = "This is just a test!"
11
+ message.from = "Test McTestski <test@example.foo>"
12
+ message.recipients = "John Doe <jdoe@example.foo>; Sally Smith <ssmith@example.foo>"
13
+
14
+ # Saving the message commits it to the server, causing the message to
15
+ # be sent out.
16
+ message.save
17
+
18
+ # The server temporarily stores copies of all sent messages. Saving a
19
+ # message (i.e. sending it) assigns to it a unique ID. We can use this
20
+ # ID to later retrieve a copy of this message.
21
+ message2 = Message.find(message.id)
@@ -0,0 +1,65 @@
1
+ <?php
2
+
3
+ /**
4
+ To use this exmple, you will need the Zend Framework from:
5
+
6
+ http://framework.zend.com/download
7
+
8
+ For more information on using the Zendr_Rest_Client, see:
9
+
10
+ - http://framework.zend.com/manual/en/zend.rest.client.html
11
+ - http://www.pixelated-dreams.com/archives/243-Next-Generation-REST-Web-Services-Client.html
12
+ **/
13
+
14
+ require 'Zend/Rest/Client.php';
15
+
16
+ $howlr_site_url = "http://localhost:7008";
17
+
18
+ /**
19
+ If you have your Howlr server configured to require authentication, uncomment the next block
20
+ and change the username ans password to whatever you have in your config.yml file.
21
+ **/
22
+ //$username = 'howlr';
23
+ //$password = 'howl!';
24
+ //Zend_Rest_Client::getHttpClient()->setAuth($username, $password);
25
+
26
+ $rest = new Zend_Rest_Client($howlr_site_url);
27
+
28
+ $data = array(
29
+ 'from' => "Test McTestski <tmctestski@example.foo>",
30
+ 'recipients' => "John Doe <jdoe@example.foo>; Sally Smith <ssmith@example.foo>",
31
+ 'subject' => "Testing Howlr",
32
+ 'body' => "Did it work?"
33
+ );
34
+
35
+ $r = $rest->post('/messages.xml', $data);
36
+
37
+ /**
38
+ You can also send out HTML emails.
39
+ **/
40
+
41
+ $rest = new Zend_Rest_Client($howlr_site_url);
42
+
43
+ $html = "
44
+ <html>
45
+ <head>
46
+ <title>Test</title>
47
+ </head>
48
+ <body>
49
+ <h1>This is a test!</h1>
50
+ <p>Did it work?</p>
51
+ </body>
52
+ </html>
53
+ ";
54
+
55
+ $data = array(
56
+ 'from' => "Test McTestski <tmctestski@example.foo>",
57
+ 'recipients' => "John Doe <jdoe@example.foo>",
58
+ 'subject' => "Testing Howlr HTML",
59
+ 'body' => $html,
60
+ 'content_type' => 'text/html'
61
+ );
62
+
63
+ $r = $rest->post('/messages.xml', $data);
64
+
65
+ ?>
@@ -0,0 +1,46 @@
1
+ # This file is part of Howlr.
2
+ #
3
+ # Howlr is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # Howlr is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with Howlr. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ $: << File.dirname(File.expand_path(__FILE__))
17
+ require 'howlr/environment'
18
+
19
+ Camping.goes :Howlr
20
+
21
+ Howlr.picnic!
22
+
23
+ require 'howlr/views'
24
+ require 'howlr/controllers'
25
+
26
+ # defaults, overridden by your conf file
27
+ $CONF[:authentication] ||= {:username => 'howlr', :password => 'howl!'}
28
+ $CONF[:mailer] ||= {:delivery_method => 'sendmail'}
29
+
30
+ if Howlr::Conf[:authentication]
31
+ Howlr.authenticate_using(Howlr::Conf[:authentication][:method] || :basic)
32
+ end
33
+
34
+ module Howlr
35
+ def self.authenticate(credentials)
36
+ credentials[:username] == Howlr::Conf[:authentication][:username] &&
37
+ credentials[:password] == Howlr::Conf[:authentication][:password]
38
+ end
39
+ end
40
+
41
+ def Howlr.create
42
+ Howlr::Deliverers::Email::Mailer.delivery_method = Howlr::Conf[:mailer][:delivery_method]
43
+ Howlr::Deliverers::Email::Mailer.smtp_settings = Howlr::Conf[:mailer][:smtp_settings]
44
+ end
45
+
46
+ Howlr.start_picnic
@@ -0,0 +1,129 @@
1
+ # This file is part of Howlr.
2
+ #
3
+ # Howlr is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # Howlr is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with Howlr. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require 'howlr/message'
17
+ require 'restr'
18
+
19
+ module Howlr::Controllers
20
+ # Messages are created and delivered via this resource.
21
+ class Messages < REST 'messages'
22
+ # Contains a list of messages that were created.
23
+ # Note that this is not persistent! This value is wiped when the server
24
+ # is shut down.
25
+ @@messages = []
26
+
27
+ # Render a form for manually inputing a new message.
28
+ def new
29
+ render :new_message
30
+ end
31
+
32
+ # Show the message with the given id created by this server.
33
+ def read(id)
34
+ puts "Looking for #{id}"
35
+ @message = @@messages.find{|m| m.id == id}
36
+ puts @format
37
+ if @message
38
+ render :message
39
+ else
40
+ _error("There is no recently sent message with id #{id}.", 404)
41
+ end
42
+ end
43
+
44
+ # Create and send a new message.
45
+ def create
46
+ if @input['rest'] == '1' && @input['0']
47
+ # for PHP Zend_Rest_Client compatibility
48
+ data = @input['0']
49
+ else
50
+ data = @input
51
+ end
52
+
53
+ data[:author] ||= @env['REMOTE_HOST']
54
+
55
+ $LOG.debug "Creating new message from: #{data.inspect}"
56
+
57
+
58
+ @message = Howlr::Message.new(data)
59
+ $LOG.debug "Sending message: #{@message.inspect}"
60
+
61
+ @@messages << @message
62
+
63
+ begin
64
+ @message.send
65
+ rescue Howlr::Message::CallbackError => e
66
+ return _error("Error while executing callback: #{e.underlying_error}", 500, e.underlying_error)
67
+ rescue => e
68
+ return _error("Error while sending message: #{e.message}", 500, e)
69
+ end
70
+
71
+ @headers['Location'] = "/messages/#{@message.id}?format=#{@format}"
72
+
73
+ render :message
74
+ end
75
+ end
76
+
77
+ # Can be used as a callback target for messages. This makes it possible
78
+ # to receive a notification when a message is sent out.
79
+ #
80
+ # For example, set up your outgoing message's callback values as follows:
81
+ #
82
+ # callback_url: http://howlr.example.com/delivery_notifications
83
+ # callback_method: post
84
+ #
85
+ # Now when the message is sent, a delivery notice will be sent back to
86
+ # the sender, informing them of whether the message was successfully
87
+ # sent out, or if some sort of delivery error occurred.
88
+ #
89
+ # The real-world usefulness of this is probably questionable. It's just
90
+ # meant to illustrate how a message callback receiver can be implemented.
91
+ class DeliveryNotifications < REST 'delivery_notifications'
92
+ def create
93
+ $LOG.debug "Creating delivery notification from: #{@input.inspect}"
94
+
95
+ auth = {
96
+ :username => Conf[:auth_username],
97
+ :password => Conf[:auth_password]
98
+ }
99
+
100
+ begin
101
+ m = Restr.get("http://localhost:#{Conf[:port]}#{Conf[:uri_path]}messages",
102
+ {:id => @input[:message_id], :format => 'XML'},
103
+ auth)
104
+
105
+ to = m['from']
106
+ subject = "Howlr Message Delivery Notification"
107
+
108
+ body = "Your message regarding #{m['subject'].inspect} was " +
109
+ (@input[:send_success] == 'true' ? '' : 'NOT') +
110
+ " sent successfully to #{@input[:recipient_address]}."
111
+
112
+ data = {
113
+ :recipients => to,
114
+ :body => body,
115
+ :subject => subject,
116
+ :from => @input[:recipient_address]
117
+ }
118
+ puts data.inspect
119
+ Restr.post("http://localhost:#{Conf.port}#{Conf.uri_path}messages",
120
+ data, auth)
121
+
122
+ rescue Net::HTTPServerException, Net::HTTPError => e
123
+ return _error($LAST_ERROR_BODY, e.response.code, e)
124
+ rescue => e
125
+ return _error(e.inspect, 500, e)
126
+ end
127
+ end
128
+ end
129
+ end