mime 0.4.1 → 0.4.2
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 +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
|