mime 0.1 → 0.2.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.
- data/README.rdoc +303 -0
- data/Rakefile +8 -24
- data/lib/mime.rb +1 -1
- data/lib/mime/discrete_media_factory.rb +2 -3
- data/lib/mime/headers/internet.rb +15 -13
- data/lib/mime/headers/mime.rb +18 -18
- data/lib/mime/message.rb +10 -0
- data/mime.gemspec +18 -0
- data/test/scaffold/application.msg +4 -4
- data/test/scaffold/audio.msg +3 -3
- data/test/scaffold/{index.html → data.htm} +0 -0
- data/test/scaffold/image.msg +0 -0
- data/test/scaffold/multipart_alternative.msg +10 -12
- data/test/scaffold/multipart_alternative_related.msg +0 -0
- data/test/scaffold/multipart_form_data_file_and_text.msg +0 -0
- data/test/scaffold/multipart_form_data_mixed.msg +0 -0
- data/test/scaffold/multipart_form_data_text.msg +31 -26
- data/test/scaffold/multipart_mixed_inline_and_attachment.msg +0 -0
- data/test/scaffold/multipart_mixed_inline_and_attachment2.msg +0 -0
- data/test/scaffold/multipart_related.msg +0 -0
- data/test/scaffold/plain_text_email.msg +9 -7
- data/test/scaffold/text.msg +2 -2
- data/test/scaffold/video.msg +4 -4
- data/test/test_mime.rb +417 -0
- data/test/test_mime.rb-try +616 -0
- metadata +53 -51
- data/README +0 -256
- data/test/mime_test.rb +0 -386
- data/test/scaffold/multipart_form_data_file.msg +0 -0
metadata
CHANGED
@@ -1,46 +1,45 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: mime
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
|
-
authors:
|
7
|
+
authors:
|
7
8
|
- Clint Pachl
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
|
12
|
-
date: 2008-11-05 00:00:00 -07:00
|
13
|
-
default_executable:
|
12
|
+
date: 2013-12-18 00:00:00.000000000 Z
|
14
13
|
dependencies: []
|
14
|
+
description: ! 'A library for building RFC compliant Multipurpose Internet Mail Extensions
|
15
|
+
|
16
|
+
(MIME) messages. It can be used to construct standardized MIME messages for use
|
17
|
+
|
18
|
+
in client/server communications, such as Internet mail or HTTP
|
15
19
|
|
16
|
-
|
20
|
+
multipart/form-data transactions.
|
21
|
+
|
22
|
+
'
|
17
23
|
email: pachl@ecentryx.com
|
18
24
|
executables: []
|
19
|
-
|
20
25
|
extensions: []
|
21
|
-
|
22
26
|
extra_rdoc_files: []
|
23
|
-
|
24
|
-
|
25
|
-
- README
|
27
|
+
files:
|
28
|
+
- README.rdoc
|
26
29
|
- Rakefile
|
30
|
+
- mime.gemspec
|
27
31
|
- lib/mime/headers/mime.rb
|
28
32
|
- lib/mime/headers/internet.rb
|
33
|
+
- lib/mime/discrete_media_factory.rb
|
34
|
+
- lib/mime/error.rb
|
35
|
+
- lib/mime/header_container.rb
|
36
|
+
- lib/mime/parser.rb
|
29
37
|
- lib/mime/content_types.rb
|
30
38
|
- lib/mime/media_type.rb
|
31
39
|
- lib/mime/composite_media_type.rb
|
32
40
|
- lib/mime/discrete_media_type.rb
|
33
41
|
- lib/mime/message.rb
|
34
|
-
- lib/mime/discrete_media_factory.rb
|
35
|
-
- lib/mime/error.rb
|
36
|
-
- lib/mime/header_container.rb
|
37
|
-
- lib/mime/parser.rb
|
38
42
|
- lib/mime.rb
|
39
|
-
- test/scaffold
|
40
|
-
- test/scaffold/multipart_form_data_file.msg
|
41
|
-
- test/scaffold/multipart_mixed_inline_and_attachment.msg
|
42
|
-
- test/scaffold/multipart_form_data_text.msg
|
43
|
-
- test/scaffold/audio.msg
|
44
43
|
- test/scaffold/application.msg
|
45
44
|
- test/scaffold/unknown.yyy
|
46
45
|
- test/scaffold/video.msg
|
@@ -48,45 +47,48 @@ files:
|
|
48
47
|
- test/scaffold/image.jpg
|
49
48
|
- test/scaffold/book.pdf
|
50
49
|
- test/scaffold/plain_text_email.msg
|
51
|
-
- test/scaffold/multipart_alternative_related.msg
|
52
|
-
- test/scaffold/multipart_alternative.msg
|
53
|
-
- test/scaffold/ruby.png
|
54
50
|
- test/scaffold/song.mp3
|
51
|
+
- test/scaffold/ruby.png
|
52
|
+
- test/scaffold/multipart_alternative.msg
|
53
|
+
- test/scaffold/multipart_alternative_related.msg
|
55
54
|
- test/scaffold/multipart_related.msg
|
56
55
|
- test/scaffold/multipart_mixed_inline_and_attachment2.msg
|
57
|
-
- test/scaffold/multipart_form_data_file_and_text.msg
|
58
56
|
- test/scaffold/image.msg
|
59
|
-
- test/scaffold/
|
57
|
+
- test/scaffold/multipart_form_data_file_and_text.msg
|
60
58
|
- test/scaffold/data.xml
|
59
|
+
- test/scaffold/multipart_form_data_mixed.msg
|
61
60
|
- test/scaffold/text.msg
|
62
|
-
- test/scaffold/index.html
|
63
61
|
- test/scaffold/main.css
|
64
|
-
- test/
|
65
|
-
|
66
|
-
|
62
|
+
- test/scaffold/multipart_mixed_inline_and_attachment.msg
|
63
|
+
- test/scaffold/multipart_form_data_text.msg
|
64
|
+
- test/scaffold/audio.msg
|
65
|
+
- test/scaffold/data.htm
|
66
|
+
- test/test_mime.rb-try
|
67
|
+
- test/test_mime.rb
|
68
|
+
homepage: http://ecentryx.com/gems/mime
|
69
|
+
licenses:
|
70
|
+
- ISC
|
67
71
|
post_install_message:
|
68
72
|
rdoc_options: []
|
69
|
-
|
70
|
-
require_paths:
|
73
|
+
require_paths:
|
71
74
|
- lib
|
72
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ! '>='
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ! '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
84
87
|
requirements: []
|
85
|
-
|
86
|
-
|
87
|
-
rubygems_version: 1.3.0
|
88
|
+
rubyforge_project:
|
89
|
+
rubygems_version: 1.8.23
|
88
90
|
signing_key:
|
89
|
-
specification_version:
|
91
|
+
specification_version: 3
|
90
92
|
summary: Multipurpose Internet Mail Extensions (MIME) Library
|
91
|
-
test_files:
|
92
|
-
- test/
|
93
|
+
test_files:
|
94
|
+
- test/test_mime.rb
|
data/README
DELETED
@@ -1,256 +0,0 @@
|
|
1
|
-
== Multipurpose Internet Mail Extensions (MIME)
|
2
|
-
|
3
|
-
A library for building RFC compliant Multipurpose Internet Mail Extensions
|
4
|
-
(MIME) messages. It can be used to construct standardized MIME messages for use
|
5
|
-
in client/server communications, such as Internet mail or HTTP
|
6
|
-
multipart/form-data transactions.
|
7
|
-
|
8
|
-
|
9
|
-
== See
|
10
|
-
|
11
|
-
* MIME for RFCs used to implement the library (other RFCs scattered throughout)
|
12
|
-
* MIME::CompositeMediaType for a description of composite media types
|
13
|
-
* MIME::DiscreteMediaType for a description of discrete media types
|
14
|
-
* MIME::DiscreteMediaFactory for easy programming of discrete media types
|
15
|
-
|
16
|
-
|
17
|
-
== Media Type Inheritance Heirarchy
|
18
|
-
|
19
|
-
MediaType*
|
20
|
-
^
|
21
|
-
|
|
22
|
-
|--DiscreteMediaType*
|
23
|
-
| ^
|
24
|
-
| |
|
25
|
-
| |--ApplicationMedia
|
26
|
-
| |--AudioMedia
|
27
|
-
| |--ImageMedia
|
28
|
-
| |--TextMedia
|
29
|
-
| +--VideoMedia
|
30
|
-
|
|
31
|
-
+--CompositeMediaType*
|
32
|
-
^
|
33
|
-
|
|
34
|
-
|--MessageMedia**
|
35
|
-
| ^
|
36
|
-
| |
|
37
|
-
| |--ExternalBody**
|
38
|
-
| |--Partial**
|
39
|
-
| +--RFC822**
|
40
|
-
|
|
41
|
-
+--MultipartMedia*
|
42
|
-
^
|
43
|
-
|
|
44
|
-
|--Alternative
|
45
|
-
|--Digest**
|
46
|
-
|--Encrypted**
|
47
|
-
|--FormData
|
48
|
-
|--Mixed
|
49
|
-
|--Parallel**
|
50
|
-
|--Related
|
51
|
-
|--Report**
|
52
|
-
+--Signed**
|
53
|
-
|
54
|
-
* Abstract Class
|
55
|
-
** Not implemented
|
56
|
-
|
57
|
-
|
58
|
-
== MIME Message Structure
|
59
|
-
|
60
|
-
|
61
|
-
---------------------+
|
62
|
-
+----------------+ |
|
63
|
-
| RFC822 & MIME | |
|
64
|
-
| Message Headers| |
|
65
|
-
+----------------+ |
|
66
|
-
---+ |
|
67
|
-
+----------------+ | |
|
68
|
-
| MIME Headers | | |
|
69
|
-
+----------------+ |---MIME Entity |
|
70
|
-
+----------------+ | (N) |
|
71
|
-
| Body | | |---RFC822 Message
|
72
|
-
+----------------+ | |
|
73
|
-
---+ |
|
74
|
-
---+ |
|
75
|
-
+----------------+ | |
|
76
|
-
| MIME Headers | | |
|
77
|
-
+----------------+ |---MIME Entity |
|
78
|
-
+----------------+ | (N+1) |
|
79
|
-
| Body | | |
|
80
|
-
+----------------+ | |
|
81
|
-
---+ |
|
82
|
-
---------------------+
|
83
|
-
|
84
|
-
Each <em>MIME Entity</em> must be a discrete (MIME::DiscreteMediaType) or
|
85
|
-
composite (MIME::CompositeMediaType) media type. Because MIME is recursive,
|
86
|
-
composite entity bodies may contain other composite or discrete entites and so
|
87
|
-
on. However, discrete entities are non-recursive and contain only non-MIME
|
88
|
-
bodies.
|
89
|
-
|
90
|
-
|
91
|
-
== Examples
|
92
|
-
|
93
|
-
<em>The following examples imply that the MIME module is included.</em>
|
94
|
-
|
95
|
-
|
96
|
-
=== Two ways to instantiate a DiscreteMediaType object using a file path
|
97
|
-
|
98
|
-
fpath = '/tmp/data.xml'
|
99
|
-
text_media = open(fpath) {|f| TextMedia.new(f.read, 'text/xml')}
|
100
|
-
text_media = DiscreteMediaFactory.create(fpath)
|
101
|
-
|
102
|
-
|
103
|
-
=== Simple text/plain RFC822 email
|
104
|
-
|
105
|
-
msg = Message.new # creates a blank message with date and message ID headers
|
106
|
-
msg.date = (Time.now - 3600).rfc2822 # specify a different date
|
107
|
-
msg.subject = 'This is important'
|
108
|
-
msg.headers.add('X-Priority', 'high') # custom header
|
109
|
-
|
110
|
-
msg.body = TextMedia.new('hello, it is me!')
|
111
|
-
#
|
112
|
-
# The following snippets are equivalent to the previous line.
|
113
|
-
#
|
114
|
-
# msg.body = "\r\nhello, it is me!"
|
115
|
-
# msg.header.add('Content-Type', 'text/plain; charset=us-ascii')
|
116
|
-
#
|
117
|
-
# --OR--
|
118
|
-
#
|
119
|
-
# msg.body = "Content-Type: text/plain; charset=us-ascii\r\n\r\nhello, it is me!"
|
120
|
-
|
121
|
-
msg.to = {
|
122
|
-
's13xj@x.com' => nil, # no name display
|
123
|
-
'james@x.com' => 'James',
|
124
|
-
'clint@x.com' => 'Clint',
|
125
|
-
}
|
126
|
-
msg.from = {
|
127
|
-
'theboss@x.com' => 'Boss Man'
|
128
|
-
}
|
129
|
-
|
130
|
-
msg.to_s # ready to be sent via SMTP
|
131
|
-
|
132
|
-
|
133
|
-
=== Plain text multipart/mixed message with a file attachment
|
134
|
-
|
135
|
-
The multipart/mixed content type can be used to aggregate multiple unrelated
|
136
|
-
entities.
|
137
|
-
|
138
|
-
text = DiscreteMediaFactory.create('/tmp/data.txt')
|
139
|
-
image = DiscreteMediaFactory.create('/tmp/ruby.png')
|
140
|
-
|
141
|
-
mixed_msg = MultipartMedia::Mixed.new
|
142
|
-
mixed_msg.attach_entity(image)
|
143
|
-
mixed_msg.add_entity(text)
|
144
|
-
mixed_msg.to_s
|
145
|
-
|
146
|
-
|
147
|
-
=== Plain text and HTML multipart/alternative MIME message
|
148
|
-
|
149
|
-
The multipart/alternative content type allows for multiple alternatively
|
150
|
-
formatted versions of the same content. Clients are then responsible for
|
151
|
-
choosing the most suitable version for display.
|
152
|
-
|
153
|
-
text_msg = TextMedia.new(<<-text_data, 'text/plain')
|
154
|
-
*Headline*
|
155
|
-
Ruby is cool!
|
156
|
-
text_data
|
157
|
-
|
158
|
-
html_msg = TextMedia.new(<<-html_data, 'text/html')
|
159
|
-
<html>
|
160
|
-
<body>
|
161
|
-
<h1>Headline</h1>
|
162
|
-
<p>Ruby is cool!</p>
|
163
|
-
</body>
|
164
|
-
</html>
|
165
|
-
html_data
|
166
|
-
|
167
|
-
msg = MultipartMedia::Alternative.new
|
168
|
-
msg.add_entity(html_msg) # most complex representation must be added first
|
169
|
-
msg.add_entity(text_msg)
|
170
|
-
msg.to_s
|
171
|
-
|
172
|
-
|
173
|
-
=== HTML multipart/related MIME email with embedded image
|
174
|
-
|
175
|
-
Sometimes it is desirable to send a document that is made up of many separate
|
176
|
-
parts. For example, an HTML page with embedded images. The multipart/related
|
177
|
-
content type aggregates all the parts and creates the means for the root entity
|
178
|
-
to reference the other entities.
|
179
|
-
|
180
|
-
image = DiscreteMediaFactory.create('/tmp/ruby.png')
|
181
|
-
image.content_transfer_encoding = 'binary'
|
182
|
-
|
183
|
-
html_msg = TextMedia.new(<<-html_data, 'text/html; charset=iso-8859-1')
|
184
|
-
<html>
|
185
|
-
<body>
|
186
|
-
<h1>Ruby Image</h1>
|
187
|
-
<p>Check out this cool pic.</p>
|
188
|
-
<img alt="cool ruby" src="cid:#{image.content_id}"/>
|
189
|
-
<p>Wasn't it cool?</p>
|
190
|
-
</body>
|
191
|
-
</html>
|
192
|
-
html_data
|
193
|
-
html_msg.content_transfer_encoding = '7bit'
|
194
|
-
|
195
|
-
related_msg = MultipartMedia::Related.new
|
196
|
-
related_msg.inline_entity(image)
|
197
|
-
related_msg.add_entity(html_msg)
|
198
|
-
|
199
|
-
email_msg = Message.new(related_msg)
|
200
|
-
email_msg.to = {'joe@domain.com' => 'Joe Schmo'}
|
201
|
-
email_msg.from = {'john@domain.com' => 'John Doe'}
|
202
|
-
email_msg.subject = 'Ruby is cool'
|
203
|
-
email_msg.to_s
|
204
|
-
|
205
|
-
|
206
|
-
=== HTML form with file upload using multipart/form-data encoding
|
207
|
-
|
208
|
-
This example builds a representation of an HTML form that can be POSTed to an
|
209
|
-
HTTP server. It contains a single text input and a file input.
|
210
|
-
|
211
|
-
name_field = TextMedia.new('Joe Blow')
|
212
|
-
|
213
|
-
portrait_filename = '/tmp/joe_portrait.jpg'
|
214
|
-
portrait_field = open(portrait_filename) do |f|
|
215
|
-
ImageMedia.new(f.read, 'image/jpeg') # explicit content type
|
216
|
-
end
|
217
|
-
portrait_field.content_transfer_encoding = 'binary'
|
218
|
-
|
219
|
-
form_data = MultipartMedia::FormData.new
|
220
|
-
form_data.add_entity(name_field, 'name')
|
221
|
-
form_data.add_entity(portrait_field, 'portrait', portrait_filename) # explicity filename
|
222
|
-
form_data.to_s
|
223
|
-
|
224
|
-
|
225
|
-
=== HTML form with file upload using multipart/form-data encoding (DiscreteMediaFactory)
|
226
|
-
|
227
|
-
The outcome of this example is identical to the previous example. The only
|
228
|
-
semantic difference is that the MIME::DiscreteMediaFactory class is used to
|
229
|
-
automatically instantiate the MIME::MediaType object.
|
230
|
-
|
231
|
-
name_field = TextMedia.new('Joe Blow')
|
232
|
-
|
233
|
-
portrait_field = DiscreteMediaFactory.create('/tmp/joe_portrait.jpg') # no explicit content type
|
234
|
-
portrait_field.content_transfer_encoding = 'binary'
|
235
|
-
|
236
|
-
form_data = MultipartMedia::FormData.new
|
237
|
-
form_data.add_entity(name_field, 'name')
|
238
|
-
form_data.add_entity(portrait_field, 'portrait') # no explicit filename
|
239
|
-
form_data.to_s
|
240
|
-
|
241
|
-
|
242
|
-
== More Examples
|
243
|
-
|
244
|
-
For many more examples, check the test class MIMETest.
|
245
|
-
|
246
|
-
|
247
|
-
== Contact
|
248
|
-
|
249
|
-
Please email inquiries to pachl at ecentryx dot com.
|
250
|
-
|
251
|
-
[Home Page] http://mime.rubyforge.org/
|
252
|
-
[RubyForge] http://rubyforge.org/projects/mime/
|
253
|
-
|
254
|
-
== License
|
255
|
-
|
256
|
-
The entire MIME library is free to use under the terms of the Ruby license.
|
data/test/mime_test.rb
DELETED
@@ -1,386 +0,0 @@
|
|
1
|
-
require 'mime'
|
2
|
-
require 'test/unit'
|
3
|
-
|
4
|
-
class MIMETest < Test::Unit::TestCase
|
5
|
-
|
6
|
-
include MIME
|
7
|
-
|
8
|
-
def test_make_top_level_rfc2822_message
|
9
|
-
data = "\r\nmessage body"
|
10
|
-
rfc2822_msg = Message.new
|
11
|
-
rfc2822_msg.body = data
|
12
|
-
expected_msg =
|
13
|
-
"Message-ID: <993708956@989739608>\r\n"\
|
14
|
-
"Date: Wed, 24 Oct 2008 15:45:31 -0700\r\n"\
|
15
|
-
"MIME-Version: 1.0 (Ruby MIME v0.1)\r\n"\
|
16
|
-
"\r\nmessage body\r\n"
|
17
|
-
|
18
|
-
assert_equal_mime_message expected_msg, rfc2822_msg.to_s
|
19
|
-
end
|
20
|
-
|
21
|
-
def test_make_audio_message
|
22
|
-
audio = '0110000101110101011001000110100101101111'
|
23
|
-
audio_media = AudioMedia.new(audio, 'audio/midi')
|
24
|
-
audio_media.content_transfer_encoding = 'binary'
|
25
|
-
|
26
|
-
mime_msg = Message.new(audio_media).to_s
|
27
|
-
expected_mime_msg = IO.read(sd('/audio.msg'))
|
28
|
-
|
29
|
-
assert_equal_mime_message expected_mime_msg, mime_msg
|
30
|
-
end
|
31
|
-
|
32
|
-
def test_make_application_message
|
33
|
-
application = '011000100110100101101110011000010111001001111001'
|
34
|
-
application_media = ApplicationMedia.new(application)
|
35
|
-
application_media.content_transfer_encoding = 'binary'
|
36
|
-
|
37
|
-
mime_msg = Message.new(application_media).to_s
|
38
|
-
expected_mime_msg = IO.read(sd('/application.msg'))
|
39
|
-
|
40
|
-
assert_equal_mime_message expected_mime_msg, mime_msg
|
41
|
-
end
|
42
|
-
|
43
|
-
def test_make_image_message
|
44
|
-
image = IO.read(sd('/image.jpg'))
|
45
|
-
image_media = ImageMedia.new(image)
|
46
|
-
image_media.content_type = 'image/jpeg'
|
47
|
-
image_media.content_transfer_encoding = 'binary'
|
48
|
-
|
49
|
-
mime_msg = Message.new(image_media).to_s
|
50
|
-
expected_mime_msg = IO.read(sd('/image.msg'))
|
51
|
-
|
52
|
-
assert_equal_mime_message expected_mime_msg, mime_msg
|
53
|
-
end
|
54
|
-
|
55
|
-
def test_make_text_message
|
56
|
-
text = 'a plain text message'
|
57
|
-
mime_msg = Message.new(TextMedia.new(text)).to_s
|
58
|
-
expected_mime_msg = IO.read(sd('/text.msg'))
|
59
|
-
|
60
|
-
assert_equal_mime_message expected_mime_msg, mime_msg
|
61
|
-
end
|
62
|
-
|
63
|
-
def test_make_video_message
|
64
|
-
video = '0111011001101001011001000110010101101111'
|
65
|
-
video_media = VideoMedia.new(video)
|
66
|
-
video_media.content_type = 'video/mpeg'
|
67
|
-
video_media.content_transfer_encoding = 'binary'
|
68
|
-
|
69
|
-
mime_msg = Message.new(video_media).to_s
|
70
|
-
expected_mime_msg = IO.read(sd('/video.msg'))
|
71
|
-
|
72
|
-
assert_equal_mime_message expected_mime_msg, mime_msg
|
73
|
-
end
|
74
|
-
|
75
|
-
def test_no_instantiation_of_abstract_classes
|
76
|
-
e = AbstractClassError
|
77
|
-
assert_raise(e) {MediaType.new(nil, nil)}
|
78
|
-
assert_raise(e) {DiscreteMediaType.new(nil)}
|
79
|
-
assert_raise(e) {CompositeMediaType.new(nil)}
|
80
|
-
assert_raise(e) {MultipartMedia.new(nil)}
|
81
|
-
end
|
82
|
-
|
83
|
-
def test_multipart_form_data_with_text_entities
|
84
|
-
t1 = TextMedia.new('this is t1')
|
85
|
-
t2 = TextMedia.new('this is t2', 'text/enhanced')
|
86
|
-
t3 = open(sd('/index.html')) {|f| TextMedia.new(f.read, 'text/html')}
|
87
|
-
t4 = open(sd('/data.xml')) {|f| TextMedia.new(f.read, 'text/xml')}
|
88
|
-
|
89
|
-
form_data = MultipartMedia::FormData.new
|
90
|
-
form_data.add_entity t1, 'txt1'
|
91
|
-
form_data.add_entity t2, 'txt2'
|
92
|
-
form_data.add_entity t3, 'txt3'
|
93
|
-
form_data.add_entity t3, 'txt3'
|
94
|
-
|
95
|
-
expected = IO.read(sd('/multipart_form_data_text.msg'))
|
96
|
-
|
97
|
-
assert_equal_mime_message expected, form_data.to_s
|
98
|
-
end
|
99
|
-
|
100
|
-
def test_multipart_form_data_with_file_entities
|
101
|
-
img1 = sd('/image.jpg')
|
102
|
-
img2 = sd('/ruby.png')
|
103
|
-
f1 = open(img1) {|f| ImageMedia.new(f.read, 'image/jpeg')}
|
104
|
-
f2 = open(img2) {|f| ImageMedia.new(f.read, 'image/png')}
|
105
|
-
|
106
|
-
f1.content_transfer_encoding = 'binary'
|
107
|
-
f2.content_transfer_encoding = 'binary'
|
108
|
-
|
109
|
-
form_data = MultipartMedia::FormData.new
|
110
|
-
form_data.add_entity f1, 'file1', img1
|
111
|
-
form_data.add_entity f2, 'file2', img2
|
112
|
-
|
113
|
-
expected = IO.read(sd('/multipart_form_data_file.msg'))
|
114
|
-
|
115
|
-
assert_equal_mime_message expected, form_data.to_s
|
116
|
-
end
|
117
|
-
|
118
|
-
def test_multipart_form_data_with_file_and_text_entities
|
119
|
-
t1 = TextMedia.new('this is t1')
|
120
|
-
t2 = TextMedia.new('this is t2', 'text/enhanced')
|
121
|
-
|
122
|
-
img1 = sd('/image.jpg')
|
123
|
-
f1 = open(img1) {|f| ImageMedia.new(f.read, 'image/jpeg')}
|
124
|
-
f1.content_transfer_encoding = 'binary'
|
125
|
-
|
126
|
-
form_data = MultipartMedia::FormData.new
|
127
|
-
form_data.add_entity t1, 'txt1'
|
128
|
-
form_data.add_entity t2, 'txt2'
|
129
|
-
form_data.add_entity f1, 'img1', img1
|
130
|
-
|
131
|
-
expected = IO.read(sd('/multipart_form_data_file_and_text.msg'))
|
132
|
-
|
133
|
-
assert_equal_mime_message expected, form_data.to_s
|
134
|
-
end
|
135
|
-
|
136
|
-
def test_construction_of_plain_text_email_message
|
137
|
-
email_msg = Message.new
|
138
|
-
email_msg.to = {
|
139
|
-
'person1@domain.com' => 'Harry',
|
140
|
-
'person2@domain.com' => nil,
|
141
|
-
'person3@domain.com' => 'Mary'
|
142
|
-
}
|
143
|
-
email_msg.cc = {'Head Honcho' => 'bossman@domain.com'}
|
144
|
-
email_msg.from = 'person4@domain.com'
|
145
|
-
email_msg.subject = 'This is an important email'
|
146
|
-
#TODO - what do we do about this body thing???????? raw_body= and body=
|
147
|
-
email_msg.body = "\r\nThis is the all important email body"
|
148
|
-
#email_msg.body = TextMedia.new("This is the all important email body")
|
149
|
-
|
150
|
-
expected = IO.read(sd('/plain_text_email.msg'))
|
151
|
-
|
152
|
-
assert_equal_mime_message expected, email_msg.to_s
|
153
|
-
end
|
154
|
-
|
155
|
-
def test_content_type_detection
|
156
|
-
(o = Object.new).extend(ContentTypes)
|
157
|
-
|
158
|
-
# test using file path
|
159
|
-
assert_equal 'application/pdf', o.file_type('book.pdf')
|
160
|
-
assert_equal 'audio/mpeg', o.file_type('/tmp/song.mp3')
|
161
|
-
assert_equal 'text/css', o.file_type('/tmp/main.css')
|
162
|
-
assert_equal 'video/quicktime', o.file_type('mini.mov')
|
163
|
-
assert_equal 'application/octet-stream', o.file_type('dsk.iso')
|
164
|
-
assert_equal nil, o.file_type('file.yyy')
|
165
|
-
|
166
|
-
# test using file object
|
167
|
-
img_file = sd('/ruby.png')
|
168
|
-
img_type = open(img_file) {|f| o.file_type(f)}
|
169
|
-
assert_equal 'image/png', img_type
|
170
|
-
assert_not_equal 'image/jpeg', img_type
|
171
|
-
end
|
172
|
-
|
173
|
-
def test_object_instantiation_using_discrete_media_factory
|
174
|
-
application_file = sd('/book.pdf')
|
175
|
-
audio_file = sd('/song.mp3')
|
176
|
-
text_file = sd('/data.xml')
|
177
|
-
video_file = sd('/mini.mov')
|
178
|
-
image_file = sd('/image.jpg')
|
179
|
-
unknown_file = sd('/unknown.yyy')
|
180
|
-
|
181
|
-
dmf = DiscreteMediaFactory
|
182
|
-
|
183
|
-
# test using file path
|
184
|
-
assert_kind_of ApplicationMedia, dmf.create(application_file)
|
185
|
-
assert_kind_of AudioMedia, dmf.create(audio_file)
|
186
|
-
assert_kind_of TextMedia, dmf.create(text_file)
|
187
|
-
assert_kind_of VideoMedia, dmf.create(video_file)
|
188
|
-
|
189
|
-
# test using file object
|
190
|
-
open(image_file) do |image_file_obj|
|
191
|
-
assert_kind_of ImageMedia, dmf.create(image_file_obj)
|
192
|
-
end
|
193
|
-
open(text_file) do |text_file_obj|
|
194
|
-
assert_kind_of TextMedia, dmf.create(text_file_obj)
|
195
|
-
end
|
196
|
-
|
197
|
-
# raise for unknown file path and File object
|
198
|
-
assert_raises(UnknownContentError) {dmf.create(unknown_file)}
|
199
|
-
open(unknown_file) do |unknown_file_obj|
|
200
|
-
assert_raises(UnknownContentError) {dmf.create(unknown_file_obj)}
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
def test_discrete_media_factory_creates_path_singleton_method
|
205
|
-
pdf_file_path = sd('/book.pdf')
|
206
|
-
|
207
|
-
media_obj = DiscreteMediaFactory.create(pdf_file_path)
|
208
|
-
assert_equal pdf_file_path, media_obj.path
|
209
|
-
|
210
|
-
open(pdf_file_path) do |pdf_file_obj|
|
211
|
-
media_obj = DiscreteMediaFactory.create(pdf_file_obj)
|
212
|
-
end
|
213
|
-
assert_equal pdf_file_path, media_obj.path
|
214
|
-
end
|
215
|
-
|
216
|
-
def test_multipart_alternative_message_construction
|
217
|
-
txt_data = "*Header*\nmessage\n"
|
218
|
-
htm_data = "<html><body><h1>Header</h1><p>message</p></body></html>\n"
|
219
|
-
txt_msg = TextMedia.new(txt_data)
|
220
|
-
htm_msg = TextMedia.new(htm_data)
|
221
|
-
|
222
|
-
txt_msg.content_type = 'text/plain; charset=us-ascii'
|
223
|
-
htm_msg.content_type = 'text/html; charset=iso-8859-1'
|
224
|
-
|
225
|
-
alt_msg = MultipartMedia::Alternative.new
|
226
|
-
alt_msg.add_entity htm_msg
|
227
|
-
alt_msg.add_entity txt_msg
|
228
|
-
|
229
|
-
expected = IO.read(sd('/multipart_alternative.msg'))
|
230
|
-
|
231
|
-
assert_equal_mime_message expected, alt_msg.to_s
|
232
|
-
end
|
233
|
-
|
234
|
-
def test_multipart_mixed_with_inline_and_attachment
|
235
|
-
mixed_msg = MultipartMedia::Mixed.new
|
236
|
-
|
237
|
-
open(sd('/image.jpg')) do |img_file|
|
238
|
-
img_msg = ImageMedia.new(img_file.read, 'image/jpeg')
|
239
|
-
mixed_msg.attach_entity(img_msg, 'filename' => img_file.path)
|
240
|
-
end
|
241
|
-
mixed_msg.inline_entity(TextMedia.new('This is plain text'))
|
242
|
-
|
243
|
-
expected = IO.read(sd('/multipart_mixed_inline_and_attachment.msg'))
|
244
|
-
|
245
|
-
assert_equal_mime_message expected, mixed_msg.to_s
|
246
|
-
end
|
247
|
-
|
248
|
-
def test_multipart_mixed_message_construction_using_media_factory
|
249
|
-
img1 = sd('/image.jpg')
|
250
|
-
img2 = sd('/ruby.png')
|
251
|
-
txt = sd('/index.html')
|
252
|
-
bot_img = DiscreteMediaFactory.create(img1)
|
253
|
-
top_img = DiscreteMediaFactory.create(img2)
|
254
|
-
top_txt = DiscreteMediaFactory.create(txt)
|
255
|
-
|
256
|
-
mixed_msg = MultipartMedia::Mixed.new
|
257
|
-
mixed_msg.attach_entity(bot_img)
|
258
|
-
mixed_msg.attach_entity(top_img)
|
259
|
-
mixed_msg.inline_entity(top_txt)
|
260
|
-
|
261
|
-
expected = IO.read(sd('/multipart_mixed_inline_and_attachment2.msg'))
|
262
|
-
|
263
|
-
assert_equal_mime_message expected, mixed_msg.to_s
|
264
|
-
end
|
265
|
-
|
266
|
-
def test_multipart_form_data_with_mixed_entity
|
267
|
-
txt = TextMedia.new('Joe Blow')
|
268
|
-
img1 = DiscreteMediaFactory.create(sd('/image.jpg'))
|
269
|
-
img2 = DiscreteMediaFactory.create(sd('/ruby.png'))
|
270
|
-
|
271
|
-
mixed_msg = MultipartMedia::Mixed.new
|
272
|
-
mixed_msg.attach_entity(img2)
|
273
|
-
mixed_msg.attach_entity(img1)
|
274
|
-
|
275
|
-
form = MultipartMedia::FormData.new
|
276
|
-
form.add_entity(mixed_msg, 'pics')
|
277
|
-
form.add_entity(txt, 'field1')
|
278
|
-
|
279
|
-
# similar to example 6 in RFC1867
|
280
|
-
expected = IO.read(sd('/multipart_form_data_mixed.msg'))
|
281
|
-
|
282
|
-
assert_equal_mime_message expected, form.to_s
|
283
|
-
end
|
284
|
-
|
285
|
-
def test_multipart_related_html_message_with_embedded_image
|
286
|
-
img = DiscreteMediaFactory.create(sd('/ruby.png'))
|
287
|
-
img.content_transfer_encoding = 'binary'
|
288
|
-
|
289
|
-
html_msg = TextMedia.new(<<-html, 'text/html; charset=iso-8859-1')
|
290
|
-
<html>
|
291
|
-
<body>
|
292
|
-
<h1>HTML multipart/related message</h1>
|
293
|
-
<p>txt before pix</p>
|
294
|
-
<img alt="cool ruby" src="cid:#{img.content_id}"/>
|
295
|
-
<p>txt after pix</p>
|
296
|
-
</body>
|
297
|
-
</html>
|
298
|
-
html
|
299
|
-
html_msg.content_transfer_encoding = '7bit'
|
300
|
-
|
301
|
-
related_msg = MultipartMedia::Related.new
|
302
|
-
related_msg.inline_entity(img)
|
303
|
-
related_msg.add_entity(html_msg)
|
304
|
-
|
305
|
-
expected = IO.read(sd('/multipart_related.msg'))
|
306
|
-
|
307
|
-
assert_equal_mime_message expected, related_msg.to_s
|
308
|
-
end
|
309
|
-
|
310
|
-
def test_multipart_alternative_with_related_html_entity
|
311
|
-
img = DiscreteMediaFactory.create(sd('/ruby.png'))
|
312
|
-
img.content_transfer_encoding = 'binary'
|
313
|
-
|
314
|
-
html_msg = TextMedia.new(<<-html, 'text/html; charset=iso-8859-1')
|
315
|
-
<html>
|
316
|
-
<body>
|
317
|
-
<h1>HTML multipart/alternative message</h1>
|
318
|
-
<p>txt before pix</p>
|
319
|
-
<img alt="cool ruby" src="cid:#{img.content_id}"/>
|
320
|
-
<p>txt after pix</p>
|
321
|
-
</body>
|
322
|
-
</html>
|
323
|
-
html
|
324
|
-
html_msg.content_transfer_encoding = '7bit'
|
325
|
-
|
326
|
-
text_msg = TextMedia.new(<<-text)
|
327
|
-
*HTML multipart/alternative message*
|
328
|
-
txt before pix
|
329
|
-
<cool ruby image>
|
330
|
-
txt after pix
|
331
|
-
text
|
332
|
-
text_msg.content_transfer_encoding = '7bit'
|
333
|
-
|
334
|
-
related_msg = MultipartMedia::Related.new
|
335
|
-
related_msg.inline_entity(img)
|
336
|
-
related_msg.add_entity(html_msg)
|
337
|
-
|
338
|
-
alt_msg = MultipartMedia::Alternative.new
|
339
|
-
alt_msg.add_entity(related_msg)
|
340
|
-
alt_msg.add_entity(text_msg)
|
341
|
-
|
342
|
-
expected = IO.read(sd('/multipart_alternative_related.msg'))
|
343
|
-
|
344
|
-
assert_equal_mime_message expected, alt_msg.to_s
|
345
|
-
end
|
346
|
-
|
347
|
-
|
348
|
-
private
|
349
|
-
|
350
|
-
#
|
351
|
-
# Test the equality of the normalized +expected+ and +actual+ MIME messages.
|
352
|
-
#
|
353
|
-
def assert_equal_mime_message expected, actual
|
354
|
-
assert_equal normalize_message(expected), normalize_message(actual)
|
355
|
-
end
|
356
|
-
|
357
|
-
#
|
358
|
-
# Make messages comparable by removing *-ID header values, library version
|
359
|
-
# comment in MIME-Version header, Date header value, multipart/related
|
360
|
-
# content IDs, and boundaries.
|
361
|
-
#
|
362
|
-
def normalize_message message
|
363
|
-
# these are very delicate REs that are inter-dependent, be careful
|
364
|
-
match_id_headers = /-ID: <[^>]+>\r\n/
|
365
|
-
match_boundaries = /Boundary_\d+\.\d+/
|
366
|
-
match_lib_version = / \(Ruby MIME v\d\.\d\)/
|
367
|
-
match_date_header = /^Date: .*\d{4}\r\n/
|
368
|
-
match_related_cid = /cid:\d+\.\d+/
|
369
|
-
|
370
|
-
message.
|
371
|
-
gsub(match_related_cid, "cid").
|
372
|
-
gsub(match_id_headers, "-ID:\r\n").
|
373
|
-
gsub(match_boundaries, "Boundary_").
|
374
|
-
sub(match_date_header, "Date:\r\n").
|
375
|
-
sub(match_lib_version, " (Ruby MIME v0.0)")
|
376
|
-
end
|
377
|
-
|
378
|
-
#
|
379
|
-
# Return the absolute path of +file+ under the test/scaffold directory.
|
380
|
-
#
|
381
|
-
def sd file
|
382
|
-
@scaffold_dir ||= File.join(File.dirname(__FILE__), 'scaffold')
|
383
|
-
@scaffold_dir + file
|
384
|
-
end
|
385
|
-
|
386
|
-
end
|