mmmail 1.0.0

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