aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/ruby-msg/lib/mapi.rb
blob: b9d3413f74ba0794df11193213c7a3766b03e904 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
require 'mapi/types'
require 'mapi/property_set'

module Mapi
	VERSION = '1.4.0'

	#
	# Mapi::Item is the base class used for all mapi objects, and is purely a
	# property set container
	#
	class Item
		attr_reader :properties
		alias props properties

		# +properties+ should be a PropertySet instance.
		def initialize properties
			@properties = properties
		end
	end

	# a general attachment class. is subclassed by Msg and Pst attachment classes
	class Attachment < Item
		def filename
			props.attach_long_filename || props.attach_filename
		end

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

		# 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') 
		def save io
			raise "can only save binary data blobs, not ole dirs" if @embedded_ole
			data.each_read { |chunk| io << chunk }
		end

		def inspect
			"#<#{self.class.to_s[/\w+$/]}" +
				(filename ? " filename=#{filename.inspect}" : '') +
				(@embedded_ole ? " embedded_type=#{@embedded_ole.embedded_type.inspect}" : '') + ">"
		end
	end
	
	class Recipient < Item
		# some kind of best effort guess for converting to standard mime style format.
		# there are some rules for encoding non 7bit stuff in mail headers. should obey
		# that here, as these strings could be unicode
		# email_address will be an EX:/ address (X.400?), unless external recipient. the
		# other two we try first.
		# consider using entry id for this too.
		def name
			name = props.transmittable_display_name || props.display_name
			# dequote
			name[/^'(.*)'/, 1] or name rescue nil
		end

		def email
			props.smtp_address || props.org_email_addr || props.email_address
		end

		RECIPIENT_TYPES = { 0 => :orig, 1 => :to, 2 => :cc, 3 => :bcc }
		def type
			RECIPIENT_TYPES[props.recipient_type]
		end

		def to_s
			if name = self.name and !name.empty? and email && name != email
				%{"#{name}" <#{email}>}
			else
				email || name
			end
		end

		def inspect
			"#<#{self.class.to_s[/\w+$/]}:#{self.to_s.inspect}>"
		end
	end

	# i refer to it as a message (as does mapi), although perhaps Item is better, as its a more general
	# concept than a message, as used in Pst files. though maybe i'll switch to using
	# Mapi::Object as the base class there.
	#
	# IMessage essentially, but there's also stuff like IMAPIFolder etc. so, for this to form
	# basis for PST Item, it'd need to be more general.
	class Message < Item
		# these 2 collections should be provided by our subclasses
		def attachments
			raise NotImplementedError
		end

		def recipients
			raise NotImplementedError
		end
		
		def inspect
			str = %w[message_class from to subject].map do |key|
				" #{key}=#{props.send(key).inspect}"
			end.compact.join
			str << " recipients=#{recipients.inspect}"
			str << " attachments=#{attachments.inspect}"
			"#<#{self.class.to_s[/\w+$/]}#{str}>"
		end
	end
end