mime 0.3.0 → 0.4.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.
Files changed (35) hide show
  1. data/README.rdoc +192 -140
  2. data/lib/mime/composite_media.rb +230 -0
  3. data/lib/mime/content_formats/text_flowed.rb +6 -6
  4. data/lib/mime/discrete_media.rb +73 -0
  5. data/lib/mime/discrete_media_factory.rb +19 -13
  6. data/lib/mime/header.rb +48 -0
  7. data/lib/mime/headers/internet.rb +124 -27
  8. data/lib/mime/headers/mime.rb +38 -27
  9. data/lib/mime/mail.rb +51 -0
  10. data/lib/mime/media.rb +30 -0
  11. data/lib/mime/parser.rb +1 -1
  12. data/lib/mime.rb +27 -9
  13. data/test/scaffold/application.msg +2 -5
  14. data/test/scaffold/audio.msg +2 -5
  15. data/test/scaffold/image.msg +0 -0
  16. data/test/scaffold/multipart_alternative.msg +7 -7
  17. data/test/scaffold/multipart_alternative_related.msg +0 -0
  18. data/test/scaffold/multipart_form_data_file_and_text.msg +0 -0
  19. data/test/scaffold/multipart_form_data_mixed.msg +0 -0
  20. data/test/scaffold/multipart_form_data_text.msg +12 -12
  21. data/test/scaffold/multipart_mixed_inline_and_attachment.msg +0 -0
  22. data/test/scaffold/multipart_mixed_inline_and_attachment2.msg +0 -0
  23. data/test/scaffold/multipart_related.msg +0 -0
  24. data/test/scaffold/rfc822_composite.msg +0 -0
  25. data/test/scaffold/{plain_text_email.msg → rfc822_discrete.msg} +5 -5
  26. data/test/scaffold/text.msg +2 -5
  27. data/test/scaffold/video.msg +2 -5
  28. data/test/test_mime.rb +323 -150
  29. data/test/test_text_flowed.rb +1 -1
  30. metadata +13 -12
  31. data/lib/mime/composite_media_type.rb +0 -169
  32. data/lib/mime/discrete_media_type.rb +0 -78
  33. data/lib/mime/header_container.rb +0 -32
  34. data/lib/mime/media_type.rb +0 -51
  35. data/lib/mime/message.rb +0 -61
@@ -8,19 +8,19 @@ module MIME
8
8
 
9
9
  attr_reader(
10
10
  :mime_version,
11
- :content_description,
12
- :content_disposition,
13
- :content_id,
14
- :content_transfer_encoding,
15
- :content_type
11
+ :description,
12
+ :disposition,
13
+ :id,
14
+ :transfer_encoding,
15
+ :type
16
16
  )
17
17
 
18
18
  #
19
19
  # Describes the content, which can be useful for non-MIME clients.
20
20
  #
21
- def content_description= description
22
- @content_description = description
23
- headers.add('Content-Description', description)
21
+ def description= description
22
+ @description = description
23
+ headers.set('Content-Description', description)
24
24
  end
25
25
 
26
26
  #
@@ -30,18 +30,18 @@ module MIME
30
30
  #
31
31
  # RFC 2183 Communicating Presentation Information in Internet Messages.
32
32
  #
33
- def content_disposition= disposition
34
- @content_disposition = disposition
35
- headers.add('Content-Disposition', disposition)
33
+ def disposition= disposition
34
+ @disposition = disposition
35
+ headers.set('Content-Disposition', disposition)
36
36
  end
37
37
 
38
38
  #
39
39
  # Globally unique ID that identifies a top-level message or message
40
40
  # entity. Content IDs can be used for referencing or caching purposes.
41
41
  #
42
- def content_id= id
43
- @content_id = id
44
- headers.add('Content-ID', "<#{id}>")
42
+ def id= id
43
+ @id = id
44
+ headers.set('Content-ID', "<#{id}>")
45
45
  end
46
46
 
47
47
  #
@@ -54,9 +54,9 @@ module MIME
54
54
  # * quoted-printable
55
55
  # * base64
56
56
  #
57
- def content_transfer_encoding= encoding
58
- @content_transfer_encoding = encoding
59
- headers.add('Content-Transfer-Encoding', encoding)
57
+ def transfer_encoding= encoding
58
+ @transfer_encoding = encoding
59
+ headers.set('Content-Transfer-Encoding', encoding)
60
60
  end
61
61
 
62
62
  #
@@ -64,7 +64,7 @@ module MIME
64
64
  #
65
65
  def mime_version= version
66
66
  @mime_version = version
67
- headers.add('MIME-Version', version)
67
+ headers.set('MIME-Version', version)
68
68
  end
69
69
 
70
70
  protected
@@ -80,9 +80,9 @@ module MIME
80
80
  # * text/plain
81
81
  # * video/mpeg
82
82
  #
83
- def content_type= type
84
- @content_type = type
85
- headers.add('Content-Type', type)
83
+ def type= type
84
+ @type = type
85
+ headers.set('Content-Type', type)
86
86
  end
87
87
 
88
88
  #
@@ -97,20 +97,31 @@ module MIME
97
97
  #
98
98
  # The values for the *-date keys may use Time::rfc2822.
99
99
  #
100
- def set_content_disposition type, params = {}
101
- disposition = type
102
-
100
+ def set_disposition type, params = {}
103
101
  if params['filename']
104
102
  params['filename'] = File.basename(params['filename'])
105
103
  elsif self.respond_to?(:path)
106
104
  params['filename'] = File.basename(self.path)
107
105
  end
106
+ self.disposition = append_field_params(type, params)
107
+ end
108
+
109
+
110
+ private
108
111
 
112
+ #
113
+ # Append parameters to header field body.
114
+ # Used for Content-Type and Content-Disposition headers.
115
+ #
116
+ def append_field_params body, params = {}
109
117
  params.each do |name, value|
110
- disposition << %Q[; #{name}="#{value}"] if value
118
+ next unless value
119
+ unless value =~ Internet::DOT_ATOM
120
+ value = '"' + value.gsub('"','\"') + '"'
121
+ end
122
+ body << "; #{name}=#{value}"
111
123
  end
112
-
113
- self.content_disposition = disposition
124
+ body
114
125
  end
115
126
 
116
127
  end
data/lib/mime/mail.rb ADDED
@@ -0,0 +1,51 @@
1
+ require 'time'
2
+ require 'mime/headers/internet'
3
+
4
+ module MIME
5
+
6
+ #
7
+ # Construct RFC 2822 Internet messages.
8
+ #
9
+ class Mail
10
+
11
+ include Headers::Internet
12
+
13
+ attr_reader :headers, :body
14
+
15
+ #
16
+ # Initialize a Mail object with body set to +content+.
17
+ #
18
+ def initialize content = nil
19
+ @headers = Header.new
20
+ self.body = content
21
+ self.date = Time.now
22
+ end
23
+
24
+ #
25
+ # Format the Mail object as an Internet message.
26
+ #
27
+ def to_s
28
+ self.message_id ||= ID.generate_gid(domain)
29
+ body.mime_version ||= "1.0 (Ruby MIME v#{VERSION})"
30
+
31
+ #--
32
+ # In an RFC 2822 message, the header and body sections must be separated
33
+ # by two line breaks (i.e., 2*CRLF). One line break is deliberately
34
+ # omitted here to allowing the body supplier to append headers to the
35
+ # top-level message header section.
36
+ #++
37
+ "#{headers}\r\n#{body}"
38
+ end
39
+
40
+ def body= content
41
+ @body = content.is_a?(Media) ? content : Text.new(content.to_s)
42
+ end
43
+
44
+ private
45
+
46
+ def domain
47
+ headers.get('from').match(/@([[:alnum:].-]+)/)[1] rescue nil
48
+ end
49
+
50
+ end
51
+ end
data/lib/mime/media.rb ADDED
@@ -0,0 +1,30 @@
1
+ require 'mime/headers/mime'
2
+
3
+ module MIME
4
+
5
+ #
6
+ # Abstract top-level media class.
7
+ #
8
+ class Media
9
+
10
+ include Headers::MIME
11
+
12
+ attr_reader :headers, :body
13
+
14
+ def initialize content, content_type, content_params = {}
15
+ AbstractClassError.no_instantiation(self, Media)
16
+ @headers = Header.new
17
+ @body = content
18
+ self.id = ID.generate_gid
19
+ self.type = append_field_params(content_type, content_params)
20
+ end
21
+
22
+ #
23
+ # Format the Media object as a MIME message.
24
+ #
25
+ def to_s
26
+ "#{headers}\r\n\r\n#{body}"
27
+ end
28
+
29
+ end
30
+ end
data/lib/mime/parser.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module MIME
2
2
 
3
3
  #
4
- # Parse MIME messages, constructing MediaType objects for each MIME entity.
4
+ # Parse MIME messages, constructing Media objects for each MIME entity.
5
5
  #
6
6
  # TODO Implement
7
7
  #
data/lib/mime.rb CHANGED
@@ -18,20 +18,38 @@
18
18
  #
19
19
  module MIME
20
20
 
21
- VERSION = '0.3.0'
21
+ VERSION = '0.4.0'
22
22
 
23
- module ContentFormats
24
- MAX_SMTP_LINE = 997
23
+ # Defined in RFC: https://tools.ietf.org/html/rfc5322#section-2.1.1
24
+ MAX_LINE_LENGTH = 998
25
+
26
+ module ID
27
+ #
28
+ # Generate local ID.
29
+ #
30
+ def self.generate_id
31
+ timestamp = (Time.now.to_f * 1E7).to_i
32
+ rand(1E9).to_s(36) +
33
+ object_id.to_s(36) +
34
+ timestamp.to_s(36)
35
+ end
36
+
37
+ #
38
+ # Generate global ID for "Message-ID" or "Content-ID" header.
39
+ #
40
+ def self.generate_gid domain = nil
41
+ generate_id + "@" + (domain || "#{generate_id}.local")
42
+ end
25
43
  end
26
44
 
27
45
  end
28
46
 
29
47
  require 'mime/content_types'
48
+ require 'mime/content_formats/text_flowed'
30
49
  require 'mime/error'
31
- require 'mime/header_container'
32
- require 'mime/media_type'
33
- require 'mime/discrete_media_type'
34
- require 'mime/composite_media_type'
35
- require 'mime/message'
50
+ require 'mime/header'
51
+ require 'mime/media'
52
+ require 'mime/composite_media'
53
+ require 'mime/discrete_media'
36
54
  require 'mime/discrete_media_factory'
37
- require 'mime/content_formats/text_flowed'
55
+ require 'mime/mail'
@@ -1,8 +1,5 @@
1
- Date: Wed, 29 Oct 2008 22:02:00 -0700
2
- Message-ID: <350015069@1033007998>
3
- MIME-Version: 1.0 (Ruby MIME v0.2.0)
4
- Content-ID: <10330079680.971971651113797>
1
+ Content-ID: <10330079680@971971651113797>
5
2
  Content-Type: application/octet-stream
6
3
  Content-Transfer-Encoding: binary
7
4
 
8
- 0110000101110101011001000110100101101111
5
+ 0110000101110101011001000110100101101111
@@ -1,8 +1,5 @@
1
- Date: Wed, 29 Oct 2008 22:06:46 -0700
2
- Message-ID: <738362674@978907908>
3
- MIME-Version: 1.0 (Ruby MIME v0.2.0)
4
- Content-ID: <9789078880.11546613041526>
1
+ Content-ID: <9789078880@11546613041526>
5
2
  Content-Type: audio/midi
6
3
  Content-Transfer-Encoding: binary
7
4
 
8
- 0110000101110101011001000110100101101111
5
+ 0110000101110101011001000110100101101111
Binary file
@@ -1,15 +1,15 @@
1
- Content-ID: <154873488180000.3045551269054866>
2
- Content-Type: multipart/alternative; boundary=Boundary_154873488180000.5284747660488839
1
+ Content-ID: <154873488180000@3045551269054866>
2
+ Content-Type: multipart/alternative; boundary=Boundary_154873488180000
3
3
 
4
- --Boundary_154873488180000.5284747660488839
5
- Content-ID: <154873488189000.6392244491224042>
4
+ --Boundary_154873488180000
5
+ Content-ID: <154873488189000@6392244491224042>
6
6
  Content-Type: text/enhanced; charset=us-ascii
7
7
 
8
8
  *Header*
9
9
  message
10
- --Boundary_154873488180000.5284747660488839
11
- Content-ID: <154873488185800.3424043482513621>
10
+ --Boundary_154873488180000
11
+ Content-ID: <154873488185800@3424043482513621>
12
12
  Content-Type: text/html; charset=iso-8859-1
13
13
 
14
14
  <html><body><h1>Header</h1><p>message</p></body></html>
15
- --Boundary_154873488180000.5284747660488839--
15
+ --Boundary_154873488180000--
@@ -1,10 +1,10 @@
1
- Content-ID: <88135231713600.7894413004791365>
2
- Content-Type: multipart/form-data; boundary=Boundary_88135231713600.3996846921776409
1
+ Content-ID: <88135231713600@7894413004791365>
2
+ Content-Type: multipart/form-data; boundary=Boundary_88135231713600
3
3
 
4
- --Boundary_88135231713600.3996846921776409
5
- Content-ID: <88135231717000.5720607746781624>
4
+ --Boundary_88135231713600
5
+ Content-ID: <88135231717000@5720607746781624>
6
6
  Content-Type: text/xml
7
- Content-Disposition: form-data; name="xml"
7
+ Content-Disposition: form-data; name=xml
8
8
 
9
9
  <media_types abstract="true">
10
10
  <discrete_media_types abstract="true">
@@ -24,10 +24,10 @@ Content-Disposition: form-data; name="xml"
24
24
  </composite>
25
25
  </media_types>
26
26
 
27
- --Boundary_88135231713600.3996846921776409
28
- Content-ID: <88135231721400.4415016053712104>
27
+ --Boundary_88135231713600
28
+ Content-ID: <88135231721400@4415016053712104>
29
29
  Content-Type: text/html
30
- Content-Disposition: form-data; name="htm"
30
+ Content-Disposition: form-data; name=htm
31
31
 
32
32
  <html>
33
33
  <body>
@@ -36,10 +36,10 @@ Content-Disposition: form-data; name="htm"
36
36
  </body>
37
37
  </html>
38
38
 
39
- --Boundary_88135231713600.3996846921776409
40
- Content-ID: <88135231725400.11623307734175536>
39
+ --Boundary_88135231713600
40
+ Content-ID: <88135231725400@11623307734175536>
41
41
  Content-Type: text/plain
42
- Content-Disposition: form-data; name="txt"
42
+ Content-Disposition: form-data; name=txt
43
43
 
44
44
  text body
45
- --Boundary_88135231713600.3996846921776409--
45
+ --Boundary_88135231713600--
Binary file
Binary file
@@ -1,11 +1,11 @@
1
1
  Date: Tue, 17 Dec 2013 04:54:56 -0700
2
- Message-ID: <776432154@10297424291820>
3
- MIME-Version: 1.0 (Ruby MIME v0.0.0)
4
2
  To: John <john@example.com>, paul@example.com, Mary <mary@example.com>
5
- Cc: boss@example.com <Head Honcho>
3
+ Cc: Head Honcho <boss@example.com>
6
4
  From: jane@example.com
7
5
  Subject: This is an important email
8
- Content-ID: <102975158103800.7998663631497803>
6
+ Message-ID: <776432154@10297424291820>
7
+ Content-ID: <102975158103800@7998663631497803>
9
8
  Content-Type: text/plain
9
+ MIME-Version: 1.0 (Ruby MIME v0.0.0)
10
10
 
11
- Hello, world!
11
+ Hello, world!
@@ -1,7 +1,4 @@
1
- Date: Wed, 29 Oct 2008 14:55:34 -0700
2
- Message-ID: <357114433@1021851988>
3
- MIME-Version: 1.0 (Ruby MIME v0.1.0)
4
- Content-ID: <10218519780.0838656876757202>
1
+ Content-ID: <10218519780@0838656876757202>
5
2
  Content-Type: text/plain
6
3
 
7
- a plain text message
4
+ a plain text message
@@ -1,8 +1,5 @@
1
- Date: Wed, 29 Oct 2008 21:56:48 -0700
2
- Message-ID: <740518531@1061166128>
3
- MIME-Version: 1.0 (Ruby MIME v0.1.0)
4
- Content-ID: <10611659780.38729886896997>
1
+ Content-ID: <10611659780@38729886896997>
5
2
  Content-Type: video/mpeg
6
3
  Content-Transfer-Encoding: binary
7
4
 
8
- 0110000101110101011001000110100101101111
5
+ 0110000101110101011001000110100101101111