mmmail 1.0.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.
Files changed (6) hide show
  1. data/LICENSE +22 -0
  2. data/README.markdown +81 -0
  3. data/Rakefile +42 -0
  4. data/lib/mmmail.rb +283 -0
  5. data/spec/basic_spec.rb +193 -0
  6. metadata +59 -0
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2009 Loren Segal
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,81 @@
1
+ MmMail
2
+ ======
3
+
4
+ Mmmm, a Minimalist mail library for Ruby. Works with SMTP or sendmail.
5
+ One method call to send out emails. You're done. Easy tastes good. Oh,
6
+ and it works with Ruby 1.9.
7
+
8
+ Join the discussion: #mmmail on freenode
9
+
10
+ Install
11
+ -------
12
+
13
+ $ git clone git://github.com/lsegal/mmmail
14
+ $ cd mmmail
15
+ $ rake install
16
+
17
+ or use GitHub gems:
18
+
19
+ $ sudo gem install lsegal-mmmail --source http://gems.github.com
20
+
21
+ Use
22
+ ---
23
+
24
+ **An easy example**:
25
+
26
+ require 'mmmail'
27
+ MmMail.send(to: 'me@gmail.com', from: 'me@yahoo.com',
28
+ subject: 'hello joe', body: <<-eof)
29
+ Hey Joe,
30
+
31
+ You left the kitchen light on.
32
+ It started a fire and burned down your house.
33
+ Have fun in Hawaii.
34
+
35
+ Jake.
36
+ eof
37
+
38
+ Yes, that's Ruby 1.9 syntax, get used to it. It should work out
39
+ with the inferior 1.8 hash syntax too.
40
+
41
+ **More complex stuff, like using sendmail instead of Net::SMTP:**
42
+
43
+ require 'mmmail'
44
+ MmMail::Transport::DefaultConfig.method = :sendmail
45
+ MmMail.send(...)
46
+
47
+ Okay it wasn't that hard. You can also specify the path to sendmail with
48
+
49
+ MmMail::Transport::DefaultConfig.sendmail_binary = '/bin/sendmail'
50
+
51
+ **Dealing with SMTP auth and separate hosts:**
52
+
53
+ My ISP makes me do this:
54
+
55
+ require 'mmmail'
56
+ config = MmMail::Transport::DefaultConfig
57
+ config.host = 'smtp.myisp.com'
58
+ config.port = 587
59
+ config.auth_type = :plain # or :md5cram or :login
60
+ config.auth_user = 'myuser'
61
+ config.auth_pass = 'mypass'
62
+
63
+ Yours might too. Okay, it doesn't make me do *all* of that, but these are
64
+ just examples, right?
65
+
66
+ You can also create a `MmMail::Transport::Config` object to pass to `#mail`
67
+ if you need multiple configurations:
68
+
69
+ config = MmMail::Transport::Config.new
70
+ config.host = 'mail.someOtherIspHost.com'
71
+
72
+ MmMail.send({options: here}, config)
73
+ # or
74
+ msg = MmMail::Message.new(to: '...', from: '...', subject: '...', body: '...')
75
+ transport = MmMail::Transport.new(config)
76
+ transport.send(msg, config)
77
+
78
+ Documentation
79
+ -------------
80
+
81
+ [http://lsegal.github.com/mmmail/doc](http://lsegal.github.com/mmmail/doc)
@@ -0,0 +1,42 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+
4
+ begin
5
+ require 'spec'
6
+ require 'spec/rake/spectask'
7
+ rescue LoadError; end
8
+
9
+ begin
10
+ require 'yard'
11
+ rescue LoadError; end
12
+
13
+ WINDOWS = (PLATFORM =~ /win32|cygwin/ ? true : false) rescue false
14
+ SUDO = WINDOWS ? '' : 'sudo'
15
+
16
+ task :default => :specs
17
+
18
+ load 'mmmail.gemspec'
19
+ Rake::GemPackageTask.new(SPEC) do |pkg|
20
+ pkg.gem_spec = SPEC
21
+ pkg.need_zip = true
22
+ pkg.need_tar = true
23
+ end
24
+
25
+ desc "Install the gem locally"
26
+ task :install => :package do
27
+ sh "#{SUDO} gem install pkg/#{SPEC.name}-#{SPEC.version}.gem --local"
28
+ sh "#{SUDO} rm -rf pkg/#{SPEC.name}-#{SPEC.version}" unless ENV['KEEP_FILES']
29
+ end
30
+
31
+ begin
32
+ desc "Run all specs"
33
+ Spec::Rake::SpecTask.new("specs") do |t|
34
+ $DEBUG = true if ENV['DEBUG']
35
+ t.spec_opts = ["--format", "specdoc", "--colour"]
36
+ t.spec_files = Dir["spec/**/*_spec.rb"].sort
37
+ end
38
+ rescue LoadError; end
39
+
40
+ begin
41
+ YARD::Rake::YardocTask.new
42
+ rescue LoadError; end
@@ -0,0 +1,283 @@
1
+ require 'net/smtp'
2
+
3
+ module MmMail
4
+ # General exception class when something goes wrong in MmMail
5
+ class TransportError < Exception; end
6
+
7
+ # Handles the transportation of a {Message} to its destination.
8
+ # Basic support for SMTP (through +Net::SMTP+) or +sendmail+.
9
+ #
10
+ # You can either pass a new {Transport::Config} object during transport or use
11
+ # the system wide {Transport::DefaultConfig} object.
12
+ #
13
+ # @example [To set transport to use sendmail]
14
+ # MmMail::Transport::DefaultConfig.method = :sendmail
15
+ # # Note you might need to point to sendmail if it's not in your PATH:
16
+ # MmMail::Transport::DefaultConfig.sendmail_binary = '/path/to/sendmail'
17
+ #
18
+ # @example [To connect to your ISP SMTP server on 587]
19
+ # MmMail::Transport::DefaultConfig.host = 'smtp.myisp.com'
20
+ # MmMail::Transport::DefaultConfig.port = 587
21
+ #
22
+ # @see Transport::Config
23
+ # @see Transport::mail
24
+ class Transport
25
+ # Configuration class for a {Transport}
26
+ class Config
27
+ # Set/get the SMTP host/port information
28
+ attr_accessor :host, :port
29
+
30
+ # Set/get the authentication type (nil for none, :plain, :login or :cram_md5)
31
+ attr_accessor :auth_type
32
+
33
+ # Set/get the AUTH user/password when using SMTP transport.
34
+ attr_accessor :auth_user, :auth_pass
35
+
36
+ # Set/get the email method. Allowed values are +:smtp+ or +:sendmail+.
37
+ attr_accessor :method
38
+
39
+ # Set/get the location of the sendmail binary on the system
40
+ attr_accessor :sendmail_binary
41
+
42
+ # Creates a new Config object set to send via SMTP on
43
+ # localhost:25 with no authentication.
44
+ def initialize
45
+ @method = :smtp # :sendmail
46
+ @host = 'localhost'
47
+ @port = 25
48
+ @auth_type = nil # :plain, :login, :cram_md5
49
+ @auth_user = nil
50
+ @auth_pass = nil
51
+ @sendmail_binary = 'sendmail'
52
+ end
53
+ end
54
+
55
+ # The default system wide configuration used when no custom config
56
+ # object is provided to a Transport object. If you want to make global
57
+ # configuration changes, change the settings here.
58
+ DefaultConfig = Config.new
59
+
60
+ # Creates a new {Transport} object and sends an email.
61
+ #
62
+ # @see #mail
63
+ def self.mail(message, config = nil)
64
+ new(config).mail(message)
65
+ end
66
+
67
+ # Sets a {Config} object to use when sending mail
68
+ attr_accessor :config
69
+
70
+ # Creates a new Transport object to send emails with. To change
71
+ # settings to sendmail or use SMTP auth, set these in the {Config}
72
+ # object.
73
+ #
74
+ # @param [Config] a configuration to use
75
+ # @raise [ArgumentError] if config is not a {Config} object.
76
+ def initialize(config = nil)
77
+ if config && !config.is_a?(Config)
78
+ raise ArgumentError, "expected #{self.class}::Config"
79
+ end
80
+
81
+ @config = config || DefaultConfig
82
+ end
83
+
84
+ # Sends a {Message} object out as an email using the configuration
85
+ # set during initialization.
86
+ #
87
+ # @param [Message] an email to send
88
+ # @raise [ArgumentError] if message is not a {Message} object
89
+ # @raise [TransportError] if message is not {Message#valid? valid}.
90
+ def mail(message)
91
+ unless Message === message
92
+ raise ArgumentError, "expected MmMail::Message, got #{message.class}"
93
+ end
94
+
95
+ raise TransportError, "invalid message" unless message.valid?
96
+
97
+ send("mail_#{config.method}", message)
98
+ end
99
+
100
+ # Sends a mail through Net::SMTP using the {#config} if
101
+ # any SMTP or hostname information is set.
102
+ #
103
+ # @param [#to_s] message the message to send
104
+ def mail_smtp(message)
105
+ Net::SMTP.start(config.host, config.port, 'localhost.localdomain',
106
+ config.auth_user, config.auth_pass, config.auth_type) do |smtp|
107
+ smtp.send_message(message.to_s, message.from, message.recipients_list)
108
+ end
109
+ end
110
+
111
+ # Sends a mail through sendmail using the {Config#sendmail_binary} as the
112
+ # location of the file.
113
+ #
114
+ # @param [#to_s] message the message to send
115
+ # @raise [TransportError] if a problem during execution occured
116
+ def mail_sendmail(message)
117
+ bin, err = config.sendmail_binary, ''
118
+ result = IO.popen("#{bin} -t 2>&1", "w+") do |io|
119
+ io.write(message.to_s)
120
+ io.close_write
121
+ err = io.read.chomp
122
+ end
123
+
124
+ raise TransportError, err if $? != 0
125
+ end
126
+ end
127
+
128
+ # A Message object representing an Email to be passed to a {Transport}.
129
+ class Message
130
+ # Creates a new message with associated fields.
131
+ #
132
+ # @example
133
+ # MmMail::Message.new(:to => 'test@example.com', :body => 'hi')
134
+ #
135
+ # @param [Hash] opts the options to create a message with.
136
+ # @option opts [String] :from ('nobody@localhost') The email's From field
137
+ # @option opts [String] :subject ('') The email's Subject field
138
+ # @option opts [String] :body ('') The email's body (not a header)
139
+ # @option opts [String] :to (nil) The email's To field. List multiple recipients as
140
+ # 'a@b.c, b@c.d', not an array.
141
+ def initialize(opts = {})
142
+ defaults = {
143
+ :from => 'nobody@localhost',
144
+ :subject => '',
145
+ :body => ''
146
+ }
147
+ @headers = defaults.merge(opts)
148
+ end
149
+
150
+ # Allow access of fields by header name or symbolic representation
151
+ #
152
+ # @example
153
+ # m[:x_message_id] = '1234'
154
+ # m['X-Message-Id'] == '1234' # => true
155
+ #
156
+ # @param [String, Symbol] k the header or symbolic header value to lookup.
157
+ # @return [String] the value associated with the field
158
+ def [](k) @headers[translate_header_to_sym(k)] end
159
+
160
+ # Allow access of fields by header name or symbolic representation
161
+ #
162
+ # @example
163
+ # m[:x_message_id] = '1234'
164
+ # m['X-Message-Id'] == '1234' # => true
165
+ #
166
+ def []=(k, v) @headers[translate_header_to_sym(k)] = v end
167
+
168
+ # Override this method to allow any call to obj.meth or obj.meth= to
169
+ # set a header field on this object.
170
+ #
171
+ # @example [To set the field 'X-Message-Id']
172
+ # m.x_message_id = '1234'
173
+ # m.x_message_id == '1234' # => true
174
+ #
175
+ def method_missing(sym, *args)
176
+ if sym.to_s =~ /=$/
177
+ self[sym.to_s[0..-2].to_sym] = args.first
178
+ elsif @headers.has_key?(sym)
179
+ self[sym]
180
+ else
181
+ super
182
+ end
183
+ end
184
+
185
+ # Override this method to verify if a field has been set.
186
+ #
187
+ # @return [Boolean] whether the field was set (or if a regular method
188
+ # is callable.)
189
+ def respond_to?(sym)
190
+ return true if super
191
+ @headers.has_key?(sym)
192
+ end
193
+
194
+ # Returns the message in its full form as expected by an SMTP server.
195
+ #
196
+ # @return [String] the email with headers followed by a body
197
+ def to_s
198
+ [headers, body].join("\n")
199
+ end
200
+
201
+ # Returns all the recipients in the To field.
202
+ #
203
+ # @example
204
+ # m.to = 'a@b.c, b@c.d'
205
+ # m.recipients_list # => ['a@b.c', 'b@c.d']
206
+ #
207
+ # @return [Array<String>] the emails in the To field of the message.
208
+ def recipients_list
209
+ to.split(/\s*,\s*/)
210
+ end
211
+
212
+ # Checks if the message is valid. Validity is based on
213
+ # having the From, To and Subject fields set. From and To
214
+ # must not be empty.
215
+ #
216
+ # @return [Boolean] whether or not the message is a valid e-mail
217
+ def valid?
218
+ [:from, :to].each do |field|
219
+ return false if !self[field] || self[field].empty?
220
+ end
221
+
222
+ self[:subject] ? true : false
223
+ end
224
+
225
+ private
226
+
227
+ # Returns the headers as the RFC822 string.
228
+ #
229
+ # @return [String] the headers in RFC822 format
230
+ def headers
231
+ @headers.reject {|k, v| k == :body }.map do |k, v|
232
+ translate_header_name(k) + ': ' + v + "\n"
233
+ end.join
234
+ end
235
+
236
+ # Translates a header from its symbolic representation to its
237
+ # RFC822 header name or the other way around. If you give in
238
+ # a header name (String) you will get a Symbol, and a Symbol
239
+ # if you give a String.
240
+ #
241
+ # @example
242
+ # msg.translate_header_name(:x_message_id) # => 'X-Message-Id'
243
+ # msg.translate_header_name('Content-Type') # => :content_type
244
+ #
245
+ # @param [String,Symbol] key the header name to translate
246
+ # @return [Symbol,String] the symbolic or header representation of
247
+ # the symbol or header name.
248
+ # @raise [ArgumentError] if key is neither a String or Symbol
249
+ def translate_header_name(key)
250
+ case key
251
+ when String
252
+ key.downcase.tr('-', '_').to_sym
253
+ when Symbol
254
+ key.to_s.capitalize.gsub(/_(.)/) {|m| '-' + m[1].upcase }
255
+ else
256
+ raise ArgumentError, "invalid key type #{key.class}"
257
+ end
258
+ end
259
+
260
+ # Translates a header one-way to the symbolic representation.
261
+ #
262
+ # @param [String, Symbol] key any header or symbolic key
263
+ # @return [Symbol] the symbolic representation of the header name
264
+ # @see #translate_header_name
265
+ def translate_header_to_sym(key)
266
+ return key if Symbol === key
267
+ translate_header_name(key)
268
+ end
269
+ end
270
+
271
+ # Quickly send out an email.
272
+ #
273
+ # @example
274
+ # MmMail.mail(:to => 'me@gmail.com', :body => 'hi!')
275
+ #
276
+ # @param [Hash] opts the hash used to construct the message
277
+ # @param [Transport::Config, nil] config the configuration object to use
278
+ # during transport
279
+ # @see Transport#mail
280
+ def self.mail(opts = {}, config = nil)
281
+ Transport.mail(Message.new(opts), config)
282
+ end
283
+ end
@@ -0,0 +1,193 @@
1
+ require File.dirname(__FILE__) + '/../lib/mmmail.rb'
2
+ require 'net/smtp'
3
+
4
+ describe MmMail::Message, '#initialize' do
5
+ it "should always have from, subject and body" do
6
+ m = MmMail::Message.new
7
+ m.from.should == 'nobody@localhost'
8
+ m.body.should == ''
9
+ m.subject.should == ''
10
+ end
11
+ end
12
+
13
+ describe MmMail::Message, "accessor methods" do
14
+ it "should allow access from m.value/m.value=" do
15
+ m = MmMail::Message.new
16
+ m.some_field = 'hello'
17
+ m.some_field.should == 'hello'
18
+ end
19
+
20
+ it "should allow access from m[:value]" do
21
+ m = MmMail::Message.new
22
+ m[:some_field] = 'hello'
23
+ m[:some_field].should == 'hello'
24
+ end
25
+
26
+ it "should allow access from m['Value']" do
27
+ m = MmMail::Message.new
28
+ m['Some-Field'] = 'hello'
29
+ m['Some-Field'].should == 'hello'
30
+ end
31
+
32
+ it "should allow mixing of any form of access" do
33
+ check = lambda do |m|
34
+ m.some_field.should == 'hello'
35
+ m[:some_field].should == 'hello'
36
+ m['Some-Field'].should == 'hello'
37
+ end
38
+
39
+ m = MmMail::Message.new
40
+ m.some_field = 'hello'
41
+ check.call(m)
42
+ m[:some_field] = 'hello'
43
+ check.call(m)
44
+ m['Some-Field'] = 'hello'
45
+ check.call(m)
46
+ end
47
+
48
+ it "should advertise that it responds to set fields (respond_to?)" do
49
+ m = MmMail::Message.new
50
+ m.some_field = 'hello'
51
+ m.respond_to?(:to_s).should == true # sanity check
52
+ m.respond_to?(:some_field).should == true
53
+ m.respond_to?(:FAIL).should == false
54
+ end
55
+ end
56
+
57
+ describe MmMail::Message, '#translate_header_name' do
58
+ def translate(val) MmMail::Message.new.send(:translate_header_name, val) end
59
+
60
+ it "should translate header 'Some-Field' attribute name to :some_field" do
61
+ translate('Some-Field').should == :some_field
62
+ translate('Some-field').should == :some_field
63
+ translate('To').should == :to
64
+ translate('X-Message-Id').should == :x_message_id
65
+ end
66
+
67
+ it "should translate header :some_field to 'Some-Field'" do
68
+ translate(:some_field).should == 'Some-Field'
69
+ end
70
+
71
+ it "should raise ArgumentError if arg is not Symbol or String" do
72
+ lambda { translate({}) }.should raise_error(ArgumentError)
73
+ end
74
+ end
75
+
76
+ describe MmMail::Message, "#to_s" do
77
+ it "should show all headers before special value body" do
78
+ m = MmMail::Message.new
79
+ m.to = 'hello@email.com'
80
+ m.from = 'me@email.com'
81
+ m.x_message_id = '12345'
82
+ m.body = "Hello World"
83
+ m.subject = 'Subject Here'
84
+
85
+ # Might not work in Ruby 1.8 (hashes are unordered)
86
+ m.to_s.should ==
87
+ "From: me@email.com\nSubject: Subject Here\nTo: hello@email.com\n" +
88
+ "X-Message-Id: 12345\n\nHello World"
89
+ end
90
+ end
91
+
92
+ describe MmMail::Message, '#valid?' do
93
+ it "should be valid only if message has from, to and subject" do
94
+ m = MmMail::Message.new
95
+ m.valid?.should == false # no to or subject
96
+ m.to = ''
97
+ m.valid?.should == false # to is empty, not good enough
98
+ m.to = 'hello@test.com'
99
+ m.subject = ''
100
+ m.valid?.should == true # empty subject is legal
101
+ m.subject = nil
102
+ m.valid?.should == false
103
+ end
104
+ end
105
+
106
+ describe MmMail::Message, '#recipient_list' do
107
+ it "should list all emails in the To header" do
108
+ m = MmMail::Message.new
109
+ m.to = 'a@b.c , b@c.d'
110
+ m.recipients_list.should == ['a@b.c', 'b@c.d']
111
+ end
112
+ end
113
+
114
+ describe MmMail::Transport::Config, '#initialize' do
115
+ it "should initialize with sane defaults" do
116
+ config = MmMail::Transport::Config.new
117
+ config.host.should == 'localhost'
118
+ config.port.should == 25
119
+ config.auth_type.should be_nil
120
+ config.auth_user.should be_nil
121
+ config.auth_pass.should be_nil
122
+ config.method.should == :smtp
123
+ config.sendmail_binary.should == 'sendmail'
124
+ end
125
+ end
126
+
127
+ describe MmMail::Transport, '.mail' do
128
+ it "should create a Transport object and call #mail" do
129
+ Net::SMTP.should_receive(:start)
130
+ m = MmMail::Message.new(:to => 'test@test.com', :subject => 'hi')
131
+ MmMail::Transport.mail(m)
132
+ end
133
+ end
134
+
135
+ describe MmMail::Transport, '#initialize' do
136
+ it "should allow config object to be passed" do
137
+ lambda { MmMail::Transport.new(:symbol) }.should raise_error(ArgumentError)
138
+ end
139
+
140
+ it "should allow valid config" do
141
+ conf = MmMail::Transport::Config.new
142
+ transport = MmMail::Transport.new(conf)
143
+ transport.config.should == conf
144
+ end
145
+ end
146
+
147
+ describe MmMail::Transport, '#mail' do
148
+ it "should raise ArgumentError if argument is not a message" do
149
+ lambda { MmMail::Transport.new.mail(:sym) }.should raise_error(ArgumentError)
150
+ end
151
+
152
+ it "should raise TransportError if message is invalid" do
153
+ invalid_m = MmMail::Message.new
154
+ lambda { MmMail::Transport.new.mail(invalid_m) }.should raise_error(MmMail::TransportError)
155
+ end
156
+
157
+ it "should pass to Net::SMTP if method is set to :smtp" do
158
+ Net::SMTP.should_receive(:start).with('localhost', 25, 'localhost.localdomain', nil, nil, nil)
159
+ m = MmMail::Message.new(:to => 'test@test.com', :subject => 'hi')
160
+ MmMail::Transport.new.mail(m)
161
+ end
162
+
163
+ it "should pass changed config values to Net::SMTP" do
164
+ conf = MmMail::Transport::Config.new
165
+ conf.auth_type = :plain
166
+ conf.auth_user = 'foo'
167
+ conf.auth_pass = 'bar'
168
+ conf.host = 'foo.bar'
169
+ conf.port = 587
170
+ Net::SMTP.should_receive(:start).with(conf.host, conf.port,
171
+ 'localhost.localdomain', conf.auth_user, conf.auth_pass, conf.auth_type)
172
+ m = MmMail::Message.new(:to => 'test@test.com', :subject => 'hi')
173
+ MmMail::Transport.new(conf).mail(m)
174
+ end
175
+
176
+ it "should pass to sendmail if method is set to :sendmail" do
177
+ conf = MmMail::Transport::Config.new
178
+ conf.method = :sendmail
179
+ conf.sendmail_binary = '/path/to/sendmail'
180
+ IO.should_receive(:popen).with('/path/to/sendmail -t 2>&1', 'w+')
181
+ m = MmMail::Message.new(:to => 'test@test.com', :subject => 'hi')
182
+ lambda { MmMail::Transport.new(conf).mail(m) }.should raise_error
183
+ end
184
+
185
+ # Fails in rake specs? works from TextMate
186
+ it "should fail if the sendmail binary is invalid" do
187
+ conf = MmMail::Transport::Config.new
188
+ conf.method = :sendmail
189
+ conf.sendmail_binary = '/FAIL'
190
+ m = MmMail::Message.new(:to => 'test@test.com', :subject => 'hi')
191
+ lambda { MmMail::Transport.new(conf).mail(m) }.should raise_error(MmMail::TransportError)
192
+ end
193
+ end
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mmmail
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Loren Segal
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-02-22 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: lsegal@soen.ca
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - lib/mmmail.rb
26
+ - spec/basic_spec.rb
27
+ - LICENSE
28
+ - README.markdown
29
+ - Rakefile
30
+ has_rdoc: yard
31
+ homepage: http://github.com/lsegal/mmmail
32
+ licenses: []
33
+
34
+ post_install_message:
35
+ rdoc_options: []
36
+
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: mmmail
54
+ rubygems_version: 1.3.4
55
+ signing_key:
56
+ specification_version: 3
57
+ summary: Mmmm, a Minimalist mail library for Ruby. Works with SMTP or sendmail.
58
+ test_files: []
59
+