anthonygarcia-mailfactory 1.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2 @@
1
+ mailfactory.gemspec
2
+ pkg
@@ -0,0 +1,3 @@
1
+ (^|/)\_darcs($|/)
2
+ (^|/)\.hg($|/)
3
+ (^|/)\.hgtags($|/)
@@ -0,0 +1,14 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gemspec|
4
+ gemspec.name = 'anthonygarcia-mailfactory'
5
+ gemspec.summary = "Fork of tmm1/mailfactory to fix BlackBerry issuse"
6
+ gemspec.description = 'Create MIME email messages with multiple body parts and attachments in Ruby'
7
+ gemspec.email = 'frobotnet@gmail.com'
8
+ gemspec.homepage = 'http://github.com/anthonygarcia/mailfactory'
9
+ gemspec.authors = ['David Powers', 'Anthony Garcia']
10
+ end
11
+ Jeweler::GemcutterTasks.new
12
+ rescue LoadError
13
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
14
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.4.2
@@ -0,0 +1,45 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{anthonygarcia-mailfactory}
8
+ s.version = "1.4.2"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["David Powers", "Anthony Garcia"]
12
+ s.date = %q{2010-03-11}
13
+ s.description = %q{Create MIME email messages with multiple body parts and attachments in Ruby}
14
+ s.email = %q{frobotnet@gmail.com}
15
+ s.files = [
16
+ ".gitignore",
17
+ ".hgignore",
18
+ "Rakefile",
19
+ "VERSION",
20
+ "anthonygarcia-mailfactory.gemspec",
21
+ "lib/mailfactory.rb",
22
+ "mailfactory.gemspec",
23
+ "scripts/release.sh",
24
+ "tests/test_mailfactory.rb",
25
+ "tests/testfile.txt",
26
+ "tests/testsheet.xls",
27
+ "vendor/bundled_gems/bin/rake"
28
+ ]
29
+ s.homepage = %q{http://github.com/anthonygarcia/mailfactory}
30
+ s.rdoc_options = ["--charset=UTF-8"]
31
+ s.require_paths = ["lib"]
32
+ s.rubygems_version = %q{1.3.6}
33
+ s.summary = %q{Fork of tmm1/mailfactory to fix BlackBerry issuse}
34
+
35
+ if s.respond_to? :specification_version then
36
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
37
+ s.specification_version = 3
38
+
39
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
40
+ else
41
+ end
42
+ else
43
+ end
44
+ end
45
+
@@ -0,0 +1,464 @@
1
+ # = Overview:
2
+ # A simple to use module for generating RFC compliant MIME mail
3
+ # ---
4
+ # = License:
5
+ # Author:: David Powers
6
+ # Copyright:: May, 2005
7
+ # License:: Ruby License
8
+ # ---
9
+ # = Usage:
10
+ # require 'net/smtp'
11
+ # require 'rubygems'
12
+ # require 'mailfactory'
13
+ #
14
+ #
15
+ # mail = MailFactory.new()
16
+ # mail.to = "test@test.com"
17
+ # mail.from = "sender@sender.com"
18
+ # mail.subject = "Here are some files for you!"
19
+ # mail.text = "This is what people with plain text mail readers will see"
20
+ # mail.html = "A little something <b>special</b> for people with HTML readers"
21
+ # mail.attach("/etc/fstab")
22
+ # mail.attach("/some/other/file")
23
+ #
24
+ # Net::SMTP.start('smtp1.testmailer.com', 25, 'mail.from.domain', fromaddress, password, :cram_md5) { |smtp|
25
+ # mail.to = toaddress
26
+ # smtp.send_message(mail.to_s(), fromaddress, toaddress)
27
+ # }
28
+
29
+ require 'pathname'
30
+
31
+ # try to bring in the mime/types module, make a dummy module if it can't be found
32
+ begin
33
+ begin
34
+ require 'rubygems'
35
+ rescue LoadError
36
+ end
37
+ require 'mime/types'
38
+ rescue LoadError
39
+ module MIME
40
+ class Types
41
+ def Types::type_for(filename)
42
+ return('')
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ # An easy class for creating a mail message
49
+ class MailFactory
50
+
51
+ VERSION = '1.4.0'
52
+
53
+ def initialize()
54
+ @headers = Array.new()
55
+ @attachments = Array.new()
56
+ @attachmentboundary = generate_boundary()
57
+ @bodyboundary = generate_boundary()
58
+ @html = nil
59
+ @text = nil
60
+ @charset = 'utf-8'
61
+ end
62
+
63
+
64
+ # adds a header to the bottom of the headers
65
+ def add_header(header, value)
66
+ value = quoted_printable_with_instruction(value, @charset) if header == 'subject'
67
+ value = quote_address_if_necessary(value, @charset) if %w[from to cc bcc reply-to].include?(header.downcase)
68
+ @headers << "#{header}: #{value}"
69
+ end
70
+
71
+
72
+ # removes the named header - case insensitive
73
+ def remove_header(header)
74
+ @headers.each_index() { |i|
75
+ if(@headers[i] =~ /^#{Regexp.escape(header)}:/i)
76
+ @headers.delete_at(i)
77
+ end
78
+ }
79
+ end
80
+
81
+
82
+ # sets a header (removing any other versions of that header)
83
+ def set_header(header, value)
84
+ remove_header(header)
85
+ add_header(header, value)
86
+ end
87
+
88
+
89
+ def replyto=(newreplyto)
90
+ remove_header("Reply-To")
91
+ add_header("Reply-To", newreplyto)
92
+ end
93
+
94
+
95
+ def replyto()
96
+ return(get_header("Reply-To")[0])
97
+ end
98
+
99
+
100
+ # sets the plain text body of the message
101
+ def text=(newtext)
102
+ @text = newtext
103
+ end
104
+
105
+
106
+ # sets the HTML body of the message. Only the body of the
107
+ # html should be provided
108
+ def html=(newhtml)
109
+ @html = "<html>\n<head>\n<meta content=\"text/html;charset=#{@charset}\" http-equiv=\"Content-Type\">\n</head>\n<body bgcolor=\"#ffffff\" text=\"#000000\">\n#{newhtml}\n</body>\n</html>"
110
+ end
111
+
112
+
113
+ # sets the HTML body of the message. The entire HTML section should be provided
114
+ def rawhtml=(newhtml)
115
+ @html = newhtml
116
+ end
117
+
118
+
119
+ # implement method missing to provide helper methods for setting and getting headers.
120
+ # Headers with '-' characters may be set/gotten as 'x_mailer' or 'XMailer' (splitting
121
+ # will occur between capital letters or on '_' chracters)
122
+ def method_missing(methId, *args)
123
+ name = methId.id2name()
124
+
125
+ # mangle the name if we have to
126
+ if(name =~ /_/)
127
+ name = name.gsub(/_/, '-')
128
+ elsif(name =~ /[A-Z]/)
129
+ name = name.gsub(/([a-zA-Z])([A-Z])/, '\1-\2')
130
+ end
131
+
132
+ # determine if it sets or gets, and do the right thing
133
+ if(name =~ /=$/)
134
+ if(args.length != 1)
135
+ super(methId, args)
136
+ end
137
+ set_header(name[/^(.*)=$/, 1], args[0])
138
+ else
139
+ if(args.length != 0)
140
+ super(methId, args)
141
+ end
142
+ headers = get_header(name)
143
+ return(get_header(name))
144
+ end
145
+ end
146
+
147
+
148
+ # returns the value (or values) of the named header in an array
149
+ def get_header(header)
150
+ headers = Array.new()
151
+ headerregex = /^#{Regexp.escape(header)}:/i
152
+ @headers.each() { |h|
153
+ if(headerregex.match(h))
154
+ headers << h[/^[^:]+:(.*)/i, 1].strip()
155
+ end
156
+ }
157
+
158
+ return(headers)
159
+ end
160
+
161
+
162
+ # returns true if the email is multipart
163
+ def multipart?()
164
+ if(@attachments.length > 0 or @html != nil)
165
+ return(true)
166
+ else
167
+ return(false)
168
+ end
169
+ end
170
+
171
+
172
+ # builds an email and returns it as a string. Takes the following options:
173
+ # <tt>:messageid</tt>:: Adds a message id to the message based on the from header (defaults to false)
174
+ # <tt>:date</tt>:: Adds a date to the message if one is not present (defaults to true)
175
+ def construct(options = Hash.new)
176
+ if(options[:date] == nil)
177
+ options[:date] = true
178
+ end
179
+
180
+ if(options[:messageid])
181
+ # add a unique message-id
182
+ remove_header("Message-ID")
183
+ sendingdomain = get_header('from')[0].to_s()[/@([-a-zA-Z0-9._]+)/,1].to_s()
184
+ add_header("Message-ID", "<#{Time.now.to_f()}.#{Process.euid()}.#{String.new.object_id()}@#{sendingdomain}>")
185
+ end
186
+
187
+ if(options[:date])
188
+ if(get_header("Date").length == 0)
189
+ add_header("Date", Time.now.strftime("%a, %d %b %Y %H:%M:%S %z"))
190
+ end
191
+ end
192
+
193
+ # Add a mime header if we don't already have one and we have multiple parts
194
+ if(multipart?())
195
+ if(get_header("MIME-Version").length == 0)
196
+ add_header("MIME-Version", "1.0")
197
+ end
198
+
199
+ if(get_header("Content-Type").length == 0)
200
+ if(@attachments.length == 0)
201
+ add_header("Content-Type", "multipart/alternative;boundary=\"#{@bodyboundary}\"")
202
+ else
203
+ add_header("Content-Type", "multipart/mixed; boundary=\"#{@attachmentboundary}\"")
204
+ end
205
+ end
206
+ end
207
+
208
+ return("#{headers_to_s()}#{body_to_s()}")
209
+ end
210
+
211
+
212
+ # returns a formatted email - equivalent to construct(:messageid => true)
213
+ def to_s()
214
+ return(construct(:messageid => true))
215
+ end
216
+
217
+
218
+ # generates a unique boundary string
219
+ def generate_boundary()
220
+ randomstring = Array.new()
221
+ 1.upto(25) {
222
+ whichglyph = rand(100)
223
+ if(whichglyph < 40)
224
+ randomstring << (rand(25) + 65).chr()
225
+ elsif(whichglyph < 70)
226
+ randomstring << (rand(25) + 97).chr()
227
+ elsif(whichglyph < 90)
228
+ randomstring << (rand(10) + 48).chr()
229
+ elsif(whichglyph < 95)
230
+ randomstring << '.'
231
+ else
232
+ randomstring << '_'
233
+ end
234
+ }
235
+ return("----=_NextPart_#{randomstring.join()}")
236
+ end
237
+
238
+
239
+ # adds an attachment to the mail. Type may be given as a mime type. If it
240
+ # is left off and the MIME::Types module is available it will be determined automagically.
241
+ # If the optional attachemntheaders is given, then they will be added to the attachment
242
+ # boundary in the email, which can be used to produce Content-ID markers. attachmentheaders
243
+ # can be given as an Array or a String.
244
+ def add_attachment(filename, type=nil, attachmentheaders = nil)
245
+ attachment = Hash.new()
246
+ attachment['filename'] = Pathname.new(filename).basename
247
+ if(type == nil)
248
+ attachment['mimetype'] = MIME::Types.type_for(filename).to_s
249
+ else
250
+ attachment['mimetype'] = type
251
+ end
252
+
253
+ # Open in rb mode to handle Windows, which mangles binary files opened in a text mode
254
+ File.open(filename, "rb") { |fp|
255
+ attachment['attachment'] = file_encode(fp.read())
256
+ }
257
+
258
+ if(attachmentheaders != nil)
259
+ if(!attachmentheaders.kind_of?(Array))
260
+ attachmentheaders = attachmentheaders.split(/\r?\n/)
261
+ end
262
+ attachment['headers'] = attachmentheaders
263
+ end
264
+
265
+ @attachments << attachment
266
+ end
267
+
268
+
269
+ # adds an attachment to the mail as emailfilename. Type may be given as a mime type. If it
270
+ # is left off and the MIME::Types module is available it will be determined automagically.
271
+ # file may be given as an IO stream (which will be read until the end) or as a filename.
272
+ # If the optional attachemntheaders is given, then they will be added to the attachment
273
+ # boundary in the email, which can be used to produce Content-ID markers. attachmentheaders
274
+ # can be given as an Array of a String.
275
+ def add_attachment_as(file, emailfilename, type=nil, attachmentheaders = nil)
276
+ attachment = Hash.new()
277
+ attachment['filename'] = emailfilename
278
+
279
+ if(type != nil)
280
+ attachment['mimetype'] = type.to_s()
281
+ elsif(file.kind_of?(String) or file.kind_of?(Pathname))
282
+ attachment['mimetype'] = MIME::Types.type_for(file.to_s()).to_s
283
+ else
284
+ attachment['mimetype'] = ''
285
+ end
286
+
287
+ if(file.kind_of?(String) or file.kind_of?(Pathname))
288
+ # Open in rb mode to handle Windows, which mangles binary files opened in a text mode
289
+ File.open(file.to_s(), "rb") { |fp|
290
+ attachment['attachment'] = file_encode(fp.read())
291
+ }
292
+ elsif(file.respond_to?(:read))
293
+ attachment['attachment'] = file_encode(file.read())
294
+ else
295
+ raise(Exception, "file is not a supported type (must be a String, Pathnamem, or support read method)")
296
+ end
297
+
298
+ if(attachmentheaders != nil)
299
+ if(!attachmentheaders.kind_of?(Array))
300
+ attachmentheaders = attachmentheaders.split(/\r?\n/)
301
+ end
302
+ attachment['headers'] = attachmentheaders
303
+ end
304
+
305
+ @attachments << attachment
306
+ end
307
+
308
+
309
+ alias attach add_attachment
310
+ alias attach_as add_attachment_as
311
+
312
+ protected
313
+
314
+ # returns the @headers as a properly formatted string
315
+ def headers_to_s()
316
+ return("#{@headers.join("\r\n")}\r\n\r\n")
317
+ end
318
+
319
+
320
+ # returns the body as a properly formatted string
321
+ def body_to_s()
322
+ body = Array.new()
323
+
324
+ # simple message with one part
325
+ if(!multipart?())
326
+ return(@text)
327
+ else
328
+
329
+ if(@attachments.length > 0)
330
+ # text part
331
+ body << "#{buildbodyboundary("text/plain; charset=#{@charset}; format=flowed", 'quoted-printable')}\r\n\r\n#{quote_if_necessary(@text, @charset)}"
332
+
333
+ # html part if one is provided
334
+ if @html
335
+ body << "#{buildbodyboundary("text/html; charset=#{@charset}", 'quoted-printable')}\r\n\r\n#{quote_if_necessary(@html, @charset)}"
336
+ end
337
+
338
+ body << "--#{@bodyboundary}--"
339
+
340
+ # and, the attachments
341
+ if(@attachments.length > 0)
342
+ @attachments.each() { |attachment|
343
+ body << "#{buildattachmentboundary(attachment)}\r\n\r\n#{attachment['attachment']}"
344
+ }
345
+ body << "\r\n--#{@attachmentboundary}--"
346
+ end
347
+ else
348
+ # text part
349
+ body << "#{buildbodyboundary("text/plain; charset=#{@charset}; format=flowed", 'quoted-printable')}\r\n\r\n#{quote_if_necessary(@text, @charset)}"
350
+
351
+ # html part
352
+ body << "#{buildbodyboundary("text/html; charset=#{@charset}", 'quoted-printable')}\r\n\r\n#{quote_if_necessary(@html, @charset)}"
353
+
354
+ body << "--#{@bodyboundary}--"
355
+ end
356
+
357
+ return(body.join("\r\n\r\n"))
358
+ end
359
+ end
360
+
361
+
362
+ # builds a boundary string for including attachments in the body, expects an attachment hash as built by
363
+ # add_attachment and add_attachment_as
364
+ def buildattachmentboundary(attachment)
365
+ disposition = "Content-Disposition: inline; filename=\"#{attachment['filename']}\""
366
+ boundary = "--#{@attachmentboundary}\r\nContent-Type: #{attachment['mimetype']}; name=\"#{attachment['filename']}\"\r\nContent-Transfer-Encoding: base64\r\n#{disposition}"
367
+ if(attachment['headers'])
368
+ boundary = boundary + "\r\n#{attachment['headers'].join("\r\n")}"
369
+ end
370
+
371
+ return(boundary)
372
+ end
373
+
374
+
375
+ # builds a boundary string for inclusion in the body of a message
376
+ def buildbodyboundary(type, encoding)
377
+ return("--#{@bodyboundary}\r\nContent-Type: #{type}\r\nContent-Transfer-Encoding: #{encoding}")
378
+ end
379
+
380
+
381
+ # returns a base64 encoded version of the contents of str
382
+ def file_encode(str)
383
+ collection = Array.new()
384
+ enc = [str].pack('m')
385
+ # while(enc.length > 60)
386
+ # collection << enc.slice!(0..59)
387
+ # end
388
+ # collection << enc
389
+ # return(collection.join("\n"))
390
+ return(enc)
391
+ end
392
+
393
+
394
+ # Convert the given text into quoted printable format, with an instruction
395
+ # that the text be eventually interpreted in the given charset.
396
+
397
+ def quoted_printable_with_instruction(text, charset)
398
+ text = quoted_printable_encode_header(text)
399
+ "=?#{charset}?Q?#{text}?="
400
+ end
401
+
402
+ # rfc2045 compatible. use rfc2047 for headers (such as the Subject line) instead
403
+ def quoted_printable_encode(text)
404
+ [text].pack('M').gsub(/\n/, "\r\n").chomp.gsub(/=$/, '')
405
+ end
406
+
407
+ # Convert the given character to quoted printable format
408
+ # see http://tools.ietf.org/html/rfc2047
409
+
410
+ require 'enumerator' unless ''.respond_to? :enum_for
411
+
412
+ def quoted_printable_encode_header(text)
413
+ text.enum_for(:each_byte).map do |ord|
414
+ if ord < 128 and ord != 61 # 61 is ascii '='
415
+ ord.chr
416
+ else
417
+ '=%X' % ord
418
+ end
419
+ end.join('').
420
+ chomp.
421
+ gsub(/=$/,'').
422
+ gsub('?', '=3F').
423
+ gsub('_', '=5F').
424
+ gsub(/ /, '_')
425
+ end
426
+
427
+
428
+ # A quick-and-dirty regexp for determining whether a string contains any
429
+ # characters that need escaping.
430
+ #--
431
+ # Jun18-08: deprecated, since all multipart blocks are marked quoted-printable, quoting is required
432
+
433
+ # if !defined?(CHARS_NEEDING_QUOTING)
434
+ # CHARS_NEEDING_QUOTING = /[\000-\011\013\014\016-\037\177-\377]/
435
+ # end
436
+
437
+
438
+ # Quote the given text if it contains any "illegal" characters
439
+ def quote_if_necessary(text, charset, instruction = false)
440
+ return unless text
441
+ text = text.dup.force_encoding(Encoding::ASCII_8BIT) if text.respond_to?(:force_encoding)
442
+ #(text =~ CHARS_NEEDING_QUOTING) ? (instruction ? quoted_printable_with_instruction(text, charset) : quoted_printable_encode(text)) : text
443
+ instruction ? quoted_printable_with_instruction(text, charset) : quoted_printable_encode(text)
444
+ end
445
+
446
+
447
+ # Quote the given address if it needs to be. The address may be a
448
+ # regular email address, or it can be a phrase followed by an address in
449
+ # brackets. The phrase is the only part that will be quoted, and only if
450
+ # it needs to be. This allows extended characters to be used in the
451
+ # "to", "from", "cc", and "bcc" headers.
452
+ def quote_address_if_necessary(address, charset)
453
+ if Array === address
454
+ address.map { |a| quote_address_if_necessary(a, charset) }
455
+ elsif address =~ /^(\S.*)\s+(<.*>)$/
456
+ address = $2
457
+ phrase = quote_if_necessary($1.gsub(/^['"](.*)['"]$/, '\1'), charset, true)
458
+ "\"#{phrase}\" #{address}"
459
+ else
460
+ address
461
+ end
462
+ end
463
+
464
+ end
@@ -0,0 +1,9 @@
1
+ #!/bin/sh
2
+
3
+ # destroy old docs and gems
4
+ rm -rf ./doc
5
+ rm -f mailfactory-*.gem
6
+
7
+ # build the gem
8
+ ruby ./mailfactory.gemspec
9
+
@@ -0,0 +1,225 @@
1
+ #!/usr/bin/env ruby
2
+ # coding:utf-8
3
+
4
+ require 'test/unit/ui/console/testrunner'
5
+ require File.dirname(__FILE__) + '/../lib/mailfactory.rb'
6
+
7
+
8
+ def get_options()
9
+ options = Hash.new()
10
+
11
+ opts = OptionParser.new() { |opts|
12
+ opts.on_tail("-h", "--help", "Print this message") {
13
+ print(opts)
14
+ exit()
15
+ }
16
+
17
+ opts.on("-s", "--smtpserver SERVER", "SMTP server to use for remote tests") { |server|
18
+ options['smtpserver'] = server
19
+ }
20
+
21
+ opts.on("-f", "--from ADDRESS", "address to send the mail from") { |address|
22
+ options['from'] = address
23
+ }
24
+
25
+ opts.on("-t", "--to ADDRESS", "address to send the mail to") { |address|
26
+ options['to'] = address
27
+ }
28
+
29
+ opts.on("-u", "--username USERNAME", "username for smtp auth (required)") { |username|
30
+ options['username'] = username
31
+ }
32
+
33
+ opts.on("-p", "--password PASSWORD", "password for smtp auth (required)") { |password|
34
+ options['password'] = password
35
+ }
36
+
37
+ }
38
+
39
+ opts.parse(ARGV)
40
+
41
+ return(options)
42
+ end
43
+
44
+
45
+
46
+ class TC_MailFactory < Test::Unit::TestCase
47
+
48
+ def setup()
49
+ @mail = MailFactory.new
50
+ end
51
+
52
+
53
+ def test_set_to
54
+ assert_nothing_raised("exception raised while setting to=") {
55
+ @mail.to = "test@test.com"
56
+ }
57
+
58
+ assert_equal(@mail.to, ["test@test.com"], "to does not equal what it was set to")
59
+
60
+ assert_nothing_raised("exception raised while setting to=") {
61
+ @mail.to = "test@test2.com"
62
+ }
63
+
64
+ # count to headers in the final message to make sure we have only one
65
+ count = 0
66
+ @mail.to_s().each_line() { |line|
67
+ if(line =~ /^To:/i)
68
+ count = count + 1
69
+ end
70
+ }
71
+ assert_equal(1, count, "Count of To: headers expected to be 1, but was #{count}")
72
+ end
73
+
74
+
75
+ def test_set_from
76
+ assert_nothing_raised("exception raised while setting from=") {
77
+ @mail.from = "test@test.com"
78
+ }
79
+
80
+ assert_equal(@mail.from, ["test@test.com"], "from does not equal what it was set to")
81
+
82
+ assert_nothing_raised("exception raised while setting from=") {
83
+ @mail.from = "test@test2.com"
84
+ }
85
+
86
+ # count to headers in the final message to make sure we have only one
87
+ count = 0
88
+ @mail.to_s().each_line() { |line|
89
+ if(line =~ /^From:/i)
90
+ count = count + 1
91
+ end
92
+ }
93
+ assert_equal(1, count, "Count of From: headers expected to be 1, but was #{count}")
94
+ end
95
+
96
+
97
+ def test_set_subject
98
+ assert_nothing_raised("exception raised while setting subject=") {
99
+ @mail.subject = "Test Subject"
100
+ }
101
+
102
+ assert_equal(["=?utf-8?Q?Test_Subject?="], @mail.subject, "subject does not equal what it was set to")
103
+
104
+ assert_nothing_raised("exception raised while setting subject=") {
105
+ @mail.subject = "A Different Subject"
106
+ }
107
+
108
+ # count to headers in the final message to make sure we have only one
109
+ count = 0
110
+ @mail.to_s().each_line() { |line|
111
+ if(line =~ /^Subject:/i)
112
+ count = count + 1
113
+ end
114
+ }
115
+ assert_equal(1, count, "Count of Subject: headers expected to be 1, but was #{count}")
116
+ end
117
+
118
+
119
+ def test_set_header
120
+ assert_nothing_raised("exception raised while setting arbitrary header") {
121
+ @mail.set_header("arbitrary", "some value")
122
+ }
123
+
124
+ assert_equal("some value", @mail.get_header("arbitrary")[0], "arbitrary header does not equal \"some value\"")
125
+
126
+ assert_nothing_raised("exception raised while setting arbitrary header with _") {
127
+ @mail.arbitrary_header = "some _ value"
128
+ }
129
+
130
+ assert_equal(["some _ value"], @mail.get_header("arbitrary-header"), "arbitrary header does not equal \"some _ value\"")
131
+ assert_equal(["some _ value"], @mail.arbitrary_header, "arbitrary header does not equal \"some _ value\"")
132
+
133
+
134
+ assert_nothing_raised("exception raised while setting arbitraryHeader") {
135
+ @mail.arbitraryHeader = "someValue"
136
+ }
137
+
138
+ assert_equal(["someValue"], @mail.get_header("arbitrary-header"), "arbitrary header does not equal \"someValue\"")
139
+ assert_equal(["someValue"], @mail.arbitraryHeader, "arbitrary header does not equal \"someValue\"")
140
+ end
141
+
142
+
143
+ def test_boundary_generator
144
+ 1.upto(50) {
145
+ assert_match(/^----=_NextPart_[a-zA-Z0-9\._]{25}$/, @mail.generate_boundary(), "illegal message boundary generated")
146
+ }
147
+ end
148
+
149
+
150
+ def test_email
151
+ @mail.to="test@test.com"
152
+ @mail.from="test@othertest.com"
153
+ @mail.subject="This is a test"
154
+ @mail.text = "This is a test message with\na few\n\nlines."
155
+
156
+ @mail.attach(File.dirname(__FILE__) + '/testfile.txt')
157
+ @mail.attach(File.dirname(__FILE__) + '/testsheet.xls')
158
+
159
+ if($options['smtpserver'] != nil and $options['to'] != nil and $options['from'] != nil)
160
+ assert_nothing_raised() {
161
+ require('net/smtp')
162
+ Net::SMTP.start($options['smtpserver'], 25, 'mail.from.domain', $options['username'], $options['password'], :cram_md5) { |smtp|
163
+ smtp.send_message(@mail.to_s(), $options['from'], $options['to'])
164
+ }
165
+ }
166
+ end
167
+ end
168
+
169
+
170
+ def test_attach_as
171
+ @mail.to="test@test.com"
172
+ @mail.from="test@othertest.com"
173
+ @mail.subject="This is a test"
174
+ @mail.text = "This is a test message with\na few\n\nlines."
175
+
176
+ @mail.add_attachment_as(File.dirname(__FILE__) + '/testfile.txt', 'newname.txt')
177
+ @mail.add_attachment_as(File.open(File.dirname(__FILE__) + '/testsheet.xls', 'rb'), 'newname.xls', 'application/vnd.ms-excel')
178
+
179
+ if($options['smtpserver'] != nil and $options['to'] != nil and $options['from'] != nil)
180
+ assert_nothing_raised() {
181
+ require('net/smtp')
182
+ Net::SMTP.start($options['smtpserver'], 25, 'mail.from.domain', $options['username'], $options['password'], :cram_md5) { |smtp|
183
+ smtp.send_message(@mail.to_s(), $options['from'], $options['to'])
184
+ }
185
+ }
186
+ end
187
+ end
188
+
189
+ def test_quoted_printable_with_instruction
190
+ @mail.to="test@test.com"
191
+ @mail.from="test@othertest.com"
192
+ @mail.subject="My email subject has a ? in it and also an = and a _ too... Also some non-quoted junk ()!@\#\{\$\%\}"
193
+ @mail.text = "This is a test message with\na few\n\nlines."
194
+ assert_equal(["=?utf-8?Q?My_email_subject_has_a_=3F_in_it_and_also_an_=3D_and_a_=5F_too..._Also_some_non-quoted_junk_()!@\#\{\$\%\}?="], @mail.subject)
195
+ end
196
+
197
+ def test_scandinavian_subject_quoting
198
+ @mail.to="test@test.com"
199
+ @mail.from="test@othertest.com"
200
+ # Three a with dots and three o with dots.
201
+ @mail.subject="\303\244\303\244\303\244\303\266\303\266\303\266"
202
+ @mail.text = "This is a test message with\na few\n\nlines."
203
+ assert_equal(["=?utf-8?Q?=C3=A4=C3=A4=C3=A4=C3=B6=C3=B6=C3=B6?="], @mail.subject)
204
+ end
205
+
206
+ def test_utf8_quoted_printable_with_instruction
207
+ @mail.to="test@test.com"
208
+ @mail.from="test@othertest.com"
209
+ @mail.subject="My email subject has a à which is utf8."
210
+ @mail.text = "This is a test message with\na few\n\nlines."
211
+ assert_equal(["=?utf-8?Q?My_email_subject_has_a_=C3=83_which_is_utf8.?="], @mail.subject)
212
+ end
213
+
214
+ def test_quoted_printable_html
215
+ @mail.to="test@test.com"
216
+ @mail.from="test@othertest.com"
217
+ @mail.subject="some html"
218
+ @mail.html="<a href=\"http://google.com\">click here</a>"
219
+ assert_match('<a href=3D"http://google.com">click here</a>', @mail.to_s)
220
+ end
221
+
222
+ end
223
+
224
+ $options = get_options()
225
+ Test::Unit::UI::Console::TestRunner.run(TC_MailFactory)
@@ -0,0 +1 @@
1
+ This is a test text file
Binary file
@@ -0,0 +1,19 @@
1
+ #!/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby
2
+ #
3
+ # This file was generated by RubyGems.
4
+ #
5
+ # The application 'rake' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'rubygems'
10
+
11
+ version = ">= 0"
12
+
13
+ if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
14
+ version = $1
15
+ ARGV.shift
16
+ end
17
+
18
+ gem 'rake', version
19
+ load Gem.bin_path('rake', 'rake', version)
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: anthonygarcia-mailfactory
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 4
8
+ - 2
9
+ version: 1.4.2
10
+ platform: ruby
11
+ authors:
12
+ - David Powers
13
+ - Anthony Garcia
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-03-11 00:00:00 -06:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: Create MIME email messages with multiple body parts and attachments in Ruby
23
+ email: frobotnet@gmail.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - .gitignore
32
+ - .hgignore
33
+ - Rakefile
34
+ - VERSION
35
+ - anthonygarcia-mailfactory.gemspec
36
+ - lib/mailfactory.rb
37
+ - mailfactory.gemspec
38
+ - scripts/release.sh
39
+ - tests/test_mailfactory.rb
40
+ - tests/testfile.txt
41
+ - tests/testsheet.xls
42
+ - vendor/bundled_gems/bin/rake
43
+ has_rdoc: true
44
+ homepage: http://github.com/anthonygarcia/mailfactory
45
+ licenses: []
46
+
47
+ post_install_message:
48
+ rdoc_options:
49
+ - --charset=UTF-8
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ segments:
57
+ - 0
58
+ version: "0"
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ requirements: []
67
+
68
+ rubyforge_project:
69
+ rubygems_version: 1.3.6
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: Fork of tmm1/mailfactory to fix BlackBerry issuse
73
+ test_files: []
74
+