Class: Msg::Attachment

Inherits:
Object
  • Object
show all
Defined in:
lib/msg.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(obj) ⇒ Attachment

Returns a new instance of Attachment.



358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
# File 'lib/msg.rb', line 358

def initialize obj
	@obj = obj
	@properties = Properties.load @obj
	@embedded_ole = nil
	@embedded_msg = nil

	@properties.unused.each do |child|
		# FIXME temporary hack. this is fairly messy stuff.
		if child.dir? and child.name =~ Properties::SUBSTG_RX and
			 $1 == '3701' and $2.downcase == '000d'
			@embedded_ole = child
			class << @embedded_ole
				def compobj
					return nil unless compobj = self["\001CompObj"]
					compobj.read[/^.{32}([^\x00]+)/m, 1]
				end

				def embedded_type
					temp = compobj and return temp
					# try to guess more
					if children.select { |child| child.name =~ /__(substg|properties|recip|attach|nameid)/ }.length > 2
						return 'Microsoft Office Outlook Message'
					end
					nil
				end
			end
			if @embedded_ole.embedded_type == 'Microsoft Office Outlook Message'
				@embedded_msg = Msg.new @embedded_ole
			end
		end
		# FIXME warn
	end
end

Instance Attribute Details

#objObject (readonly)

Returns the value of attribute obj.



355
356
357
# File 'lib/msg.rb', line 355

def obj
  @obj
end

#propertiesObject (readonly) Also known as: props

Returns the value of attribute properties.



355
356
357
# File 'lib/msg.rb', line 355

def properties
  @properties
end

Instance Method Details

#dataObject



402
403
404
# File 'lib/msg.rb', line 402

def data
	@embedded_msg || @embedded_ole || props.attach_data
end

#filenameObject



398
399
400
# File 'lib/msg.rb', line 398

def filename
	props.attach_long_filename || props.attach_filename
end

#inspectObject



451
452
453
454
455
# File 'lib/msg.rb', line 451

def inspect
	"#<#{self.class.to_s[/\w+$/]}" +
		(filename ? " filename=#{filename.inspect}" : '') +
		(@embedded_ole ? " embedded_type=#{@embedded_ole.embedded_type.inspect}" : '') + ">"
end

#save(io) ⇒ Object

with new stream work, its possible to not have the whole thing in memory at one time, just to save an attachment

a = msg.attachments.first a.save open(File.basename(a.filename || 'attachment'), 'wb')



411
412
413
414
# File 'lib/msg.rb', line 411

def save io
	raise "can only save binary data blobs, not ole dirs" if @embedded_ole
	data.each_read { |chunk| io << chunk }
end

#to_mimeObject



416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
# File 'lib/msg.rb', line 416

def to_mime
	# TODO: smarter mime typing.
	mimetype = props.attach_mime_tag || 'application/octet-stream'
	mime = Mime.new "Content-Type: #{mimetype}\r\n\r\n"
	mime.headers['Content-Disposition'] = [%{attachment; filename="#{filename}"}]
	mime.headers['Content-Transfer-Encoding'] = ['base64']
	mime.headers['Content-Location'] = [props.attach_content_location] if props.attach_content_location
	mime.headers['Content-ID'] = [props.attach_content_id] if props.attach_content_id
	# data.to_s for now. data was nil for some reason.
	# perhaps it was a data object not correctly handled?
	# hmmm, have to use read here. that assumes that the data isa stream.
	# but if the attachment data is a string, then it won't work. possible?
	data_str = if @embedded_msg
		mime.headers['Content-Type'] = 'message/rfc822'
		# lets try making it not base64 for now
		mime.headers.delete 'Content-Transfer-Encoding'
		# not filename. rather name, or something else right?
		# maybe it should be inline?? i forget attach_method / access meaning
		mime.headers['Content-Disposition'] = [%{attachment; filename="#{@embedded_msg.subject}"}]
		@embedded_msg.to_mime.to_s
	elsif @embedded_ole
		# kind of hacky
		io = StringIO.new
		Ole::Storage.new io do |ole|
			ole.root.type = :dir
			Ole::Storage::Dirent.copy @embedded_ole, ole.root
		end
		io.string
	else
		data.read.to_s
	end
	mime.body.replace @embedded_msg ? data_str : Base64.encode64(data_str).gsub(/\n/, "\r\n")
	mime
end

#valid?Boolean

Returns:

  • (Boolean)


392
393
394
395
396
# File 'lib/msg.rb', line 392

def valid?
	# something i started to notice when handling embedded ole object attachments is
	# the particularly strange case where they're are empty attachments
	props.raw.keys.length > 0
end