hiroshi-pony 0.3.1

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.
data/README.rdoc ADDED
@@ -0,0 +1,62 @@
1
+ = Pony, the express way to send email in Ruby
2
+
3
+ == Overview
4
+
5
+ Ruby no longer has to be jealous of PHP's mail() function, which can send an email in a single command.
6
+
7
+ Pony.mail(:to => 'you@example.com', :from => 'me@example.com', :subject => 'hi', :body => 'Hello there.')
8
+
9
+ Any option key may be omitted except for :to.
10
+
11
+ == Transport
12
+
13
+ Pony uses /usr/sbin/sendmail to send mail if it is available, otherwise it uses SMTP to localhost.
14
+
15
+ This can be over-ridden if you specify a via option
16
+
17
+ Pony.mail(:to => 'you@example.com', :via => :smtp) # sends via SMTP
18
+
19
+ Pony.mail(:to => 'you@example.com', :via => :sendmail) # sends via sendmail
20
+
21
+ You can also specify options for SMTP:
22
+
23
+ Pony.mail(:to => 'you@example.com', :via => :smtp, :smtp => {
24
+ :host => 'smtp.yourserver.com',
25
+ :port => '25',
26
+ :user => 'user',
27
+ :pass => 'pass',
28
+ :auth => :plain # :plain, :login, :cram_md5, no auth by default
29
+ :domain => "localhost.localdomain" # the HELO domain provided by the client to the server
30
+ }
31
+
32
+ == TLS/SSL
33
+
34
+ With smtp transport it also possible to use TLS/SSL:
35
+
36
+ Pony.mail(:to => 'you@example.com', :via => :smtp, :smtp => {
37
+ :host => 'smtp.gmail.com',
38
+ :port => '587',
39
+ :tls => true,
40
+ :user => 'user',
41
+ :pass => 'pass',
42
+ :auth => :plain # :plain, :login, :cram_md5, no auth by default
43
+ :domain => "localhost.localdomain" # the HELO domain provided by the client to the server
44
+ })
45
+
46
+ == Attachments
47
+
48
+ You can attach a file or two with the :attachments option:
49
+
50
+ Pony.mail(..., :attachments => {"foo.zip" => File.read("path/to/foo.zip"), "hello.txt" => "hello!"})
51
+
52
+ == Meta
53
+
54
+ Written by Adam Wiggins
55
+
56
+ Patches contributed by: Mathieu Martin, Arun Thampi, Thomas Hurst, Stephen
57
+ Celis, Othmane Benkirane, and Neil Mock
58
+
59
+ Released under the MIT License: http://www.opensource.org/licenses/mit-license.php
60
+
61
+ http://github.com/adamwiggins/pony
62
+
data/Rakefile ADDED
@@ -0,0 +1,73 @@
1
+ require 'rake'
2
+ require 'spec/rake/spectask'
3
+
4
+ desc "Run all specs"
5
+ Spec::Rake::SpecTask.new('spec') do |t|
6
+ t.spec_files = FileList['spec/*_spec.rb']
7
+ end
8
+
9
+ desc "Print specdocs"
10
+ Spec::Rake::SpecTask.new(:doc) do |t|
11
+ t.spec_opts = ["--format", "specdoc", "--dry-run"]
12
+ t.spec_files = FileList['spec/*_spec.rb']
13
+ end
14
+
15
+ desc "Run all examples with RCov"
16
+ Spec::Rake::SpecTask.new('rcov') do |t|
17
+ t.spec_files = FileList['spec/*_spec.rb']
18
+ t.rcov = true
19
+ t.rcov_opts = ['--exclude', 'examples']
20
+ end
21
+
22
+ task :default => :spec
23
+
24
+ ######################################################
25
+
26
+ require 'rake'
27
+ require 'rake/testtask'
28
+ require 'rake/clean'
29
+ require 'rake/gempackagetask'
30
+ require 'fileutils'
31
+
32
+ version = "0.3"
33
+ name = "pony"
34
+
35
+ spec = Gem::Specification.new do |s|
36
+ s.name = name
37
+ s.version = version
38
+ s.summary = "Send email in one command: Pony.mail(:to => 'someone@example.com', :body => 'hello')"
39
+ s.description = "Send email in one command: Pony.mail(:to => 'someone@example.com', :body => 'hello')"
40
+ s.author = "Adam Wiggins"
41
+ s.email = "adam@heroku.com"
42
+ s.homepage = "http://github.com/adamwiggins/pony"
43
+ s.rubyforge_project = "pony"
44
+
45
+ s.platform = Gem::Platform::RUBY
46
+ s.has_rdoc = false
47
+
48
+ s.files = %w(Rakefile) + Dir.glob("{lib,spec}/**/*")
49
+
50
+ s.require_path = "lib"
51
+ s.add_dependency( 'tmail', '~> 1.0' )
52
+ end
53
+
54
+ Rake::GemPackageTask.new(spec) do |p|
55
+ p.need_tar = true if RUBY_PLATFORM !~ /mswin/
56
+ end
57
+
58
+ task :install => [ :package ] do
59
+ sh %{sudo gem install pkg/#{name}-#{version}.gem}
60
+ end
61
+
62
+ task :uninstall => [ :clean ] do
63
+ sh %{sudo gem uninstall #{name}}
64
+ end
65
+
66
+ Rake::TestTask.new do |t|
67
+ t.libs << "spec"
68
+ t.test_files = FileList['spec/*_spec.rb']
69
+ t.verbose = true
70
+ end
71
+
72
+ CLEAN.include [ 'pkg', '*.gem', '.config' ]
73
+
data/lib/pony.rb ADDED
@@ -0,0 +1,89 @@
1
+ require 'rubygems'
2
+ require 'net/smtp'
3
+ begin
4
+ require 'smtp_tls'
5
+ rescue LoadError
6
+ end
7
+ require 'base64'
8
+ begin
9
+ require 'tmail'
10
+ rescue LoadError
11
+ require 'actionmailer'
12
+ end
13
+
14
+ module Pony
15
+ def self.mail(options)
16
+ raise(ArgumentError, ":to is required") unless options[:to]
17
+
18
+ via = options.delete(:via)
19
+ if via.nil?
20
+ transport build_tmail(options)
21
+ else
22
+ if via_options.include?(via.to_s)
23
+ send("transport_via_#{via}", build_tmail(options), options)
24
+ else
25
+ raise(ArgumentError, ":via must be either smtp or sendmail")
26
+ end
27
+ end
28
+ end
29
+
30
+ def self.build_tmail(options)
31
+ mail = TMail::Mail.new
32
+ mail.to = options[:to]
33
+ mail.from = options[:from] || 'pony@unknown'
34
+ mail.subject = options[:subject]
35
+ mail.body = options[:body] || ""
36
+ (options[:attachments] || []).each do |name, body|
37
+ attachment = TMail::Mail.new
38
+ attachment.transfer_encoding = "base64"
39
+ attachment.body = Base64.encode64(body)
40
+ # attachment.set_content_type # TODO: if necessary
41
+ attachment.set_content_disposition "attachment", "filename" => name
42
+ mail.parts.push attachment
43
+ end
44
+ mail
45
+ end
46
+
47
+ def self.sendmail_binary
48
+ @sendmail_binary ||= `which sendmail`.chomp
49
+ end
50
+
51
+ def self.transport(tmail)
52
+ if File.executable? sendmail_binary
53
+ transport_via_sendmail(tmail)
54
+ else
55
+ transport_via_smtp(tmail)
56
+ end
57
+ end
58
+
59
+ def self.via_options
60
+ %w(sendmail smtp)
61
+ end
62
+
63
+ def self.transport_via_sendmail(tmail, options={})
64
+ IO.popen('-', 'w+') do |pipe|
65
+ if pipe
66
+ pipe.write(tmail.to_s)
67
+ else
68
+ exec(sendmail_binary, *tmail.to)
69
+ end
70
+ end
71
+ end
72
+
73
+ def self.transport_via_smtp(tmail, options={:smtp => {}})
74
+ default_options = {:smtp => { :host => 'localhost', :port => '25', :domain => 'localhost.localdomain' }}
75
+ o = default_options[:smtp].merge(options[:smtp])
76
+ smtp = Net::SMTP.new(o[:host], o[:port])
77
+ if o[:tls]
78
+ raise "You may need: gem install smtp_tls" unless smtp.respond_to?(:enable_starttls)
79
+ smtp.enable_starttls
80
+ end
81
+ if o.include?(:auth)
82
+ smtp.start(o[:domain], o[:user], o[:password], o[:auth])
83
+ else
84
+ smtp.start(o[:domain])
85
+ end
86
+ smtp.send_message tmail.to_s, tmail.from, tmail.to
87
+ smtp.finish
88
+ end
89
+ end
data/pony.gemspec ADDED
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{pony}
5
+ s.version = "0.3.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Hiroshi Saito"]
9
+ s.date = %q{2009-07-10}
10
+ s.description = %q{adamwiggins/pony + file attachment (without GAE) + TLS.}
11
+ s.email = %q{HiroshiSaito@gmail.com}
12
+ s.files = ["README.rdoc", "Rakefile", "lib/pony.rb", "pony.gemspec", "spec/base.rb", "spec/pony_spec.rb"]
13
+ s.has_rdoc = false
14
+ s.homepage = %q{http://github.com/hiroshi/pony}
15
+ s.rdoc_options = ["--inline-source", "--charset=UTF-8"]
16
+ s.require_paths = ["lib"]
17
+ s.rubygems_version = %q{1.3.1}
18
+ s.summary = s.description
19
+ end
data/spec/base.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+
4
+ require File.dirname(__FILE__) + '/../lib/pony'
data/spec/pony_spec.rb ADDED
@@ -0,0 +1,139 @@
1
+ require File.dirname(__FILE__) + '/base'
2
+
3
+ describe Pony do
4
+ it "sends mail" do
5
+ Pony.should_receive(:transport) do |tmail|
6
+ tmail.to.should == [ 'joe@example.com' ]
7
+ tmail.from.should == [ 'sender@example.com' ]
8
+ tmail.subject.should == 'hi'
9
+ tmail.body.should == 'Hello, Joe.'
10
+ end
11
+ Pony.mail(:to => 'joe@example.com', :from => 'sender@example.com', :subject => 'hi', :body => 'Hello, Joe.')
12
+ end
13
+
14
+ it "requires :to param" do
15
+ Pony.stub!(:transport)
16
+ lambda { Pony.mail({}) }.should raise_error(ArgumentError)
17
+ end
18
+
19
+ it "doesn't require any other param" do
20
+ Pony.stub!(:transport)
21
+ lambda { Pony.mail(:to => 'joe@example.com') }.should_not raise_error
22
+ end
23
+
24
+ ####################
25
+
26
+ describe "builds a TMail object with field:" do
27
+ it "to" do
28
+ Pony.build_tmail(:to => 'joe@example.com').to.should == [ 'joe@example.com' ]
29
+ end
30
+
31
+ it "from" do
32
+ Pony.build_tmail(:from => 'joe@example.com').from.should == [ 'joe@example.com' ]
33
+ end
34
+
35
+ it "from (default)" do
36
+ Pony.build_tmail({}).from.should == [ 'pony@unknown' ]
37
+ end
38
+
39
+ it "subject" do
40
+ Pony.build_tmail(:subject => 'hello').subject.should == 'hello'
41
+ end
42
+
43
+ it "body" do
44
+ Pony.build_tmail(:body => 'What do you know, Joe?').body.should == 'What do you know, Joe?'
45
+ end
46
+
47
+ it "attachments" do
48
+ tmail = Pony.build_tmail(:attachments => {"foo.txt" => "content of foo.txt"})
49
+ tmail.should have(1).parts
50
+ tmail.parts.first.to_s.should == <<-PART
51
+ Content-Transfer-Encoding: Base64
52
+ Content-Disposition: attachment; filename=foo.txt
53
+
54
+ Y29udGVudCBvZiBmb28udHh0
55
+ PART
56
+ end
57
+ end
58
+
59
+ describe "transport" do
60
+ it "transports via the sendmail binary if it exists" do
61
+ File.stub!(:executable?).and_return(true)
62
+ Pony.should_receive(:transport_via_sendmail).with(:tmail)
63
+ Pony.transport(:tmail)
64
+ end
65
+
66
+ it "transports via smtp if no sendmail binary" do
67
+ Pony.stub!(:sendmail_binary).and_return('/does/not/exist')
68
+ Pony.should_receive(:transport_via_smtp).with(:tmail)
69
+ Pony.transport(:tmail)
70
+ end
71
+
72
+ it "transports mail via /usr/sbin/sendmail binary" do
73
+ pipe = mock('sendmail pipe')
74
+ IO.should_receive(:popen).with('-',"w+").and_yield(pipe)
75
+ pipe.should_receive(:write).with('message')
76
+ Pony.transport_via_sendmail(mock('tmail', :to => 'to', :from => 'from', :to_s => 'message'))
77
+ end
78
+
79
+ describe "SMTP transport" do
80
+ before do
81
+ @smtp = mock('net::smtp object')
82
+ @smtp.stub!(:start)
83
+ @smtp.stub!(:send_message)
84
+ @smtp.stub!(:finish)
85
+ Net::SMTP.stub!(:new).and_return(@smtp)
86
+ end
87
+
88
+ it "defaults to localhost as the SMTP server" do
89
+ Net::SMTP.should_receive(:new).with('localhost', '25').and_return(@smtp)
90
+ Pony.transport_via_smtp(mock('tmail', :to => 'to', :from => 'from', :to_s => 'message'))
91
+ end
92
+
93
+ it "uses SMTP authorization when auth key is provided" do
94
+ o = { :smtp => { :user => 'user', :password => 'password', :auth => 'plain'}}
95
+ @smtp.should_receive(:start).with('localhost.localdomain', 'user', 'password', 'plain')
96
+ Pony.transport_via_smtp(mock('tmail', :to => 'to', :from => 'from', :to_s => 'message'), o)
97
+ end
98
+
99
+ it "enable starttls when tls option is true" do
100
+ o = { :smtp => { :user => 'user', :password => 'password', :auth => 'plain', :tls => true}}
101
+ @smtp.should_receive(:enable_starttls)
102
+ Pony.transport_via_smtp(mock('tmail', :to => 'to', :from => 'from', :to_s => 'message'), o)
103
+ end
104
+
105
+ it "starts the job" do
106
+ @smtp.should_receive(:start)
107
+ Pony.transport_via_smtp(mock('tmail', :to => 'to', :from => 'from', :to_s => 'message'))
108
+ end
109
+
110
+ it "sends a tmail message" do
111
+ @smtp.should_receive(:send_message)
112
+ Pony.transport_via_smtp(mock('tmail', :to => 'to', :from => 'from', :to_s => 'message'))
113
+ end
114
+
115
+ it "finishes the job" do
116
+ @smtp.should_receive(:finish)
117
+ Pony.transport_via_smtp(mock('tmail', :to => 'to', :from => 'from', :to_s => 'message'))
118
+ end
119
+
120
+ end
121
+ end
122
+
123
+ describe ":via option should over-ride the default transport mechanism" do
124
+ it "should send via sendmail if :via => sendmail" do
125
+ Pony.should_receive(:transport_via_sendmail)
126
+ Pony.mail(:to => 'joe@example.com', :via => :sendmail)
127
+ end
128
+
129
+ it "should send via smtp if :via => smtp" do
130
+ Pony.should_receive(:transport_via_smtp)
131
+ Pony.mail(:to => 'joe@example.com', :via => :smtp)
132
+ end
133
+
134
+ it "should raise an error if via is neither smtp nor sendmail" do
135
+ lambda { Pony.mail(:to => 'joe@plumber.com', :via => :pigeon) }.should raise_error(ArgumentError)
136
+ end
137
+ end
138
+
139
+ end
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hiroshi-pony
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.1
5
+ platform: ruby
6
+ authors:
7
+ - Hiroshi Saito
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-07-10 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: adamwiggins/pony + file attachment (without GAE) + TLS.
17
+ email: HiroshiSaito@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - README.rdoc
26
+ - Rakefile
27
+ - lib/pony.rb
28
+ - pony.gemspec
29
+ - spec/base.rb
30
+ - spec/pony_spec.rb
31
+ has_rdoc: false
32
+ homepage: http://github.com/hiroshi/pony
33
+ post_install_message:
34
+ rdoc_options:
35
+ - --inline-source
36
+ - --charset=UTF-8
37
+ require_paths:
38
+ - lib
39
+ required_ruby_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: "0"
50
+ version:
51
+ requirements: []
52
+
53
+ rubyforge_project:
54
+ rubygems_version: 1.2.0
55
+ signing_key:
56
+ specification_version: 2
57
+ summary: adamwiggins/pony + file attachment (without GAE) + TLS.
58
+ test_files: []
59
+