mailfactory-acd 1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bd5c22dcb9829217553cb8cfc66edb342495913f
4
+ data.tar.gz: 487f01301096879b20b0f7090075d27aeec88f2c
5
+ SHA512:
6
+ metadata.gz: c8cc09ec8c971cc04ddc2a4a3675c13b17fe8bcaeb172f32221f6e1a04df7b353f733867c39ec03acd5336b22e047af4cef5fa9cd4a13535d2621b71f51740b9
7
+ data.tar.gz: 4df58e799a254ee4a809e20abe0917c7688f164ba794d50a7c8085987b550ab8c29423d0c9db119e44c142a90495814e8e067c4750a3eba85ed0f7f26e7b8508
@@ -0,0 +1,465 @@
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
+ body << "This is a multi-part message in MIME format.\r\n\r\n--#{@attachmentboundary}\r\nContent-Type: multipart/alternative; boundary=\"#{@bodyboundary}\""
329
+
330
+ if(@attachments.length > 0)
331
+ # text part
332
+ body << "#{buildbodyboundary("text/plain; charset=#{@charset}; format=flowed", 'quoted-printable')}\r\n\r\n#{quote_if_necessary(@text, @charset)}"
333
+
334
+ # html part if one is provided
335
+ if @html
336
+ body << "#{buildbodyboundary("text/html; charset=#{@charset}", 'quoted-printable')}\r\n\r\n#{quote_if_necessary(@html, @charset)}"
337
+ end
338
+
339
+ body << "--#{@bodyboundary}--"
340
+
341
+ # and, the attachments
342
+ if(@attachments.length > 0)
343
+ @attachments.each() { |attachment|
344
+ body << "#{buildattachmentboundary(attachment)}\r\n\r\n#{attachment['attachment']}"
345
+ }
346
+ body << "\r\n--#{@attachmentboundary}--"
347
+ end
348
+ else
349
+ # text part
350
+ body << "#{buildbodyboundary("text/plain; charset=#{@charset}; format=flowed", 'quoted-printable')}\r\n\r\n#{quote_if_necessary(@text, @charset)}"
351
+
352
+ # html part
353
+ body << "#{buildbodyboundary("text/html; charset=#{@charset}", 'quoted-printable')}\r\n\r\n#{quote_if_necessary(@html, @charset)}"
354
+
355
+ body << "--#{@bodyboundary}--"
356
+ end
357
+
358
+ return(body.join("\r\n\r\n"))
359
+ end
360
+ end
361
+
362
+
363
+ # builds a boundary string for including attachments in the body, expects an attachment hash as built by
364
+ # add_attachment and add_attachment_as
365
+ def buildattachmentboundary(attachment)
366
+ disposition = "Content-Disposition: inline; filename=\"#{attachment['filename']}\""
367
+ boundary = "--#{@attachmentboundary}\r\nContent-Type: #{attachment['mimetype']}; name=\"#{attachment['filename']}\"\r\nContent-Transfer-Encoding: base64\r\n#{disposition}"
368
+ if(attachment['headers'])
369
+ boundary = boundary + "\r\n#{attachment['headers'].join("\r\n")}"
370
+ end
371
+
372
+ return(boundary)
373
+ end
374
+
375
+
376
+ # builds a boundary string for inclusion in the body of a message
377
+ def buildbodyboundary(type, encoding)
378
+ return("--#{@bodyboundary}\r\nContent-Type: #{type}\r\nContent-Transfer-Encoding: #{encoding}")
379
+ end
380
+
381
+
382
+ # returns a base64 encoded version of the contents of str
383
+ def file_encode(str)
384
+ collection = Array.new()
385
+ enc = [str].pack('m')
386
+ # while(enc.length > 60)
387
+ # collection << enc.slice!(0..59)
388
+ # end
389
+ # collection << enc
390
+ # return(collection.join("\n"))
391
+ return(enc)
392
+ end
393
+
394
+
395
+ # Convert the given text into quoted printable format, with an instruction
396
+ # that the text be eventually interpreted in the given charset.
397
+
398
+ def quoted_printable_with_instruction(text, charset)
399
+ text = quoted_printable_encode_header(text)
400
+ "=?#{charset}?Q?#{text}?="
401
+ end
402
+
403
+ # rfc2045 compatible. use rfc2047 for headers (such as the Subject line) instead
404
+ def quoted_printable_encode(text)
405
+ [text].pack('M').gsub(/\n/, "\r\n").chomp.gsub(/=$/, '')
406
+ end
407
+
408
+ # Convert the given character to quoted printable format
409
+ # see http://tools.ietf.org/html/rfc2047
410
+
411
+ require 'enumerator' unless ''.respond_to? :enum_for
412
+
413
+ def quoted_printable_encode_header(text)
414
+ text.enum_for(:each_byte).map do |ord|
415
+ if ord < 128 and ord != 61 # 61 is ascii '='
416
+ ord.chr
417
+ else
418
+ '=%X' % ord
419
+ end
420
+ end.join('').
421
+ chomp.
422
+ gsub(/=$/,'').
423
+ gsub('?', '=3F').
424
+ gsub('_', '=5F').
425
+ gsub(/ /, '_')
426
+ end
427
+
428
+
429
+ # A quick-and-dirty regexp for determining whether a string contains any
430
+ # characters that need escaping.
431
+ #--
432
+ # Jun18-08: deprecated, since all multipart blocks are marked quoted-printable, quoting is required
433
+
434
+ # if !defined?(CHARS_NEEDING_QUOTING)
435
+ # CHARS_NEEDING_QUOTING = /[\000-\011\013\014\016-\037\177-\377]/
436
+ # end
437
+
438
+
439
+ # Quote the given text if it contains any "illegal" characters
440
+ def quote_if_necessary(text, charset, instruction = false)
441
+ return unless text
442
+ text = text.dup.force_encoding(Encoding::ASCII_8BIT) if text.respond_to?(:force_encoding)
443
+ #(text =~ CHARS_NEEDING_QUOTING) ? (instruction ? quoted_printable_with_instruction(text, charset) : quoted_printable_encode(text)) : text
444
+ instruction ? quoted_printable_with_instruction(text, charset) : quoted_printable_encode(text)
445
+ end
446
+
447
+
448
+ # Quote the given address if it needs to be. The address may be a
449
+ # regular email address, or it can be a phrase followed by an address in
450
+ # brackets. The phrase is the only part that will be quoted, and only if
451
+ # it needs to be. This allows extended characters to be used in the
452
+ # "to", "from", "cc", and "bcc" headers.
453
+ def quote_address_if_necessary(address, charset)
454
+ if Array === address
455
+ address.map { |a| quote_address_if_necessary(a, charset) }
456
+ elsif address =~ /^(\S.*)\s+(<.*>)$/
457
+ address = $2
458
+ phrase = quote_if_necessary($1.gsub(/^['"](.*)['"]$/, '\1'), charset, true)
459
+ "\"#{phrase}\" #{address}"
460
+ else
461
+ address
462
+ end
463
+ end
464
+
465
+ end
@@ -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)
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mailfactory-acd
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.4.0
5
+ platform: ruby
6
+ authors:
7
+ - David Powers
8
+ - CJ Lazell
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-11-13 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: mime-types
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: 1.13.1
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: 1.13.1
28
+ description: MailFactory is s simple module for producing RFC compliant mail that
29
+ can include multiple attachments, multiple body parts, and arbitrary headers
30
+ email:
31
+ - david@grayskies.net
32
+ - cjlazell@gmail.com
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - lib/mailfactory.rb
38
+ - tests/test_mailfactory.rb
39
+ homepage: https://github.com/acdcorp/mailfactory
40
+ licenses:
41
+ - MIT
42
+ metadata: {}
43
+ post_install_message:
44
+ rdoc_options: []
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ requirements: []
58
+ rubyforge_project:
59
+ rubygems_version: 2.2.2
60
+ signing_key:
61
+ specification_version: 4
62
+ summary: MailFactory is a pure-ruby MIME mail generator
63
+ test_files: []