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
-
#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.
81 82 83 |
# File 'lib/mime/entity_tmail.rb', line 81 def content @content end |
#encoding ⇒ Object
117 118 119 |
# File 'lib/mime/entity_tmail.rb', line 117 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.
81 82 83 |
# File 'lib/mime/entity_tmail.rb', line 81 def multipart_type @multipart_type end |
Instance Method Details
#attachment? ⇒ Boolean Also known as: file?
106 107 108 |
# File 'lib/mime/entity_tmail.rb', line 106 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
181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/mime/entity_tmail.rb', line 181 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
129 130 131 |
# File 'lib/mime/entity_tmail.rb', line 129 def find_part() find_parts(,true).first end |
#find_parts(options) ⇒ Object
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/mime/entity_tmail.rb', line 132 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
61 62 63 64 65 66 67 68 69 |
# File 'lib/mime/entity_tmail.rb', line 61 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.
75 76 77 |
# File 'lib/mime/entity_tmail.rb', line 75 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 #
86 87 88 89 |
# File 'lib/mime/entity_tmail.rb', line 86 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.
96 97 98 99 100 101 102 103 104 105 |
# File 'lib/mime/entity_tmail.rb', line 96 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
110 111 112 113 114 115 |
# File 'lib/mime/entity_tmail.rb', line 110 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
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/mime/entity_tmail.rb', line 149 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.
196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/mime/entity_tmail.rb', line 196 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
171 172 173 174 175 176 177 178 |
# File 'lib/mime/entity_tmail.rb', line 171 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 |