mime 0.4.1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.rdoc +2 -0
- data/lib/mime.rb +1 -1
- data/lib/mime/content_formats/text_flowed.rb +8 -1
- data/lib/mime/header.rb +2 -2
- data/lib/mime/headers/internet.rb +1 -1
- data/lib/mime/headers/mime.rb +3 -3
- data/lib/mime/mail.rb +12 -2
- data/test/test_mime.rb +34 -0
- data/test/test_text_flowed.rb +7 -2
- metadata +36 -43
- data/test/test_mime.rb-try +0 -616
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4cfd511f4221d7e04909d860f85eddb218d46e99
|
4
|
+
data.tar.gz: 3e43d9945ffdee1a5fe5e4c8f0365ea64707c36e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bd1a127ac7d9f8fef49a346ccc64c10f4f1f028357ac36a254960aa61e48168b95d202d4acb1a741c897bc34697a21041fa19e4586862c24b8ffa5697855cec0
|
7
|
+
data.tar.gz: d70123f3578684bbe430fe85a5d440d2a393a74e1b633941f610de737a51fa8acf2863af7fdc415f591c055b7cdccf5c44b5259deb334b357db0b60cd970c283
|
data/README.rdoc
CHANGED
@@ -372,6 +372,8 @@ Validators :: Please check *all* of your messages using the following lint
|
|
372
372
|
5. 2014-04-20, v0.4.1
|
373
373
|
* Add bug tracker URL.
|
374
374
|
* Link to referenced commit messages.
|
375
|
+
6. 2014-06-13, v0.4.2
|
376
|
+
* Ruby 1.8.7 compatibility fix.
|
375
377
|
|
376
378
|
|
377
379
|
== License
|
data/lib/mime.rb
CHANGED
@@ -1,9 +1,16 @@
|
|
1
|
+
#
|
2
|
+
# == Content Formats
|
3
|
+
#
|
4
|
+
# [Text/Plain Flowed] TextFlowed
|
5
|
+
# [Quoted-Printable] To be implemented ...
|
6
|
+
# [Base64] To be implemented ...
|
7
|
+
#
|
1
8
|
module MIME::ContentFormats
|
2
9
|
|
3
10
|
#
|
4
11
|
# Minimal implementation of RFC 2646: The Text/Plain Format Parameter
|
5
12
|
#
|
6
|
-
# https://
|
13
|
+
# https://tools.ietf.org/html/rfc2646
|
7
14
|
#
|
8
15
|
# == Excerpts from RFC
|
9
16
|
#
|
data/lib/mime/header.rb
CHANGED
@@ -34,14 +34,14 @@ module MIME
|
|
34
34
|
#
|
35
35
|
def set name, value
|
36
36
|
delete(name)
|
37
|
-
@headers.store(name, value)
|
37
|
+
@headers.store(name, value) unless value.nil?
|
38
38
|
end
|
39
39
|
|
40
40
|
#
|
41
41
|
# Delete header associated with +name+.
|
42
42
|
#
|
43
43
|
def delete name
|
44
|
-
@headers.delete_if {|k| name.downcase == k.downcase }
|
44
|
+
@headers.delete_if {|k,v| name.downcase == k.downcase }
|
45
45
|
end
|
46
46
|
|
47
47
|
end
|
@@ -7,7 +7,7 @@ module MIME
|
|
7
7
|
# Mailbox fields #to, #from, #cc, #bcc, and #reply_to may be a single email
|
8
8
|
# address, an array of email addresses, or a hash of _email_ => _name_
|
9
9
|
# pairs. When using a hash, set _name_ to +nil+ to omit email display name.
|
10
|
-
# The #sender field is a special case and
|
10
|
+
# The #sender field is a special case and can only contain a single mailbox.
|
11
11
|
#
|
12
12
|
module Internet
|
13
13
|
|
data/lib/mime/headers/mime.rb
CHANGED
@@ -90,9 +90,9 @@ module MIME
|
|
90
90
|
# +params+ is a Hash with zero or more of the following keys:
|
91
91
|
#
|
92
92
|
# +filename+ :: name of file
|
93
|
-
# +creation-date+ :: RFC2822
|
94
|
-
# +modification-date+ :: RFC2822
|
95
|
-
# +read-date+ :: RFC2822
|
93
|
+
# +creation-date+ :: RFC2822 date-time
|
94
|
+
# +modification-date+ :: RFC2822 date-time
|
95
|
+
# +read-date+ :: RFC2822 date-time
|
96
96
|
# +size+ :: file size in octets
|
97
97
|
#
|
98
98
|
# The values for the *-date keys may use Time::rfc2822.
|
data/lib/mime/mail.rb
CHANGED
@@ -25,14 +25,14 @@ module MIME
|
|
25
25
|
# Format the Mail object as an Internet message.
|
26
26
|
#
|
27
27
|
def to_s
|
28
|
+
self.sender ||= sender_address
|
28
29
|
self.message_id ||= ID.generate_gid(domain)
|
29
30
|
body.mime_version ||= "1.0 (Ruby MIME v#{VERSION})"
|
30
|
-
# TODO if From contains multiple mailboxes Sender must be present
|
31
31
|
|
32
32
|
#--
|
33
33
|
# In an RFC 2822 message, the header and body sections must be separated
|
34
34
|
# by two line breaks (i.e., 2*CRLF). One line break is deliberately
|
35
|
-
# omitted here
|
35
|
+
# omitted here so the MIME body supplier can append headers to the
|
36
36
|
# top-level message header section.
|
37
37
|
#++
|
38
38
|
"#{headers}\r\n#{body}"
|
@@ -44,6 +44,16 @@ module MIME
|
|
44
44
|
|
45
45
|
private
|
46
46
|
|
47
|
+
#
|
48
|
+
# Return the first From address as the sender if multiple From addresses.
|
49
|
+
#
|
50
|
+
def sender_address
|
51
|
+
case from
|
52
|
+
when Hash; Hash[*from.first] if from.size > 1
|
53
|
+
when Array; from.first if from.size > 1
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
47
57
|
def domain
|
48
58
|
headers.get('from').match(/@([[:alnum:].-]+)/)[1] rescue nil
|
49
59
|
end
|
data/test/test_mime.rb
CHANGED
@@ -301,6 +301,24 @@ EOF
|
|
301
301
|
assert_equal("#{msg_id}", msg.message_id)
|
302
302
|
end
|
303
303
|
|
304
|
+
def test_sender_field_auto_generation
|
305
|
+
msg = MIME::Mail.new
|
306
|
+
msg.from = addresses = %w(john@example.com jane@example.com)
|
307
|
+
assert_nil msg.sender
|
308
|
+
msg.to_s # add sender header when multiple from addresses
|
309
|
+
assert_equal addresses.first, msg.sender
|
310
|
+
end
|
311
|
+
|
312
|
+
def test_sender_field_manual_assignment
|
313
|
+
msg = MIME::Mail.new
|
314
|
+
msg.from = %w(john@example.com jane@example.com)
|
315
|
+
assert_nil msg.sender
|
316
|
+
msg.sender = sender = 'jack@example.com'
|
317
|
+
assert_equal sender, msg.sender
|
318
|
+
msg.to_s # should not affect sender header
|
319
|
+
assert_equal sender, msg.sender
|
320
|
+
end
|
321
|
+
|
304
322
|
def test_rfc2822_date_format
|
305
323
|
msg = MIME::Mail.new
|
306
324
|
assert_kind_of(Time, msg.date)
|
@@ -372,6 +390,22 @@ EOF
|
|
372
390
|
assert_equal '', headers.to_s
|
373
391
|
end
|
374
392
|
|
393
|
+
def test_header_field_removal_via_set_nil
|
394
|
+
headers = MIME::Header.new
|
395
|
+
headers.set 'a', 'b'
|
396
|
+
assert_equal 'b', headers.get('a')
|
397
|
+
headers.set 'a', nil
|
398
|
+
assert_nil headers.get('a')
|
399
|
+
end
|
400
|
+
|
401
|
+
def test_header_field_removal_via_delete
|
402
|
+
headers = MIME::Header.new
|
403
|
+
headers.set 'a', 'b'
|
404
|
+
assert_equal 'b', headers.get('a')
|
405
|
+
headers.delete 'a'
|
406
|
+
assert_nil headers.get('a')
|
407
|
+
end
|
408
|
+
|
375
409
|
def test_mailbox_types
|
376
410
|
e1 = 'john@example.com'
|
377
411
|
e2 = 'jane@example.com'
|
data/test/test_text_flowed.rb
CHANGED
@@ -6,6 +6,10 @@ class TextFlowedTest < Minitest::Test
|
|
6
6
|
|
7
7
|
include MIME::ContentFormats
|
8
8
|
|
9
|
+
def test_empty_string
|
10
|
+
assert_equal '', TextFlowed.encode('')
|
11
|
+
end
|
12
|
+
|
9
13
|
def test_single_word_will_not_break_regardless_of_line_length
|
10
14
|
txt = "1234567890"
|
11
15
|
assert_equal txt, TextFlowed.encode(txt, 9) # <
|
@@ -107,8 +111,9 @@ class TextFlowedTest < Minitest::Test
|
|
107
111
|
end
|
108
112
|
|
109
113
|
def test_rfc_79_character_max_flowed_line_length
|
110
|
-
|
111
|
-
|
114
|
+
assert_equal (max = 79), TextFlowed::MAX_FLOWED_LINE
|
115
|
+
TextFlowed.encode('', max) # no error
|
116
|
+
assert_raises(ArgumentError) { TextFlowed.encode('', max+1) }
|
112
117
|
end
|
113
118
|
|
114
119
|
def test_rfc_max_smtp_line_length_boundary
|
metadata
CHANGED
@@ -1,25 +1,20 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mime
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
5
|
-
prerelease:
|
4
|
+
version: 0.4.2
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Clint Pachl
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2014-
|
11
|
+
date: 2014-06-13 00:00:00.000000000 Z
|
13
12
|
dependencies: []
|
14
|
-
description:
|
15
|
-
|
13
|
+
description: |
|
14
|
+
A library for building RFC compliant Multipurpose Internet Mail Extensions
|
16
15
|
(MIME) messages. It can be used to construct standardized MIME messages for use
|
17
|
-
|
18
16
|
in client/server communications, such as Internet mail or HTTP
|
19
|
-
|
20
17
|
multipart/form-data transactions.
|
21
|
-
|
22
|
-
'
|
23
18
|
email: pachl@ecentryx.com
|
24
19
|
executables: []
|
25
20
|
extensions: []
|
@@ -27,72 +22,70 @@ extra_rdoc_files: []
|
|
27
22
|
files:
|
28
23
|
- README.rdoc
|
29
24
|
- Rakefile
|
30
|
-
- mime.
|
31
|
-
- lib/mime/headers/mime.rb
|
32
|
-
- lib/mime/headers/internet.rb
|
33
|
-
- lib/mime/discrete_media_factory.rb
|
34
|
-
- lib/mime/error.rb
|
35
|
-
- lib/mime/parser.rb
|
36
|
-
- lib/mime/content_types.rb
|
37
|
-
- lib/mime/media.rb
|
25
|
+
- lib/mime.rb
|
38
26
|
- lib/mime/composite_media.rb
|
39
27
|
- lib/mime/content_formats/text_flowed.rb
|
28
|
+
- lib/mime/content_types.rb
|
29
|
+
- lib/mime/discrete_media.rb
|
30
|
+
- lib/mime/discrete_media_factory.rb
|
31
|
+
- lib/mime/error.rb
|
40
32
|
- lib/mime/header.rb
|
33
|
+
- lib/mime/headers/internet.rb
|
34
|
+
- lib/mime/headers/mime.rb
|
41
35
|
- lib/mime/mail.rb
|
42
|
-
- lib/mime/
|
43
|
-
- lib/mime.rb
|
36
|
+
- lib/mime/media.rb
|
37
|
+
- lib/mime/parser.rb
|
38
|
+
- mime.gemspec
|
44
39
|
- test/scaffold/application.msg
|
45
|
-
- test/scaffold/
|
46
|
-
- test/scaffold/video.msg
|
47
|
-
- test/scaffold/mini.mov
|
48
|
-
- test/scaffold/image.jpg
|
40
|
+
- test/scaffold/audio.msg
|
49
41
|
- test/scaffold/book.pdf
|
50
|
-
- test/scaffold/
|
51
|
-
- test/scaffold/ruby.png
|
52
|
-
- test/scaffold/multipart_alternative.msg
|
53
|
-
- test/scaffold/multipart_mixed_inline_and_attachment2.msg
|
54
|
-
- test/scaffold/image.msg
|
55
|
-
- test/scaffold/multipart_form_data_file_and_text.msg
|
42
|
+
- test/scaffold/data.htm
|
56
43
|
- test/scaffold/data.xml
|
57
|
-
- test/scaffold/
|
58
|
-
- test/scaffold/
|
44
|
+
- test/scaffold/image.jpg
|
45
|
+
- test/scaffold/image.msg
|
59
46
|
- test/scaffold/main.css
|
47
|
+
- test/scaffold/mini.mov
|
48
|
+
- test/scaffold/multipart_alternative.msg
|
60
49
|
- test/scaffold/multipart_alternative_related.msg
|
50
|
+
- test/scaffold/multipart_form_data_file_and_text.msg
|
51
|
+
- test/scaffold/multipart_form_data_mixed.msg
|
61
52
|
- test/scaffold/multipart_form_data_text.msg
|
62
|
-
- test/scaffold/
|
53
|
+
- test/scaffold/multipart_mixed_inline_and_attachment.msg
|
54
|
+
- test/scaffold/multipart_mixed_inline_and_attachment2.msg
|
63
55
|
- test/scaffold/multipart_related.msg
|
56
|
+
- test/scaffold/rfc822_composite.msg
|
64
57
|
- test/scaffold/rfc822_discrete.msg
|
65
|
-
- test/scaffold/
|
66
|
-
- test/scaffold/
|
67
|
-
- test/scaffold/
|
68
|
-
- test/
|
58
|
+
- test/scaffold/ruby.png
|
59
|
+
- test/scaffold/song.mp3
|
60
|
+
- test/scaffold/text.msg
|
61
|
+
- test/scaffold/unknown.yyy
|
62
|
+
- test/scaffold/video.msg
|
69
63
|
- test/test_mime.rb
|
70
64
|
- test/test_text_flowed.rb
|
71
65
|
homepage: http://ecentryx.com/gems/mime
|
72
66
|
licenses:
|
73
67
|
- ISC
|
68
|
+
metadata: {}
|
74
69
|
post_install_message:
|
75
70
|
rdoc_options: []
|
76
71
|
require_paths:
|
77
72
|
- lib
|
78
73
|
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
-
none: false
|
80
74
|
requirements:
|
81
|
-
- -
|
75
|
+
- - ">="
|
82
76
|
- !ruby/object:Gem::Version
|
83
77
|
version: '0'
|
84
78
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
-
none: false
|
86
79
|
requirements:
|
87
|
-
- -
|
80
|
+
- - ">="
|
88
81
|
- !ruby/object:Gem::Version
|
89
82
|
version: '0'
|
90
83
|
requirements: []
|
91
84
|
rubyforge_project:
|
92
|
-
rubygems_version:
|
85
|
+
rubygems_version: 2.2.0
|
93
86
|
signing_key:
|
94
|
-
specification_version:
|
87
|
+
specification_version: 4
|
95
88
|
summary: Multipurpose Internet Mail Extensions (MIME) Library
|
96
89
|
test_files:
|
97
|
-
- test/test_mime.rb
|
98
90
|
- test/test_text_flowed.rb
|
91
|
+
- test/test_mime.rb
|
data/test/test_mime.rb-try
DELETED
@@ -1,616 +0,0 @@
|
|
1
|
-
# THIS IS STILL HERE BECAUSE A LOT OF WORK WENT INTO MAKING TESTS AGNOSTIC OF MIME HEADER ORDER.
|
2
|
-
# HOWEVER, THINGS GOT MESSY SO REVERTED BACK TO COMPARING AGAINST KNOWN GOOD MESSAGES.
|
3
|
-
# THIS IS HERE JUST IN CASE. IN THE FUTURE, REMOVE IT IF THERE IS NO NEED FOR IT.
|
4
|
-
|
5
|
-
gem 'minitest' # minitest in 1.9 stdlib is crufty
|
6
|
-
require 'minitest/autorun'
|
7
|
-
require 'mime'
|
8
|
-
|
9
|
-
# may be able to remove in 2.0
|
10
|
-
Encoding.default_external = 'ASCII-8BIT'
|
11
|
-
|
12
|
-
class MIMETest < Minitest::Test
|
13
|
-
|
14
|
-
CRLF = "\r\n"
|
15
|
-
HDR_BDY_SEP = CRLF * 2
|
16
|
-
MESSAGE_ID = /^Message-ID: <\d+@\d+>\r\n/
|
17
|
-
CONTENT_ID = /^Content-ID: <\d+\.\d+>\r\n/
|
18
|
-
|
19
|
-
CDISPOSITION = /^Content-Disposition: .*\r\n/
|
20
|
-
CTYPE = /^Content-Type: .*\r\n/
|
21
|
-
|
22
|
-
DATE = /^Date: ..., \d{1,2} ... \d{4} \d\d:\d\d:\d\d -\d{4}\r\n/
|
23
|
-
VERSION = /^MIME-Version: 1.0 \(Ruby MIME v\d\.\d\)\r\n/
|
24
|
-
#BOUNDARY = /^--Boundary_\d+\.\d+\r\n/
|
25
|
-
BOUNDARY = /^--Boundary_\d+\.\d+(--)?\r\n/
|
26
|
-
BOUNDARY_LAST = /^--Boundary_\d+\.\d+--\r\n/
|
27
|
-
CID = /cid:\d+\.\d+/
|
28
|
-
|
29
|
-
CTYPE_TEXT_PLAIN = /^Content-Type: text\/plain; charset=us-ascii\r\n/
|
30
|
-
CTYPE_TEXT_HTML = /^Content-Type: text\/html\r\n/
|
31
|
-
CTYPE_TEXT_XML = /^Content-Type: text\/xml\r\n/
|
32
|
-
CTYPE_IMAGE_JPEG = /^Content-Type: image\/jpeg\r\n/
|
33
|
-
CTYPE_IMAGE_PNG = /^Content-Type: image\/png\r\n/
|
34
|
-
CTYPE_VIDEO_MPEG = /^Content-Type: video\/mpeg\r\n/
|
35
|
-
CTYPE_AUDIO_MIDI = /^Content-Type: audio\/midi\r\n/
|
36
|
-
CTYPE_APPLICATION = /^Content-Type: application\/octet-stream\r\n/
|
37
|
-
|
38
|
-
CTYPE_MPART_FORM = /^Content-Type: multipart\/form-data; boundary=Boundary_\d+\.\d+\r\n/
|
39
|
-
CTYPE_MPART_ALT = /^Content-Type: multipart\/alternative; boundary=Boundary_\d+\.\d+\r\n/
|
40
|
-
CTYPE_MPART_MIXED = /^Content-Type: multipart\/mixed; boundary=Boundary_\d+\.\d+\r\n/
|
41
|
-
|
42
|
-
XFER_ENC_BINARY = /^Content-Transfer-Encoding: binary\r\n/
|
43
|
-
XFER_ENC_8BIT = /^Content-Transfer-Encoding: 8bit\r\n/
|
44
|
-
|
45
|
-
BINARY_DATA = '0110000101110101011001000110100101101111'
|
46
|
-
|
47
|
-
def test_make_top_level_rfc2822_message
|
48
|
-
rfc2822_msg = MIME::Message.new
|
49
|
-
rfc2822_msg.body = "\r\nmessage body"
|
50
|
-
msg = rfc2822_msg.to_s
|
51
|
-
|
52
|
-
assert_match MESSAGE_ID, msg
|
53
|
-
assert_match DATE, msg
|
54
|
-
assert_match VERSION, msg
|
55
|
-
assert_equal_num_headers 3, msg
|
56
|
-
assert_equal_body "message body", msg
|
57
|
-
end
|
58
|
-
|
59
|
-
# TODO remove audio.msg
|
60
|
-
def test_make_audio_message
|
61
|
-
audio_media = MIME::AudioMedia.new(BINARY_DATA, 'audio/midi')
|
62
|
-
audio_media.content_transfer_encoding = 'binary'
|
63
|
-
msg = MIME::Message.new(audio_media).to_s
|
64
|
-
|
65
|
-
[CONTENT_ID, XFER_ENC_BINARY, CTYPE_AUDIO_MIDI].each do |header|
|
66
|
-
assert_match header, msg
|
67
|
-
end
|
68
|
-
assert_equal_num_headers 6, msg
|
69
|
-
assert_equal_body BINARY_DATA, msg
|
70
|
-
end
|
71
|
-
|
72
|
-
# TODO remove expected_mime_msg = IO.read(sd('/application.msg'))
|
73
|
-
def test_make_application_message
|
74
|
-
application_media = MIME::ApplicationMedia.new(BINARY_DATA)
|
75
|
-
application_media.content_transfer_encoding = 'binary'
|
76
|
-
msg = MIME::Message.new(application_media).to_s
|
77
|
-
|
78
|
-
[CONTENT_ID, XFER_ENC_BINARY, CTYPE_APPLICATION].each do |header|
|
79
|
-
assert_match header, msg
|
80
|
-
end
|
81
|
-
assert_equal_num_headers 6, msg
|
82
|
-
assert_equal_body BINARY_DATA, msg
|
83
|
-
end
|
84
|
-
|
85
|
-
# TODO remove image.msg
|
86
|
-
def test_make_image_message
|
87
|
-
image = IO.read(sd('/image.jpg'))
|
88
|
-
image_media = MIME::ImageMedia.new(image)
|
89
|
-
image_media.content_type = 'image/jpeg'
|
90
|
-
image_media.content_transfer_encoding = 'binary'
|
91
|
-
msg = MIME::Message.new(image_media).to_s
|
92
|
-
|
93
|
-
[CONTENT_ID, XFER_ENC_BINARY, CTYPE_IMAGE_JPEG].each do |header|
|
94
|
-
assert_match header, msg
|
95
|
-
end
|
96
|
-
|
97
|
-
assert_equal_num_headers 6, msg
|
98
|
-
assert_equal_body image, msg
|
99
|
-
end
|
100
|
-
|
101
|
-
# TODO remove text.msg
|
102
|
-
def test_make_text_message
|
103
|
-
body = 'a plain text message'
|
104
|
-
msg = MIME::Message.new(MIME::TextMedia.new(body)).to_s
|
105
|
-
|
106
|
-
[CTYPE_TEXT_PLAIN].each do |header|
|
107
|
-
assert_match header, msg
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
# TODO remove video.msg
|
112
|
-
def test_make_video_message
|
113
|
-
video_media = MIME::VideoMedia.new(BINARY_DATA)
|
114
|
-
video_media.content_type = 'video/mpeg'
|
115
|
-
video_media.content_transfer_encoding = 'binary'
|
116
|
-
msg = MIME::Message.new(video_media).to_s
|
117
|
-
|
118
|
-
[CONTENT_ID, XFER_ENC_BINARY, CTYPE_VIDEO_MPEG].each do |header|
|
119
|
-
assert_match header, msg
|
120
|
-
end
|
121
|
-
assert_equal_num_headers 6, msg
|
122
|
-
assert_equal_body BINARY_DATA, msg
|
123
|
-
end
|
124
|
-
|
125
|
-
def test_no_instantiation_of_abstract_classes
|
126
|
-
e = MIME::AbstractClassError
|
127
|
-
assert_raises(e) {MIME::MediaType.new(nil, nil)}
|
128
|
-
assert_raises(e) {MIME::DiscreteMediaType.new(nil)}
|
129
|
-
assert_raises(e) {MIME::CompositeMediaType.new(nil)}
|
130
|
-
assert_raises(e) {MIME::MultipartMedia.new(nil)}
|
131
|
-
end
|
132
|
-
|
133
|
-
# def test_boundaries
|
134
|
-
# # CREATE a multipart message; take simplified version of next form data
|
135
|
-
# # test
|
136
|
-
# e = msg.scan(BOUNDARY).each
|
137
|
-
# first_boundary = e.next
|
138
|
-
# assert_equal first_boundary, e.next
|
139
|
-
# assert_equal first_boundary, e.next
|
140
|
-
# last_boundary = e.next
|
141
|
-
# refute_equal first_boundary, last_boundary
|
142
|
-
# assert_match /^--Boundary_\d+\.\d+\r\n/, first_boundary
|
143
|
-
# assert_match /^--Boundary_\d+\.\d+--\r\n/, last_boundary
|
144
|
-
# end
|
145
|
-
#
|
146
|
-
# def test_unique_content_ids_in_multipart_message
|
147
|
-
#
|
148
|
-
# content_ids = msg.scan(/^Content-ID: <(\d+.\d+)>/)
|
149
|
-
# assert_equal 4, content_ids.flatten.uniq.size # all IDs must be unique
|
150
|
-
# end
|
151
|
-
|
152
|
-
# TODO rm multipart_form_data_text.msg
|
153
|
-
def test_multipart_form_data_with_text_entities
|
154
|
-
txt_data = 'text body'
|
155
|
-
htm_data = IO.read(sd('data.htm'))
|
156
|
-
xml_data = IO.read(sd('data.xml'))
|
157
|
-
|
158
|
-
txt = MIME::TextMedia.new('text body')
|
159
|
-
htm = MIME::TextMedia.new(htm_data, 'text/html')
|
160
|
-
xml = MIME::TextMedia.new(xml_data, 'text/xml')
|
161
|
-
|
162
|
-
form_data = MIME::MultipartMedia::FormData.new
|
163
|
-
form_data.add_entity txt, 'txt'
|
164
|
-
form_data.add_entity htm, 'htm'
|
165
|
-
form_data.add_entity xml, 'xml'
|
166
|
-
msg = form_data.to_s
|
167
|
-
|
168
|
-
parts = msg.split(BOUNDARY)
|
169
|
-
assert_equal 5, parts.size, 'main header, 3 entities, last boundary'
|
170
|
-
assert_equal '--', parts.pop, 'remnant of last boundary marker'
|
171
|
-
|
172
|
-
# main header
|
173
|
-
assert_match CONTENT_ID, parts[0]
|
174
|
-
assert_match CTYPE_MPART_FORM, parts[0]
|
175
|
-
assert_equal_num_headers 2, parts[0]
|
176
|
-
assert_equal_body '', parts[0]
|
177
|
-
|
178
|
-
# xml entity
|
179
|
-
assert_match CONTENT_ID, parts[1]
|
180
|
-
assert_match CTYPE_TEXT_XML, parts[1]
|
181
|
-
assert_match /^Content-Disposition: form-data; name="xml"\r\n/, parts[1]
|
182
|
-
assert_equal_num_headers 3, parts[1]
|
183
|
-
assert_equal_body xml_data, parts[1]
|
184
|
-
|
185
|
-
# html entity
|
186
|
-
assert_match CONTENT_ID, parts[2]
|
187
|
-
assert_match CTYPE_TEXT_HTML, parts[2]
|
188
|
-
assert_match /^Content-Disposition: form-data; name="htm"\r\n/, parts[2]
|
189
|
-
assert_equal_num_headers 3, parts[2]
|
190
|
-
assert_equal_body htm_data, parts[2]
|
191
|
-
|
192
|
-
# text entity
|
193
|
-
assert_match CONTENT_ID, parts[3]
|
194
|
-
assert_match CTYPE_TEXT_PLAIN, parts[3]
|
195
|
-
assert_match /^Content-Disposition: form-data; name="txt"\r\n/, parts[3]
|
196
|
-
assert_equal_num_headers 3, parts[3]
|
197
|
-
assert_equal_body txt_data, parts[3]
|
198
|
-
end
|
199
|
-
|
200
|
-
# TODO test that only basename of the file is included in header
|
201
|
-
# test if no filename is used, then probably no filename param
|
202
|
-
# see next test for ideas
|
203
|
-
def test_content_disposition_filename
|
204
|
-
|
205
|
-
pass
|
206
|
-
end
|
207
|
-
|
208
|
-
# rm multipart_form_data_file.msg
|
209
|
-
# rm multipart_form_data_file_and_text.msg
|
210
|
-
def test_multipart_form_data_with_text_and_file_entities
|
211
|
-
img1_filename = 'image.jpg'
|
212
|
-
img2_filename = 'ruby.png'
|
213
|
-
img1_data = IO.read(sd(img1_filename))
|
214
|
-
img2_data = IO.read(sd(img2_filename))
|
215
|
-
img1 = MIME::ImageMedia.new(img1_data, 'image/jpeg')
|
216
|
-
img2 = MIME::ImageMedia.new(img2_data, 'image/png')
|
217
|
-
img1.content_transfer_encoding = '8bit'
|
218
|
-
img2.content_transfer_encoding = '8bit'
|
219
|
-
|
220
|
-
desc_data = 'This is plain text description of images.'
|
221
|
-
desc = MIME::TextMedia.new(desc_data)
|
222
|
-
|
223
|
-
form_data = MIME::MultipartMedia::FormData.new
|
224
|
-
form_data.add_entity desc, 'description'
|
225
|
-
form_data.add_entity img2, 'image_2', img2_filename
|
226
|
-
form_data.add_entity img1, 'image_1', img1_filename
|
227
|
-
msg = form_data.to_s
|
228
|
-
|
229
|
-
parts = msg.split(BOUNDARY)
|
230
|
-
assert_equal 5, parts.size, 'main header, 3 entities, last boundary'
|
231
|
-
assert_equal '--', parts.pop, 'remnant of last boundary marker'
|
232
|
-
|
233
|
-
# main header
|
234
|
-
assert_match CONTENT_ID, parts[0]
|
235
|
-
assert_match CTYPE_MPART_FORM, parts[0]
|
236
|
-
assert_equal_num_headers 2, parts[0]
|
237
|
-
assert_equal_body '', parts[0]
|
238
|
-
|
239
|
-
# first image entity
|
240
|
-
assert_match CONTENT_ID, parts[1]
|
241
|
-
assert_match CTYPE_IMAGE_JPEG, parts[1]
|
242
|
-
assert_match XFER_ENC_8BIT, parts[1]
|
243
|
-
assert_match /^Content-Disposition: form-data; name="image_1"; filename="#{img1_filename}"\r\n/, parts[1]
|
244
|
-
assert_equal_num_headers 4, parts[1]
|
245
|
-
assert_equal_body img1_data, parts[1]
|
246
|
-
|
247
|
-
# second image entity
|
248
|
-
assert_match CONTENT_ID, parts[2]
|
249
|
-
assert_match CTYPE_IMAGE_PNG, parts[2]
|
250
|
-
assert_match XFER_ENC_8BIT, parts[2]
|
251
|
-
assert_match /^Content-Disposition: form-data; name="image_2"; filename="#{img2_filename}"\r\n/, parts[2]
|
252
|
-
assert_equal_num_headers 4, parts[2]
|
253
|
-
assert_equal_body img2_data, parts[2]
|
254
|
-
|
255
|
-
# plain text entity
|
256
|
-
assert_match CONTENT_ID, parts[3]
|
257
|
-
assert_match CTYPE_TEXT_PLAIN, parts[3]
|
258
|
-
assert_match /^Content-Disposition: form-data; name="description"\r\n/, parts[3]
|
259
|
-
assert_equal_num_headers 3, parts[3]
|
260
|
-
assert_equal_body desc_data, parts[3]
|
261
|
-
end
|
262
|
-
|
263
|
-
# rm plain_text_email.msg
|
264
|
-
def test_construction_of_plain_text_email_message
|
265
|
-
subject = 'This is an important email'
|
266
|
-
body = 'This is the all important email body.'
|
267
|
-
|
268
|
-
email_msg = MIME::Message.new
|
269
|
-
email_msg.to = {
|
270
|
-
'john@example.com' => 'John',
|
271
|
-
'paul@example.com' => nil,
|
272
|
-
'mary@example.com' => 'Mary'
|
273
|
-
}
|
274
|
-
email_msg.cc = {'Head Honcho' => 'boss@example.com'}
|
275
|
-
email_msg.from = {'jane@example.com' => nil}
|
276
|
-
email_msg.subject = subject
|
277
|
-
email_msg.body = MIME::TextMedia.new(body)
|
278
|
-
|
279
|
-
msg = email_msg.to_s
|
280
|
-
|
281
|
-
assert_equal_num_headers 9, msg
|
282
|
-
assert_match MESSAGE_ID, msg
|
283
|
-
assert_match CONTENT_ID, msg
|
284
|
-
assert_match CTYPE_TEXT_PLAIN, msg
|
285
|
-
assert_match DATE, msg
|
286
|
-
assert_match VERSION, msg
|
287
|
-
assert_match /^Subject: #{subject}\r\n/, msg
|
288
|
-
assert_match /^From: jane@example.com\r\n/, msg
|
289
|
-
assert_match /^To: .+, .+, .+\r\n/, msg # 3 addresses
|
290
|
-
assert_match /^To: .*John <john@example.com>.*\r\n/, msg
|
291
|
-
assert_match /^To: .*Mary <mary@example.com>.*\r\n/, msg
|
292
|
-
assert_match /^To: .*paul@example.com.*\r\n/, msg
|
293
|
-
assert_match /^Cc: boss@example.com <Head Honcho>\r\n/, msg
|
294
|
-
assert_equal_body body, msg
|
295
|
-
end
|
296
|
-
|
297
|
-
def test_content_type_detection
|
298
|
-
(o = Object.new).extend(MIME::ContentTypes)
|
299
|
-
|
300
|
-
# test using file path, relative and absolute
|
301
|
-
assert_equal 'application/pdf', o.file_type('book.pdf')
|
302
|
-
assert_equal 'video/quicktime', o.file_type('mini.mov')
|
303
|
-
assert_equal 'application/octet-stream', o.file_type('dsk.iso')
|
304
|
-
assert_equal 'audio/mpeg', o.file_type('/tmp/song.mp3')
|
305
|
-
assert_equal 'text/css', o.file_type('/tmp/main.css')
|
306
|
-
assert_equal nil, o.file_type('unknown.yyy')
|
307
|
-
|
308
|
-
# test using file object
|
309
|
-
img_type = open(sd('ruby.png')) {|f| o.file_type(f)}
|
310
|
-
assert_equal 'image/png', img_type
|
311
|
-
refute_equal 'image/jpeg', img_type
|
312
|
-
end
|
313
|
-
|
314
|
-
def test_object_instantiation_using_discrete_media_factory
|
315
|
-
app_file = sd('book.pdf')
|
316
|
-
audio_file = sd('song.mp3')
|
317
|
-
text_file = sd('data.xml')
|
318
|
-
video_file = sd('mini.mov')
|
319
|
-
image_file = sd('image.jpg')
|
320
|
-
unknown_file = sd('unknown.yyy')
|
321
|
-
|
322
|
-
dmf = MIME::DiscreteMediaFactory
|
323
|
-
|
324
|
-
# test using file path
|
325
|
-
assert_kind_of MIME::ApplicationMedia, dmf.create(app_file)
|
326
|
-
assert_kind_of MIME::AudioMedia, dmf.create(audio_file)
|
327
|
-
assert_kind_of MIME::TextMedia, dmf.create(text_file)
|
328
|
-
assert_kind_of MIME::VideoMedia, dmf.create(video_file)
|
329
|
-
assert_kind_of MIME::ImageMedia, dmf.create(image_file)
|
330
|
-
|
331
|
-
# test using file object
|
332
|
-
open(image_file) do |image_file_obj|
|
333
|
-
assert_kind_of MIME::ImageMedia, dmf.create(image_file_obj)
|
334
|
-
end
|
335
|
-
open(text_file) do |text_file_obj|
|
336
|
-
assert_kind_of MIME::TextMedia, dmf.create(text_file_obj)
|
337
|
-
end
|
338
|
-
|
339
|
-
# raise for unknown file path and File object
|
340
|
-
assert_raises(MIME::UnknownContentError) {dmf.create(unknown_file)}
|
341
|
-
open(unknown_file) do |unknown_file_obj|
|
342
|
-
assert_raises(MIME::UnknownContentError) {dmf.create(unknown_file_obj)}
|
343
|
-
end
|
344
|
-
end
|
345
|
-
|
346
|
-
def test_discrete_media_factory_creates_path_singleton_method
|
347
|
-
pdf_file_path = sd('book.pdf')
|
348
|
-
|
349
|
-
media_obj = MIME::DiscreteMediaFactory.create(pdf_file_path)
|
350
|
-
assert_equal pdf_file_path, media_obj.path
|
351
|
-
|
352
|
-
open(pdf_file_path) do |pdf_file_obj|
|
353
|
-
media_obj = MIME::DiscreteMediaFactory.create(pdf_file_obj)
|
354
|
-
assert_equal pdf_file_path, media_obj.path
|
355
|
-
end
|
356
|
-
end
|
357
|
-
|
358
|
-
# rm multipart_alternative.msg
|
359
|
-
def test_multipart_alternative_message_construction
|
360
|
-
txt_data = "*Header*\nmessage"
|
361
|
-
htm_data = "<html><body><h1>Header</h1><p>message</p></body></html>"
|
362
|
-
txt_msg = MIME::TextMedia.new(txt_data)
|
363
|
-
htm_msg = MIME::TextMedia.new(htm_data)
|
364
|
-
|
365
|
-
txt_msg.content_type = (txt_type = 'text/enhanced; charset=us-ascii')
|
366
|
-
htm_msg.content_type = (htm_type = 'text/html; charset=iso-8859-1')
|
367
|
-
|
368
|
-
alt_msg = MIME::MultipartMedia::Alternative.new
|
369
|
-
alt_msg.add_entity htm_msg
|
370
|
-
alt_msg.add_entity txt_msg
|
371
|
-
msg = alt_msg.to_s
|
372
|
-
|
373
|
-
parts = msg.split(BOUNDARY)
|
374
|
-
assert_equal 4, parts.size, 'main header, 2 entities, last boundary'
|
375
|
-
assert_equal '--', parts.pop, 'remnant of last boundary marker'
|
376
|
-
|
377
|
-
# main header
|
378
|
-
assert_match CONTENT_ID, parts[0]
|
379
|
-
assert_match CTYPE_MPART_ALT, parts[0]
|
380
|
-
assert_equal_num_headers 2, parts[0]
|
381
|
-
assert_equal_body '', parts[0]
|
382
|
-
|
383
|
-
# text entity
|
384
|
-
assert_match CONTENT_ID, parts[1]
|
385
|
-
assert_match /^Content-Type: #{txt_type}\r\n/, parts[1]
|
386
|
-
assert_equal_num_headers 2, parts[1]
|
387
|
-
assert_equal_body txt_data, parts[1]
|
388
|
-
|
389
|
-
# html entity
|
390
|
-
assert_match CONTENT_ID, parts[2]
|
391
|
-
assert_match /^Content-Type: #{htm_type}\r\n/, parts[2]
|
392
|
-
assert_equal_num_headers 2, parts[2]
|
393
|
-
assert_equal_body htm_data, parts[2]
|
394
|
-
end
|
395
|
-
|
396
|
-
# rm multipart_mixed_inline_and_attachment.msg
|
397
|
-
def test_multipart_mixed_with_inline_and_attachment
|
398
|
-
mixed_msg = MIME::MultipartMedia::Mixed.new
|
399
|
-
|
400
|
-
img_filename = 'image.jpg'
|
401
|
-
img_data = ''
|
402
|
-
open(sd(img_filename)) do |img_file|
|
403
|
-
img_data = img_file.read
|
404
|
-
img_msg = MIME::ImageMedia.new(img_data, 'image/jpeg')
|
405
|
-
mixed_msg.attach_entity(img_msg, 'filename' => img_file.path)
|
406
|
-
end
|
407
|
-
|
408
|
-
txt_data = 'This is plain text.'
|
409
|
-
mixed_msg.inline_entity(MIME::TextMedia.new(txt_data))
|
410
|
-
msg = mixed_msg.to_s
|
411
|
-
|
412
|
-
parts = msg.split(BOUNDARY)
|
413
|
-
assert_equal 4, parts.size, 'main header, 2 entities, last boundary'
|
414
|
-
assert_equal '--', parts.pop, 'remnant of last boundary marker'
|
415
|
-
|
416
|
-
# main header
|
417
|
-
assert_match CONTENT_ID, parts[0]
|
418
|
-
assert_match CTYPE_MPART_MIXED, parts[0]
|
419
|
-
assert_equal_num_headers 2, parts[0]
|
420
|
-
assert_equal_body '', parts[0]
|
421
|
-
|
422
|
-
# text entity
|
423
|
-
assert_match CONTENT_ID, parts[1]
|
424
|
-
assert_match CTYPE_TEXT_PLAIN, parts[1]
|
425
|
-
assert_match /^Content-Disposition: inline\r\n/, parts[1]
|
426
|
-
assert_equal_num_headers 3, parts[1]
|
427
|
-
assert_equal_body txt_data, parts[1]
|
428
|
-
|
429
|
-
# image entity
|
430
|
-
assert_match CONTENT_ID, parts[2]
|
431
|
-
assert_match CTYPE_IMAGE_JPEG, parts[2]
|
432
|
-
assert_match /^Content-Disposition: attachment; filename="#{img_filename}"\r\n/, parts[2]
|
433
|
-
assert_equal_num_headers 3, parts[2]
|
434
|
-
assert_equal_body img_data, parts[2]
|
435
|
-
end
|
436
|
-
|
437
|
-
# rm multipart_mixed_inline_and_attachment2.msg
|
438
|
-
def test_multipart_mixed_message_construction_using_media_factory
|
439
|
-
img1 = sd(img1_filename = 'image.jpg')
|
440
|
-
img2 = sd(img2_filename = 'ruby.png')
|
441
|
-
txt = sd(txt_filename = 'data.htm')
|
442
|
-
bot_img = MIME::DiscreteMediaFactory.create(img1)
|
443
|
-
top_img = MIME::DiscreteMediaFactory.create(img2)
|
444
|
-
top_txt = MIME::DiscreteMediaFactory.create(txt)
|
445
|
-
|
446
|
-
mixed_msg = MIME::MultipartMedia::Mixed.new
|
447
|
-
mixed_msg.attach_entity(bot_img)
|
448
|
-
mixed_msg.attach_entity(top_img)
|
449
|
-
mixed_msg.inline_entity(top_txt)
|
450
|
-
msg = mixed_msg.to_s
|
451
|
-
|
452
|
-
parts = msg.split(BOUNDARY)
|
453
|
-
assert_equal 5, parts.size, 'main header, 2 entities, last boundary'
|
454
|
-
assert_equal '--', parts.pop, 'remnant of last boundary marker'
|
455
|
-
|
456
|
-
# main header
|
457
|
-
assert_match CONTENT_ID, parts[0]
|
458
|
-
assert_match CTYPE_MPART_MIXED, parts[0]
|
459
|
-
assert_equal_num_headers 2, parts[0]
|
460
|
-
assert_equal_body '', parts[0]
|
461
|
-
|
462
|
-
# html entity
|
463
|
-
assert_match CONTENT_ID, parts[1]
|
464
|
-
assert_match CTYPE_TEXT_HTML, parts[1]
|
465
|
-
assert_match /^Content-Disposition: inline; filename="#{txt_filename}"\r\n/, parts[1]
|
466
|
-
assert_equal_num_headers 3, parts[1]
|
467
|
-
assert_equal_body top_txt.send(:body), parts[1]
|
468
|
-
|
469
|
-
# png image entity
|
470
|
-
assert_match CONTENT_ID, parts[2]
|
471
|
-
assert_match CTYPE_IMAGE_PNG, parts[2]
|
472
|
-
assert_match /^Content-Disposition: attachment; filename="#{img2_filename}"\r\n/, parts[2]
|
473
|
-
assert_equal_num_headers 3, parts[2]
|
474
|
-
assert_equal_body top_img.send(:body), parts[2]
|
475
|
-
|
476
|
-
# jpg image entity
|
477
|
-
assert_match CONTENT_ID, parts[3]
|
478
|
-
assert_match CTYPE_IMAGE_JPEG, parts[3]
|
479
|
-
assert_match /^Content-Disposition: attachment; filename="#{img1_filename}"\r\n/, parts[3]
|
480
|
-
assert_equal_num_headers 3, parts[3]
|
481
|
-
assert_equal_body bot_img.send(:body), parts[3]
|
482
|
-
end
|
483
|
-
|
484
|
-
def test_multipart_form_data_with_mixed_entity
|
485
|
-
txt = MIME::TextMedia.new('Joe Blow')
|
486
|
-
img1 = MIME::DiscreteMediaFactory.create(sd('image.jpg'))
|
487
|
-
img2 = MIME::DiscreteMediaFactory.create(sd('ruby.png'))
|
488
|
-
|
489
|
-
mixed_msg = MIME::MultipartMedia::Mixed.new
|
490
|
-
mixed_msg.attach_entity(img2)
|
491
|
-
mixed_msg.attach_entity(img1)
|
492
|
-
|
493
|
-
form = MIME::MultipartMedia::FormData.new
|
494
|
-
form.add_entity(mixed_msg, 'pics')
|
495
|
-
form.add_entity(txt, 'field1')
|
496
|
-
|
497
|
-
# similar to example 6 in RFC1867
|
498
|
-
expected = IO.read(sd('multipart_form_data_mixed.msg'))
|
499
|
-
|
500
|
-
assert_equal_mime_message expected, form.to_s
|
501
|
-
|
502
|
-
#IO.write('/tmp/mime.out', msg)
|
503
|
-
end
|
504
|
-
|
505
|
-
# def test_multipart_related_html_message_with_embedded_image
|
506
|
-
# img = DiscreteMediaFactory.create(sd('/ruby.png'))
|
507
|
-
# img.content_transfer_encoding = 'binary'
|
508
|
-
#
|
509
|
-
# html_msg = TextMedia.new(<<-html, 'text/html; charset=iso-8859-1')
|
510
|
-
# <html>
|
511
|
-
# <body>
|
512
|
-
# <h1>HTML multipart/related message</h1>
|
513
|
-
# <p>txt before pix</p>
|
514
|
-
# <img alt="cool ruby" src="cid:#{img.content_id}"/>
|
515
|
-
# <p>txt after pix</p>
|
516
|
-
# </body>
|
517
|
-
# </html>
|
518
|
-
# html
|
519
|
-
# html_msg.content_transfer_encoding = '7bit'
|
520
|
-
#
|
521
|
-
# related_msg = MultipartMedia::Related.new
|
522
|
-
# related_msg.inline_entity(img)
|
523
|
-
# related_msg.add_entity(html_msg)
|
524
|
-
#
|
525
|
-
# expected = IO.read(sd('/multipart_related.msg'))
|
526
|
-
#
|
527
|
-
# assert_equal_mime_message expected, related_msg.to_s
|
528
|
-
# end
|
529
|
-
#
|
530
|
-
# def test_multipart_alternative_with_related_html_entity
|
531
|
-
# img = DiscreteMediaFactory.create(sd('/ruby.png'))
|
532
|
-
# img.content_transfer_encoding = 'binary'
|
533
|
-
#
|
534
|
-
# html_msg = TextMedia.new(<<-html, 'text/html; charset=iso-8859-1')
|
535
|
-
# <html>
|
536
|
-
# <body>
|
537
|
-
# <h1>HTML multipart/alternative message</h1>
|
538
|
-
# <p>txt before pix</p>
|
539
|
-
# <img alt="cool ruby" src="cid:#{img.content_id}"/>
|
540
|
-
# <p>txt after pix</p>
|
541
|
-
# </body>
|
542
|
-
# </html>
|
543
|
-
# html
|
544
|
-
# html_msg.content_transfer_encoding = '7bit'
|
545
|
-
#
|
546
|
-
# text_msg = TextMedia.new(<<-text)
|
547
|
-
# *HTML multipart/alternative message*
|
548
|
-
# txt before pix
|
549
|
-
# <cool ruby image>
|
550
|
-
# txt after pix
|
551
|
-
# text
|
552
|
-
# text_msg.content_transfer_encoding = '7bit'
|
553
|
-
#
|
554
|
-
# related_msg = MultipartMedia::Related.new
|
555
|
-
# related_msg.inline_entity(img)
|
556
|
-
# related_msg.add_entity(html_msg)
|
557
|
-
#
|
558
|
-
# alt_msg = MultipartMedia::Alternative.new
|
559
|
-
# alt_msg.add_entity(related_msg)
|
560
|
-
# alt_msg.add_entity(text_msg)
|
561
|
-
#
|
562
|
-
# expected = IO.read(sd('/multipart_alternative_related.msg'))
|
563
|
-
#
|
564
|
-
# assert_equal_mime_message expected, alt_msg.to_s
|
565
|
-
# end
|
566
|
-
|
567
|
-
|
568
|
-
private
|
569
|
-
|
570
|
-
#
|
571
|
-
# Test the equality of the normalized +expected+ and +actual+ MIME messages.
|
572
|
-
#
|
573
|
-
def assert_equal_mime_message expected, actual
|
574
|
-
assert_equal normalize_message(expected), normalize_message(actual)
|
575
|
-
end
|
576
|
-
|
577
|
-
#
|
578
|
-
# Make messages comparable by removing *-ID header values, library version
|
579
|
-
# comment in MIME-Version header, Date header value, multipart/related
|
580
|
-
# content IDs, and boundaries.
|
581
|
-
#
|
582
|
-
def normalize_message message
|
583
|
-
# these are very delicate REs that are inter-dependent, be careful
|
584
|
-
match_id_headers = /-ID: <[^>]+>\r\n/
|
585
|
-
match_boundaries = /Boundary_\d+\.\d+/
|
586
|
-
match_lib_version = / \(Ruby MIME v\d\.\d\)/
|
587
|
-
match_date_header = /^Date: .*\d{4}\r\n/
|
588
|
-
match_related_cid = /cid:\d+\.\d+/
|
589
|
-
|
590
|
-
message.
|
591
|
-
gsub(match_related_cid, "cid").
|
592
|
-
gsub(match_id_headers, "-ID:\r\n").
|
593
|
-
gsub(match_boundaries, "Boundary_").
|
594
|
-
sub(match_date_header, "Date:\r\n").
|
595
|
-
sub(match_lib_version, " (Ruby MIME v0.0)")
|
596
|
-
end
|
597
|
-
|
598
|
-
def assert_equal_num_headers num, msg
|
599
|
-
assert_equal num, msg.split(HDR_BDY_SEP).first.split(CRLF).count
|
600
|
-
end
|
601
|
-
|
602
|
-
def assert_equal_body expected_body, msg
|
603
|
-
# FIXME the next line should be a fix
|
604
|
-
headers, actual_body = msg.split(HDR_BDY_SEP)
|
605
|
-
assert_equal expected_body, actual_body.to_s.chomp
|
606
|
-
#assert_equal body, msg.split("\r\n").last
|
607
|
-
end
|
608
|
-
|
609
|
-
#
|
610
|
-
# Return the absolute path of +file+ under the test/scaffold directory.
|
611
|
-
#
|
612
|
-
def sd file
|
613
|
-
File.join(File.dirname(__FILE__), 'scaffold', file)
|
614
|
-
end
|
615
|
-
|
616
|
-
end
|