mime 0.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|