ddollar-pony 0.4.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.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
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,45 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "pony"
8
+ gem.summary = %Q{Send email in one command: Pony.mail(:to => 'someone@example.com', :body => 'hello')}
9
+ gem.description = %Q{Send email in one command: Pony.mail(:to => 'someone@example.com', :body => 'hello')}
10
+ gem.email = "<ddollar@gmail.com>"
11
+ gem.homepage = "http://github.com/ddollar/pony"
12
+ gem.authors = ["Adam Wiggins", "David Dollar"]
13
+ gem.add_development_dependency "rspec"
14
+ gem.add_development_dependency "yard"
15
+ gem.add_dependency "tmail", "~> 1.0"
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
20
+ end
21
+
22
+ require 'spec/rake/spectask'
23
+ Spec::Rake::SpecTask.new(:spec) do |spec|
24
+ spec.libs << 'lib' << 'spec'
25
+ spec.spec_files = FileList['spec/**/*_spec.rb']
26
+ end
27
+
28
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
29
+ spec.libs << 'lib' << 'spec'
30
+ spec.pattern = 'spec/**/*_spec.rb'
31
+ spec.rcov = true
32
+ end
33
+
34
+ task :spec => :check_dependencies
35
+
36
+ task :default => :spec
37
+
38
+ begin
39
+ require 'yard'
40
+ YARD::Rake::YardocTask.new
41
+ rescue LoadError
42
+ task :yardoc do
43
+ abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
44
+ end
45
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.4.0
data/lib/pony.rb ADDED
@@ -0,0 +1,90 @@
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
+ mail.set_content_type(options[:content_type] || 'text/plain')
37
+ (options[:attachments] || []).each do |name, body|
38
+ attachment = TMail::Mail.new
39
+ attachment.transfer_encoding = "base64"
40
+ attachment.body = Base64.encode64(body)
41
+ # attachment.set_content_type # TODO: if necessary
42
+ attachment.set_content_disposition "attachment", "filename" => name
43
+ mail.parts.push attachment
44
+ end
45
+ mail
46
+ end
47
+
48
+ def self.sendmail_binary
49
+ @sendmail_binary ||= `which sendmail`.chomp
50
+ end
51
+
52
+ def self.transport(tmail)
53
+ if File.executable? sendmail_binary
54
+ transport_via_sendmail(tmail)
55
+ else
56
+ transport_via_smtp(tmail)
57
+ end
58
+ end
59
+
60
+ def self.via_options
61
+ %w(sendmail smtp)
62
+ end
63
+
64
+ def self.transport_via_sendmail(tmail, options={})
65
+ IO.popen('-', 'w+') do |pipe|
66
+ if pipe
67
+ pipe.write(tmail.to_s)
68
+ else
69
+ exec(sendmail_binary, *tmail.to)
70
+ end
71
+ end
72
+ end
73
+
74
+ def self.transport_via_smtp(tmail, options={:smtp => {}})
75
+ default_options = {:smtp => { :host => 'localhost', :port => '25', :domain => 'localhost.localdomain' }}
76
+ o = default_options[:smtp].merge(options[:smtp])
77
+ smtp = Net::SMTP.new(o[:host], o[:port])
78
+ if o[:tls]
79
+ raise "You may need: gem install smtp_tls" unless smtp.respond_to?(:enable_starttls)
80
+ smtp.enable_starttls
81
+ end
82
+ if o.include?(:auth)
83
+ smtp.start(o[:domain], o[:user], o[:password], o[:auth])
84
+ else
85
+ smtp.start(o[:domain])
86
+ end
87
+ smtp.send_message tmail.to_s, tmail.from, tmail.to
88
+ smtp.finish
89
+ end
90
+ end
data/pony.gemspec ADDED
@@ -0,0 +1,57 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{pony}
8
+ s.version = "0.4.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Adam Wiggins", "David Dollar"]
12
+ s.date = %q{2009-09-09}
13
+ s.description = %q{Send email in one command: Pony.mail(:to => 'someone@example.com', :body => 'hello')}
14
+ s.email = %q{<ddollar@gmail.com>}
15
+ s.extra_rdoc_files = [
16
+ "README.rdoc"
17
+ ]
18
+ s.files = [
19
+ ".document",
20
+ ".gitignore",
21
+ "README.rdoc",
22
+ "Rakefile",
23
+ "VERSION",
24
+ "lib/pony.rb",
25
+ "pony.gemspec",
26
+ "spec/base.rb",
27
+ "spec/pony_spec.rb"
28
+ ]
29
+ s.homepage = %q{http://github.com/ddollar/pony}
30
+ s.rdoc_options = ["--charset=UTF-8"]
31
+ s.require_paths = ["lib"]
32
+ s.rubygems_version = %q{1.3.5}
33
+ s.summary = %q{Send email in one command: Pony.mail(:to => 'someone@example.com', :body => 'hello')}
34
+ s.test_files = [
35
+ "spec/base.rb",
36
+ "spec/pony_spec.rb"
37
+ ]
38
+
39
+ if s.respond_to? :specification_version then
40
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
41
+ s.specification_version = 3
42
+
43
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
44
+ s.add_development_dependency(%q<rspec>, [">= 0"])
45
+ s.add_development_dependency(%q<yard>, [">= 0"])
46
+ s.add_runtime_dependency(%q<tmail>, ["~> 1.0"])
47
+ else
48
+ s.add_dependency(%q<rspec>, [">= 0"])
49
+ s.add_dependency(%q<yard>, [">= 0"])
50
+ s.add_dependency(%q<tmail>, ["~> 1.0"])
51
+ end
52
+ else
53
+ s.add_dependency(%q<rspec>, [">= 0"])
54
+ s.add_dependency(%q<yard>, [">= 0"])
55
+ s.add_dependency(%q<tmail>, ["~> 1.0"])
56
+ end
57
+ 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,147 @@
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 "content_type" do
40
+ Pony.build_tmail(:content_type => 'text/html').content_type.should == 'text/html'
41
+ end
42
+
43
+ it "content_type (default)" do
44
+ Pony.build_tmail({}).content_type.should == 'text/plain'
45
+ end
46
+
47
+ it "subject" do
48
+ Pony.build_tmail(:subject => 'hello').subject.should == 'hello'
49
+ end
50
+
51
+ it "body" do
52
+ Pony.build_tmail(:body => 'What do you know, Joe?').body.should == 'What do you know, Joe?'
53
+ end
54
+
55
+ it "attachments" do
56
+ tmail = Pony.build_tmail(:attachments => {"foo.txt" => "content of foo.txt"})
57
+ tmail.should have(1).parts
58
+ tmail.parts.first.to_s.should == <<-PART
59
+ Content-Transfer-Encoding: Base64
60
+ Content-Disposition: attachment; filename=foo.txt
61
+
62
+ Y29udGVudCBvZiBmb28udHh0
63
+ PART
64
+ end
65
+ end
66
+
67
+ describe "transport" do
68
+ it "transports via the sendmail binary if it exists" do
69
+ File.stub!(:executable?).and_return(true)
70
+ Pony.should_receive(:transport_via_sendmail).with(:tmail)
71
+ Pony.transport(:tmail)
72
+ end
73
+
74
+ it "transports via smtp if no sendmail binary" do
75
+ Pony.stub!(:sendmail_binary).and_return('/does/not/exist')
76
+ Pony.should_receive(:transport_via_smtp).with(:tmail)
77
+ Pony.transport(:tmail)
78
+ end
79
+
80
+ it "transports mail via /usr/sbin/sendmail binary" do
81
+ pipe = mock('sendmail pipe')
82
+ IO.should_receive(:popen).with('-',"w+").and_yield(pipe)
83
+ pipe.should_receive(:write).with('message')
84
+ Pony.transport_via_sendmail(mock('tmail', :to => 'to', :from => 'from', :to_s => 'message'))
85
+ end
86
+
87
+ describe "SMTP transport" do
88
+ before do
89
+ @smtp = mock('net::smtp object')
90
+ @smtp.stub!(:start)
91
+ @smtp.stub!(:send_message)
92
+ @smtp.stub!(:finish)
93
+ Net::SMTP.stub!(:new).and_return(@smtp)
94
+ end
95
+
96
+ it "defaults to localhost as the SMTP server" do
97
+ Net::SMTP.should_receive(:new).with('localhost', '25').and_return(@smtp)
98
+ Pony.transport_via_smtp(mock('tmail', :to => 'to', :from => 'from', :to_s => 'message'))
99
+ end
100
+
101
+ it "uses SMTP authorization when auth key is provided" do
102
+ o = { :smtp => { :user => 'user', :password => 'password', :auth => 'plain'}}
103
+ @smtp.should_receive(:start).with('localhost.localdomain', 'user', 'password', 'plain')
104
+ Pony.transport_via_smtp(mock('tmail', :to => 'to', :from => 'from', :to_s => 'message'), o)
105
+ end
106
+
107
+ it "enable starttls when tls option is true" do
108
+ o = { :smtp => { :user => 'user', :password => 'password', :auth => 'plain', :tls => true}}
109
+ @smtp.should_receive(:enable_starttls)
110
+ Pony.transport_via_smtp(mock('tmail', :to => 'to', :from => 'from', :to_s => 'message'), o)
111
+ end
112
+
113
+ it "starts the job" do
114
+ @smtp.should_receive(:start)
115
+ Pony.transport_via_smtp(mock('tmail', :to => 'to', :from => 'from', :to_s => 'message'))
116
+ end
117
+
118
+ it "sends a tmail message" do
119
+ @smtp.should_receive(:send_message)
120
+ Pony.transport_via_smtp(mock('tmail', :to => 'to', :from => 'from', :to_s => 'message'))
121
+ end
122
+
123
+ it "finishes the job" do
124
+ @smtp.should_receive(:finish)
125
+ Pony.transport_via_smtp(mock('tmail', :to => 'to', :from => 'from', :to_s => 'message'))
126
+ end
127
+
128
+ end
129
+ end
130
+
131
+ describe ":via option should over-ride the default transport mechanism" do
132
+ it "should send via sendmail if :via => sendmail" do
133
+ Pony.should_receive(:transport_via_sendmail)
134
+ Pony.mail(:to => 'joe@example.com', :via => :sendmail)
135
+ end
136
+
137
+ it "should send via smtp if :via => smtp" do
138
+ Pony.should_receive(:transport_via_smtp)
139
+ Pony.mail(:to => 'joe@example.com', :via => :smtp)
140
+ end
141
+
142
+ it "should raise an error if via is neither smtp nor sendmail" do
143
+ lambda { Pony.mail(:to => 'joe@plumber.com', :via => :pigeon) }.should raise_error(ArgumentError)
144
+ end
145
+ end
146
+
147
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ddollar-pony
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ platform: ruby
6
+ authors:
7
+ - Adam Wiggins
8
+ - David Dollar
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-09-09 00:00:00 -07:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rspec
18
+ type: :development
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ version:
26
+ - !ruby/object:Gem::Dependency
27
+ name: yard
28
+ type: :development
29
+ version_requirement:
30
+ version_requirements: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "0"
35
+ version:
36
+ - !ruby/object:Gem::Dependency
37
+ name: tmail
38
+ type: :runtime
39
+ version_requirement:
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ version: "1.0"
45
+ version:
46
+ description: "Send email in one command: Pony.mail(:to => 'someone@example.com', :body => 'hello')"
47
+ email: <ddollar@gmail.com>
48
+ executables: []
49
+
50
+ extensions: []
51
+
52
+ extra_rdoc_files:
53
+ - README.rdoc
54
+ files:
55
+ - .document
56
+ - .gitignore
57
+ - README.rdoc
58
+ - Rakefile
59
+ - VERSION
60
+ - lib/pony.rb
61
+ - pony.gemspec
62
+ - spec/base.rb
63
+ - spec/pony_spec.rb
64
+ has_rdoc: false
65
+ homepage: http://github.com/ddollar/pony
66
+ post_install_message:
67
+ rdoc_options:
68
+ - --charset=UTF-8
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: "0"
76
+ version:
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: "0"
82
+ version:
83
+ requirements: []
84
+
85
+ rubyforge_project:
86
+ rubygems_version: 1.2.0
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: "Send email in one command: Pony.mail(:to => 'someone@example.com', :body => 'hello')"
90
+ test_files:
91
+ - spec/base.rb
92
+ - spec/pony_spec.rb