vestel-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/README.rdoc ADDED
@@ -0,0 +1,68 @@
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',
8
+ :type => 'html',
9
+ :charset => 'windows-1252',
10
+ :body => 'Hello there.')
11
+
12
+ Any option key may be omitted except for :to.
13
+
14
+ Default :type is 'plain' for "text/plain", other option is 'html'
15
+ Default :charset is set to 'utf-8'
16
+
17
+ == Transport
18
+
19
+ Pony uses /usr/sbin/sendmail to send mail if it is available, otherwise it uses SMTP to localhost.
20
+
21
+ This can be over-ridden if you specify a via option
22
+
23
+ Pony.mail(:to => 'you@example.com', :via => :smtp) # sends via SMTP
24
+
25
+ Pony.mail(:to => 'you@example.com', :via => :sendmail) # sends via sendmail
26
+
27
+ You can also specify options for SMTP:
28
+
29
+ Pony.mail(:to => 'you@example.com', :via => :smtp, :smtp => {
30
+ :host => 'smtp.yourserver.com',
31
+ :port => '25',
32
+ :user => 'user',
33
+ :pass => 'pass',
34
+ :auth => :plain # :plain, :login, :cram_md5, no auth by default
35
+ :domain => "localhost.localdomain" # the HELO domain provided by the client to the server
36
+ }
37
+
38
+ == TLS/SSL
39
+
40
+ With smtp transport it also possible to use TLS/SSL:
41
+
42
+ Pony.mail(:to => 'you@example.com', :via => :smtp, :smtp => {
43
+ :host => 'smtp.gmail.com',
44
+ :port => '587',
45
+ :tls => true,
46
+ :user => 'user',
47
+ :pass => 'pass',
48
+ :auth => :plain # :plain, :login, :cram_md5, no auth by default
49
+ :domain => "localhost.localdomain" # the HELO domain provided by the client to the server
50
+ })
51
+
52
+ == Attachments
53
+
54
+ You can attach a file or two with the :attachments option:
55
+
56
+ Pony.mail(..., :attachments => {"foo.zip" => File.read("path/to/foo.zip"), "hello.txt" => "hello!"})
57
+
58
+ == Meta
59
+
60
+ Written by Adam Wiggins
61
+
62
+ Patches contributed by: Mathieu Martin, Arun Thampi, Thomas Hurst, Stephen
63
+ Celis, Othmane Benkirane, and Neil Mock
64
+
65
+ Released under the MIT License: http://www.opensource.org/licenses/mit-license.php
66
+
67
+ http://github.com/adamwiggins/pony
68
+
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,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 'text', options[:type] || 'plain', {'charset'=> options[:charset] || 'utf-8'}
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,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{vestel-pony}
5
+ s.version = "0.4.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Hiroshi Saito", "Aleksandrs 'vestel' Zdancuks"]
9
+ s.date = %q{2009-08-05}
10
+ s.description = %q{adamwiggins/pony extended with file attachment, TLS support, content type, custom charset.}
11
+ s.email = %q{vestel@blog.copperred.net}
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/vestel/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,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 "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 "type" do
48
+ Pony.build_tmail(:type => 'html').content_type.should == 'text/html'
49
+ end
50
+
51
+ it "charset" do
52
+ Pony.build_tmail(:charset => 'windows-1252').charset.should == 'windows-1252'
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,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vestel-pony
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ platform: ruby
6
+ authors:
7
+ - Hiroshi Saito
8
+ - Aleksandrs 'vestel' Zdancuks
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-08-05 00:00:00 +02:00
14
+ default_executable:
15
+ dependencies: []
16
+
17
+ description: adamwiggins/pony extended with file attachment, TLS support, content type, custom charset.
18
+ email: vestel@blog.copperred.net
19
+ executables: []
20
+
21
+ extensions: []
22
+
23
+ extra_rdoc_files: []
24
+
25
+ files:
26
+ - README.rdoc
27
+ - Rakefile
28
+ - lib/pony.rb
29
+ - pony.gemspec
30
+ - spec/base.rb
31
+ - spec/pony_spec.rb
32
+ has_rdoc: true
33
+ homepage: http://github.com/vestel/pony
34
+ licenses: []
35
+
36
+ post_install_message:
37
+ rdoc_options:
38
+ - --inline-source
39
+ - --charset=UTF-8
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ version:
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ requirements: []
55
+
56
+ rubyforge_project:
57
+ rubygems_version: 1.3.5
58
+ signing_key:
59
+ specification_version: 3
60
+ summary: adamwiggins/pony extended with file attachment, TLS support, content type, custom charset.
61
+ test_files: []
62
+