Class: MIME::Entity
- Defined in:
- lib/mime/entity_tmail.rb,
lib/mime/entity.rb
Direct Known Subclasses
Instance Attribute Summary collapse
-
#content ⇒ Object
An Entity has Content.
- #encoding ⇒ Object
-
#multipart_type ⇒ Object
readonly
An Entity has Content.
Instance Method Summary collapse
- #attachment? ⇒ Boolean (also: #file?)
-
#decoded_content ⇒ Object
Converts this data structure into a string, but decoded if necessary.
- #find_part(options) ⇒ Object
- #find_parts(options) ⇒ Object
-
#from_parsed(parsed) ⇒ Object
This means we have a structure from IETF::RFC2045.
-
#from_tmail(tmail) ⇒ Object
Parse a tmail object into our Entity object.
-
#headers ⇒ Object
An Entity has Headers.
-
#initialize(one = nil, two = nil) ⇒ Entity
constructor
A new instance of Entity.
- #inspect ⇒ Object
-
#multipart? ⇒ Boolean
Macro Methods #.
-
#multipart_boundary ⇒ Object
Auto-generates a boundary if one doesn’t yet exist.
- #parsed ⇒ Object
- #part_filename ⇒ Object
- #save_to_file(path = nil) ⇒ Object
-
#set_content(raw) ⇒ Object
(also: #content=)
You can set new content, and it will be saved in encoded form.
-
#to_s ⇒ Object
Renders this data structure into a string, encoded.
Constructor Details
#initialize(one = nil, two = nil) ⇒ Entity
Returns a new instance of Entity.
14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/mime/entity_tmail.rb', line 14 def initialize(one=nil,two=nil) if one.is_a?(Hash) || two.is_a?(Hash) # Intent is to generate a message from parameters @headers = one.is_a?(Hash) ? one : two set_content one if one.is_a?(String) @encoding = 'quoted-printable' unless encoding elsif one.is_a?(String) # Intent is to parse a message body @raw = one.gsub(/\r/,'').gsub(/\n/, "\r\n") # normalizes end-of-line characters @tmail = TMail::Mail.parse(@raw) from_tmail(@tmail) elsif one.is_a?(TMail::Mail) @tmail = one from_tmail(@tmail) end end |
Instance Attribute Details
#content ⇒ Object
An Entity has Content.
IF the Content-Type is a multipart type,
the content will be one or more Entities.
83 84 85 |
# File 'lib/mime/entity_tmail.rb', line 83 def content @content end |
#encoding ⇒ Object
119 120 121 |
# File 'lib/mime/entity_tmail.rb', line 119 def encoding @encoding ||= headers['content-transfer-encoding'] || nil end |
#multipart_type ⇒ Object (readonly)
An Entity has Content.
IF the Content-Type is a multipart type,
the content will be one or more Entities.
83 84 85 |
# File 'lib/mime/entity_tmail.rb', line 83 def multipart_type @multipart_type end |
Instance Method Details
#attachment? ⇒ Boolean Also known as: file?
108 109 110 |
# File 'lib/mime/entity_tmail.rb', line 108 def @tmail. || headers['content-disposition'] =~ /^form-data;.* filename=[\"\']?[^\"\']+[\"\']?/ if headers['content-disposition'] end |
#decoded_content ⇒ Object
Converts this data structure into a string, but decoded if necessary
183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/mime/entity_tmail.rb', line 183 def decoded_content return nil if @content.is_a?(Array) case encoding.to_s.downcase when 'quoted-printable' @content.unpack('M')[0] when 'base64' @content.unpack('m')[0] # when '7bit' # # should get this 7bit encoding done too... else @content end end |
#find_part(options) ⇒ Object
131 132 133 |
# File 'lib/mime/entity_tmail.rb', line 131 def find_part() find_parts(,true).first end |
#find_parts(options) ⇒ Object
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/mime/entity_tmail.rb', line 134 def find_parts(,find_only_one=false) parts = [] return nil unless ([:content_type] && headers['content-type']) || ([:content_disposition] && headers['content-disposition']) # Do I match your search? iam = true iam = false if [:content_type] && headers['content-type'] !~ /^#{[:content_type]}(?=;|$)/ iam = false if [:content_disposition] && headers['content-disposition'] !~ /^#{[:content_disposition]}(?=;|$)/ parts << self if iam return parts unless parts.empty? # Do any of my children match your search? content.each do |part| parts.concat part.find_parts(,find_only_one) return parts if !parts.empty? && find_only_one end if multipart? return parts end |
#from_parsed(parsed) ⇒ Object
This means we have a structure from IETF::RFC2045. Entity is: [headers, content], while content may be an array of Entities. Or, :boundary, :content
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/mime/entity_tmail.rb', line 36 def from_parsed(parsed) case parsed when Array if parsed[0].is_a?(Hash) && (parsed[1].is_a?(Hash) || parsed[1].is_a?(String)) @headers = parsed[0] @content = parsed[1].is_a?(Hash) ? parsed[1][:content].collect {|p| Entity.new.from_parsed(p)} : parsed[1] if parsed[1].is_a?(Hash) @multipart_type = parsed[1][:type] @multipart_boundary = parsed[1][:boundary] raise "IETF PARSING FAIL! (empty boundary)" if @multipart_boundary == '' end else raise "IETF PARSING FAIL! ('A' structure)" end return self when Hash if parsed.has_key?(:type) && parsed.has_key?(:boundary) && parsed.has_key?(:content) @content = parsed[:content].is_a?(Array) ? parsed[:content].collect {|p| Entity.new.from_parsed(p)} : parsed[:content] else raise "IETF PARSING FAIL! ('H' structure)" end return self end raise ArgumentError, "Must pass in either: [an array with two elements: headers(hash) and content(string or array)] OR [a hash containing :type, :boundary, and :content(being the former or a string)]" end |
#from_tmail(tmail) ⇒ Object
Parse a tmail object into our Entity object
63 64 65 66 67 68 69 70 71 |
# File 'lib/mime/entity_tmail.rb', line 63 def from_tmail(tmail) raise ArgumentError, "Expecting a TMail::Mail object." unless tmail.is_a?(TMail::Mail) @headers ||= Hash.new {|h,k| tmail.header[k].to_s } if multipart? @content = tmail.parts.collect { |tpart| Entity.new.from_tmail(tpart) } else set_content tmail.body # TMail has already decoded it, but we need it still encoded end end |
#headers ⇒ Object
An Entity has Headers.
77 78 79 |
# File 'lib/mime/entity_tmail.rb', line 77 def headers @headers ||= {} end |
#inspect ⇒ Object
29 30 31 |
# File 'lib/mime/entity_tmail.rb', line 29 def inspect "<#{self.class.name}##{object_id} Headers:{#{headers.collect {|k,v| "#{k}=#{v}"}.join(' ')}} content:#{multipart? ? 'multipart' : 'flat'}>" end |
#multipart? ⇒ Boolean
Macro Methods #
88 89 90 91 |
# File 'lib/mime/entity_tmail.rb', line 88 def multipart? return @tmail.multipart? if @tmail !!(headers['content-type'] =~ /multipart\//) if headers['content-type'] end |
#multipart_boundary ⇒ Object
Auto-generates a boundary if one doesn’t yet exist.
98 99 100 101 102 103 104 105 106 107 |
# File 'lib/mime/entity_tmail.rb', line 98 def multipart_boundary return nil unless multipart? unless @multipart_boundary ||= (@tmail && @tmail.header['content-type'] ? @tmail.header['content-type'].params['boundary'] : nil) # Content-Type: multipart/mixed; boundary=000e0cd28d1282f4ba04788017e5 @multipart_boundary = String.random(25) headers['content-type'] = "multipart/#{multipart_type}; boundary=#{@multipart_boundary}" @multipart_boundary end @multipart_boundary end |
#parsed ⇒ Object
28 29 30 |
# File 'lib/mime/entity.rb', line 28 def parsed IETF::RFC2045.parse_rfc2045_from(@raw) end |
#part_filename ⇒ Object
112 113 114 115 116 117 |
# File 'lib/mime/entity_tmail.rb', line 112 def part_filename # Content-Disposition: attachment; filename="summary.txt" if headers['content-disposition'] =~ /; filename=[\"\']?([^\"\']+)/ $1 end if headers['content-disposition'] end |
#save_to_file(path = nil) ⇒ Object
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/mime/entity_tmail.rb', line 151 def save_to_file(path=nil) filename = path if path && !File.exists?(path) # If path doesn't exist, assume it's a filename filename ||= path + '/' + part_filename if path && # If path does exist, and we're saving an attachment, use the attachment filename filename ||= ( ? part_filename : path) # If there is no path and we're saving an attachment, use the attachment filename; otherwise use path (whether it is present or not) filename ||= '.' # No path supplied, and not saving an attachment. We'll just save it in the current directory. if File.directory?(filename) i = 0 begin i += 1 filename = filename + "/attachment-#{i}" end until !File.exists(filename) end # After all that trouble to get a filename to save to... File.open(filename, 'w') do |file| file << decoded_content end end |
#set_content(raw) ⇒ Object Also known as: content=
You can set new content, and it will be saved in encoded form.
198 199 200 201 202 203 204 205 206 207 208 |
# File 'lib/mime/entity_tmail.rb', line 198 def set_content(raw) @content = raw.is_a?(Array) ? raw : case encoding.to_s.downcase when 'quoted-printable' [raw].pack('M') when 'base64' [raw].pack('m') else raw end end |
#to_s ⇒ Object
Renders this data structure into a string, encoded
173 174 175 176 177 178 179 180 |
# File 'lib/mime/entity_tmail.rb', line 173 def to_s multipart_boundary # initialize the boundary if necessary, so it will be included in the headers headers.inject('') {|a,(k,v)| a << "#{MIME.capitalize_header(k)}: #{v}\r\n"} + "\r\n" + if content.is_a?(Array) "\r\n--#{multipart_boundary}\r\n" + content.collect {|part| part.to_s }.join("\r\n--#{multipart_boundary}\r\n") + "\r\n--#{multipart_boundary}--\r\n" else content.to_s end end |