Class: Sonar::Connector::EwsPullConnector

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

Constant Summary collapse

MIN_BATCH_SIZE =
2
DEFAULT_BATCH_SIZE =
100

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#authObject

Returns the value of attribute auth.



17
18
19
# File 'lib/ews_pull_connector/ews_pull_connector.rb', line 17

def auth
  @auth
end

#batch_sizeObject

Returns the value of attribute batch_size.



21
22
23
# File 'lib/ews_pull_connector/ews_pull_connector.rb', line 21

def batch_size
  @batch_size
end

#deleteObject

Returns the value of attribute delete.



22
23
24
# File 'lib/ews_pull_connector/ews_pull_connector.rb', line 22

def delete
  @delete
end

#distinguished_foldersObject

Returns the value of attribute distinguished_folders.



20
21
22
# File 'lib/ews_pull_connector/ews_pull_connector.rb', line 20

def distinguished_folders
  @distinguished_folders
end

#is_journalObject

Returns the value of attribute is_journal.



23
24
25
# File 'lib/ews_pull_connector/ews_pull_connector.rb', line 23

def is_journal
  @is_journal
end

#passwordObject

Returns the value of attribute password.



19
20
21
# File 'lib/ews_pull_connector/ews_pull_connector.rb', line 19

def password
  @password
end

#urlObject

Returns the value of attribute url.



16
17
18
# File 'lib/ews_pull_connector/ews_pull_connector.rb', line 16

def url
  @url
end

#userObject

Returns the value of attribute user.



18
19
20
# File 'lib/ews_pull_connector/ews_pull_connector.rb', line 18

def user
  @user
end

Instance Method Details

#actionObject



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/ews_pull_connector/ews_pull_connector.rb', line 101

def action
  distinguished_folder_ids.each do |fid|
    log.info "processing: #{fid.inspect}"

    offset = 0

    begin
      msg_ids = find(fid, offset)

      if msg_ids && msg_ids.length>0
        msgs = get(fid, msg_ids)

        # if there is no state, then state is set to the first message timestamp
        state[fid.key] ||= msgs.first[:date_time_received].to_s if msgs.first[:date_time_received]

        save_messages(msgs)

        if msgs.last[:date_time_received] != state[fid.key]
          finished=true
          state[fid.key] = msgs.last[:date_time_received].to_s
        end
        
        delete_messages(fid, msgs) if delete

        offset += msg_ids.length
      end
    end while msg_ids.length>0 && !finished

    save_state

    log.info "finished processing: #{fid.inspect}"
  end
  log.info "finished action"
end

#delete_messages(folder_id, messages) ⇒ Object



202
203
204
205
# File 'lib/ews_pull_connector/ews_pull_connector.rb', line 202

def delete_messages(folder_id, messages)
  log.info "deleting #{messages.length} messages from #{folder_id.inspect}"
  folder_id.delete_item(messages, :delete_type=>:HardDelete)
end

#distinguished_folder_idsObject



45
46
47
48
49
50
51
52
# File 'lib/ews_pull_connector/ews_pull_connector.rb', line 45

def distinguished_folder_ids
  return @distinguished_folder_ids if @distinguished_folder_ids
  client ||= Rews::Client.new(url, auth, user, password)

  @distinguished_folder_ids = @distinguished_folders.inject([]) do |ids, (name, mailbox_email)|
    ids << client.distinguished_folder_id(name, mailbox_email)
  end
end

#extract_journalled_message(message) ⇒ Object



193
194
195
196
197
198
199
200
# File 'lib/ews_pull_connector/ews_pull_connector.rb', line 193

def extract_journalled_message(message)
  mime_msg = Base64::decode64(message[:mime_content])
  journal_msg = Rfc822Util.extract_journalled_mail(mime_msg)
  Rfc822Util.mail_to_hash(journal_msg)
rescue Exception=>e
  log.warn("problem extracting journalled message from wrapper message")
  log.warn(e)
end

#find(folder_id, offset) ⇒ Object

find message ids from a folder



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/ews_pull_connector/ews_pull_connector.rb', line 55

def find(folder_id, offset)
  find_opts = {
    :sort_order=>[["item:DateTimeReceived", "Ascending"]],
    :indexed_page_item_view=>{
      :max_entries_returned=>batch_size, 
      :offset=>offset},
    :item_shape=>{
      :base_shape=>:IdOnly}}
  
  restriction = [:==, "item:ItemClass", "IPM.Note"]
  if state[folder_id.key]
    restriction = [:and,
                   restriction,
                   [:>= , "item:DateTimeReceived", state[folder_id.key]]]
  end
  find_opts[:restriction] =  restriction
  
  folder_id.find_item(find_opts)
end

#get(folder_id, msg_ids) ⇒ Object



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
# File 'lib/ews_pull_connector/ews_pull_connector.rb', line 75

def get(folder_id, msg_ids)
  get_opts = {
    :item_shape=>{
      :base_shape=>:IdOnly, 
      :additional_properties=>[[:field_uri, "item:ItemClass"],
                               [:field_uri, "item:DateTimeSent"],
                               [:field_uri, "item:DateTimeReceived"],
                               [:field_uri, "item:InReplyTo"],
                               [:field_uri, "message:InternetMessageId"],
                               [:field_uri, "message:References"],
                               [:field_uri, "message:From"],
                               [:field_uri, "message:Sender"],
                               [:field_uri, "message:ToRecipients"],
                               [:field_uri, "message:CcRecipients"],
                               [:field_uri, "message:BccRecipients"]]}}

  # we have to retrieve the journal message content and unwrap the 
  # original message if this
  # is an exchange journal mailbox
  if is_journal
    get_opts[:item_shape][:additional_properties] << [:field_uri, "item:MimeContent"]
  end
  
  folder_id.get_item(msg_ids, get_opts)
end

#inspectObject



41
42
43
# File 'lib/ews_pull_connector/ews_pull_connector.rb', line 41

def inspect
  "#<#{self.class} @url=#{url}, @auth=#{auth}, @user=#{user}, @password=#{password}, @distinguished_folders=#{distinguished_folders}, @batch_size=#{batch_size}, @delete=#{delete}, @is_journal=#{is_journal}>"
end

#mailbox_recipients_to_hashes(recipients) ⇒ Object



168
169
170
171
172
# File 'lib/ews_pull_connector/ews_pull_connector.rb', line 168

def mailbox_recipients_to_hashes(recipients)
  mailboxes = recipients[:mailbox] if recipients
  mailboxes = [mailboxes] if !mailboxes.is_a?(Array)
  mailboxes.compact.map{|a| mailbox_to_hash(a)}
end

#mailbox_to_hash(mailbox) ⇒ Object



161
162
163
164
165
166
# File 'lib/ews_pull_connector/ews_pull_connector.rb', line 161

def mailbox_to_hash(mailbox)
  [:name, :email_address].inject({}) do |h, k|
    h[k] = mailbox[k]
    h
  end
end

#message_to_hash(msg) ⇒ Object



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/ews_pull_connector/ews_pull_connector.rb', line 174

def message_to_hash(msg)
  message_id = Rfc822Util.strip_header(msg[:internet_message_id]) if msg[:internet_message_id]
  in_reply_to = Rfc822Util.strip_headers(msg[:in_reply_to]).first if msg[:in_reply_to]
  references = Rfc822Util.strip_headers(msg[:references]) if msg[:references]
  
    json_hash = {
      :message_id=>message_id,
      :sent_at=>msg[:date_time_sent].to_s,
      :in_reply_to=>in_reply_to,
      :references=>references,
      :from=>mailbox_recipients_to_hashes(msg[:from]).first,
      :sender=>mailbox_recipients_to_hashes(msg[:sender]).first,
      :to=>mailbox_recipients_to_hashes(msg[:to_recipients]),
      :cc=>mailbox_recipients_to_hashes(msg[:cc_recipients]),
      :bcc=>mailbox_recipients_to_hashes(msg[:bcc_recipients])
    }
    
end

#parse(settings) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/ews_pull_connector/ews_pull_connector.rb', line 25

def parse(settings)
  ["name", "repeat_delay", "url", "auth", "user", "password", "distinguished_folders", "batch_size"].each do |param|
    raise Sonar::Connector::InvalidConfig.new("#{self.class}: param '#{param}' is blank") if settings[param].blank?
  end
  
  @url = settings["url"]
  @auth = settings["auth"]
  @user = settings["user"]
  @password = settings["password"]
  @mailbox_email = settings["mailbox_email"]
  @distinguished_folders = settings["distinguished_folders"]
  @batch_size = [settings["batch_size"] || DEFAULT_BATCH_SIZE, MIN_BATCH_SIZE].max
  @delete = !!settings["delete"]
  @is_journal = !!settings["is_journal"]
end

#save_messages(messages) ⇒ Object



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/ews_pull_connector/ews_pull_connector.rb', line 136

def save_messages(messages)
  messages.each do |msg|
    h = if is_journal
          extract_journalled_message(msg)
        else
          message_to_hash(msg)
        end
    
    if !h
      log.warn("no data extracted from message. could be a decoding eror")
      return
    end

    h[:type] = "email"
    h[:connector] = name
    h[:source] = url
    h[:source_id]=msg[:item_id][:id]
    h[:received_at] = msg[:date_time_received]


    fname = MD5.hexdigest(msg[:item_id][:id])
    filestore.write(:complete, "#{fname}.json", h.to_json)
  end
end