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.
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: "0.1"
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
- description:
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
- files:
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/multipart_form_data_mixed.msg
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/mime_test.rb
65
- has_rdoc: true
66
- homepage: mime.rubyforge.org
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
- requirements:
74
- - - ">="
75
- - !ruby/object:Gem::Version
76
- version: "0"
77
- version:
78
- required_rubygems_version: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: "0"
83
- version:
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
- rubyforge_project: mime
87
- rubygems_version: 1.3.0
88
+ rubyforge_project:
89
+ rubygems_version: 1.8.23
88
90
  signing_key:
89
- specification_version: 2
91
+ specification_version: 3
90
92
  summary: Multipurpose Internet Mail Extensions (MIME) Library
91
- test_files:
92
- - test/mime_test.rb
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.
@@ -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