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
|