howlr 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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