notes-structured-text-json-messages 0.1.1 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.1.4
@@ -16,6 +16,10 @@ OptionParser.new do |opts|
16
16
  opts.on("-v", "--[no-]verbose", "Run verbosely (default: true)") do |v|
17
17
  options[:verbose] = v
18
18
  end
19
+
20
+ opts.on("-m", "--mapping-file FILE", "output notes-distinguished-name <=> internet-email-address mappings to FILE") do |f|
21
+ options[:mapping_file] = f
22
+ end
19
23
  end.parse!
20
24
 
21
25
  NotesStructuredTextJsonMessages.logger = Logger.new($stderr)
@@ -5,6 +5,7 @@ module NotesStructuredTextJsonMessages
5
5
  class << self
6
6
  attr_accessor :logger
7
7
  attr_accessor :stats
8
+ attr_accessor :mappings
8
9
  end
9
10
 
10
11
  module_function
@@ -13,26 +14,50 @@ module NotesStructuredTextJsonMessages
13
14
  yield logger if logger
14
15
  end
15
16
 
16
- def reset_stats
17
- self.stats={}
18
- end
19
-
20
17
  def increment_stats(key)
21
18
  self.stats[key] = (self.stats[key]||0) + 1
22
19
  end
23
20
 
24
- def json_messages(output_dir, input_files, options={})
25
- reset_stats
26
- [*input_files].each do |input_file|
27
- File.open(input_file, "r") do |input|
28
- json_messages_from_stream(output_dir, input, options)
21
+ def collect_mapping(addr1, addr2)
22
+ self.mappings << [addr1, addr2] if self.mappings
23
+ end
24
+
25
+ def with_mappings(options)
26
+ mapping_file = options[:mapping_file]
27
+ log{|logger| logger.info "using mapping_file: #{options[:mapping_file]}"} if mapping_file
28
+ self.mappings=[]
29
+ yield
30
+ ensure
31
+ if mapping_file
32
+ File.open(mapping_file, "w") do |output|
33
+ output << "[\n"
34
+ output << self.mappings.map(&:to_json).join(",\n")
35
+ output << "\n]"
29
36
  end
30
37
  end
31
- stats.each do |k,v|
38
+ end
39
+
40
+ def with_stats
41
+ self.stats={}
42
+ yield
43
+ ensure
44
+ self.stats.each do |k,v|
32
45
  log{|logger| logger.info("#{k}: #{v}")}
33
46
  end
34
47
  end
35
48
 
49
+ def json_messages(output_dir, input_files, options={})
50
+ with_stats do
51
+ with_mappings(options) do
52
+ [*input_files].each do |input_file|
53
+ File.open(input_file, "r") do |input|
54
+ json_messages_from_stream(output_dir, input, options)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+
36
61
  def json_messages_from_stream(output_dir, input, options={})
37
62
  block = nil
38
63
  process_block(output_dir, block, options) while block=read_block(input)
@@ -138,35 +163,42 @@ module NotesStructuredTextJsonMessages
138
163
  def process_address(addr)
139
164
  if is_distinguished_name?(addr)
140
165
  name = addr[/CN=([^\/]*)/, 1]
141
- { :name=>name,
142
- :notes_dn=>addr}
166
+ h = {:notes_dn=>addr}
167
+ h[:name] = name if name
168
+ h
143
169
  else
144
170
  ta = TMail::Address.parse(addr)
145
171
  if ta.is_a?(TMail::Address)
146
- { :name=>ta.name,
147
- :email_address=>ta.address.downcase}
172
+ h = {:email_address=>ta.address.downcase}
173
+ h[:name] = ta.name if ta.name
174
+ h
148
175
  else
149
176
  log{|logger| logger.warn("addr does not parse to a TMail::Address: #{addr}")}
150
177
  end
151
178
  end
152
179
  end
153
180
 
154
- def process_address_pair(inet_addr, notes_addr)
181
+ def process_address_pair(inet_addr, notes_addr, options)
155
182
  if inet_addr == "."
156
183
  process_address(notes_addr)
157
184
  else
158
- process_address(inet_addr)
185
+ inet_addr = process_address(inet_addr)
186
+ notes_addr = process_address(notes_addr)
187
+
188
+ collect_mapping(notes_addr, inet_addr)
189
+
190
+ inet_addr
159
191
  end
160
192
  end
161
193
 
162
- def process_addresses(block, inet_field, notes_field)
194
+ def process_addresses(block, inet_field, notes_field, options)
163
195
  inet_h = header_values(block, inet_field, :split_rfc822_addresses)
164
196
  notes_h = header_values(block, notes_field, :split_rfc822_addresses)
165
197
 
166
198
  if inet_h && notes_h
167
199
  if inet_h.length == notes_h.length
168
200
  inet_h.zip(notes_h).map do |inet_addr, notes_addr|
169
- process_address_pair(inet_addr, notes_addr)
201
+ process_address_pair(inet_addr, notes_addr, options)
170
202
  end
171
203
  else
172
204
  raise "#{inet_field}: does not match #{notes_field}:"
@@ -188,11 +220,17 @@ module NotesStructuredTextJsonMessages
188
220
 
189
221
  def extract_json_message(block, options={})
190
222
  message_id_h = header_value(block, MESSAGE_ID)
191
- raise "no #{MESSAGE_ID}" if !message_id_h
223
+ if !message_id_h
224
+ increment_stats(:failure_no_message_id)
225
+ raise "no #{MESSAGE_ID}"
226
+ end
192
227
  message_id = strip_angles(message_id_h)
193
228
 
194
229
  posted_date_h = header_value(block, POSTED_DATE)
195
- raise "no #{POSTED_DATE}" if !posted_date_h
230
+ if !posted_date_h
231
+ increment_stats(:failure_no_posted_date)
232
+ raise "no #{POSTED_DATE}"
233
+ end
196
234
  posted_date = parse_date(posted_date_h, options)
197
235
 
198
236
  in_reply_to_h = header_value(block, IN_REPLY_TO)
@@ -201,14 +239,20 @@ module NotesStructuredTextJsonMessages
201
239
  references_h = header_values(block, REFERENCES, " ")
202
240
  references = references_h.map{|r| strip_angles(r)} if references_h
203
241
 
204
- froms = process_addresses(block, INET_FROM, FROM)
205
- raise "no From:, or more than one From:" if !froms || froms.size>1
242
+ froms = process_addresses(block, INET_FROM, FROM, options)
243
+ if !froms || froms.size>1
244
+ increment_stats(:failure_from)
245
+ raise "no From:, or more than one From:"
246
+ end
206
247
  from = froms[0]
207
- to = process_addresses(block, INET_TO, TO)
208
- cc = process_addresses(block, INET_CC, CC)
209
- bcc = process_addresses(block, INET_BCC, BCC)
248
+ to = process_addresses(block, INET_TO, TO, options)
249
+ cc = process_addresses(block, INET_CC, CC, options)
250
+ bcc = process_addresses(block, INET_BCC, BCC, options)
210
251
 
211
- raise "no recipients" if (to||[]).size + (cc||[]).size + (bcc||[]).size == 0
252
+ if (to||[]).size + (cc||[]).size + (bcc||[]).size == 0
253
+ increment_stats(:failure_no_recipients)
254
+ raise "no recipients"
255
+ end
212
256
 
213
257
  { :message_type=>"email",
214
258
  :message_id=>message_id,
@@ -222,7 +266,8 @@ module NotesStructuredTextJsonMessages
222
266
  end
223
267
 
224
268
  def output_json_message(output_dir, json_message)
225
- fname = File.join(output_dir, MD5.hexdigest(json_message[:message_id]))
269
+ fname = File.join(output_dir, "#{MD5.hexdigest(json_message[:message_id])}.json")
226
270
  File.open(fname, "w"){|out| out << json_message.to_json}
227
271
  end
272
+
228
273
  end
@@ -5,7 +5,7 @@ describe NotesStructuredTextJsonMessages do
5
5
  it "should open each file and call json_messages_from_stream with it" do
6
6
  output_dir = Object.new
7
7
  input_files = [Object.new, Object.new]
8
- options = Object.new
8
+ options = {}
9
9
 
10
10
  input0 = Object.new
11
11
  input1 = Object.new
@@ -34,6 +34,27 @@ describe NotesStructuredTextJsonMessages do
34
34
  end
35
35
  end
36
36
 
37
+ describe "with_mappings" do
38
+ it "should write mapping JSON if mapping_file option is given" do
39
+ opts = Object.new
40
+ mf = Object.new
41
+ mfs = StringIO.new
42
+ stub(opts).[](:mapping_file){mf}
43
+ mock(File).open(mf, "w"){|f,m,block| block.call(mfs)}
44
+
45
+ NotesStructuredTextJsonMessages.with_mappings(opts) do
46
+ NotesStructuredTextJsonMessages.collect_mapping({:notes_dn=>"CN=foo mcfoo/OU=foofoo/O=foo"},
47
+ {:email_address=>"foo.mcfoo@foo.com"})
48
+ NotesStructuredTextJsonMessages.collect_mapping({:notes_dn=>"CN=bar mcbar/OU=barbar/O=bar"},
49
+ {:email_address=>"bar.mcbar@bar.com"})
50
+ end
51
+
52
+ j = JSON.parse(mfs.string)
53
+ j.should == [[{"notes_dn"=>"CN=foo mcfoo/OU=foofoo/O=foo"}, {"email_address"=>"foo.mcfoo@foo.com"}],
54
+ [{"notes_dn"=>"CN=bar mcbar/OU=barbar/O=bar"}, {"email_address"=>"bar.mcbar@bar.com"}]]
55
+ end
56
+ end
57
+
37
58
  describe "readblock" do
38
59
  it "should return lines read from a stream until the first empty line" do
39
60
  input = <<-EOF
@@ -240,12 +261,12 @@ EOF
240
261
 
241
262
  describe "process_address_pair" do
242
263
  it "should process_address the notes_address if the inet_address is '.'" do
243
- NotesStructuredTextJsonMessages.process_address_pair(".", "CN=foo bar/OU=here/O=there").should ==
264
+ NotesStructuredTextJsonMessages.process_address_pair(".", "CN=foo bar/OU=here/O=there", {}).should ==
244
265
  {:name=>"foo bar", :notes_dn=>"CN=foo bar/OU=here/O=there"}
245
266
  end
246
267
 
247
268
  it "should process_address the inet_addr if the inet_address is not '.'" do
248
- NotesStructuredTextJsonMessages.process_address_pair('"foo bar" <foo@bar.com>', "CN=foo bar/OU=here/O=there").should ==
269
+ NotesStructuredTextJsonMessages.process_address_pair('"foo bar" <foo@bar.com>', "CN=foo bar/OU=here/O=there", {}).should ==
249
270
  {:name=>"foo bar", :email_address=>"foo@bar.com"}
250
271
  end
251
272
  end
@@ -255,12 +276,13 @@ EOF
255
276
  inet_field = Object.new
256
277
  notes_field = Object.new
257
278
  block = Object.new
279
+ options = {}
258
280
 
259
281
  stub(NotesStructuredTextJsonMessages).header_values(block, inet_field, :split_rfc822_addresses){["foo", "bar"]}
260
282
  stub(NotesStructuredTextJsonMessages).header_values(block, notes_field, :split_rfc822_addresses){["foo"]}
261
283
 
262
284
  lambda {
263
- NotesStructuredTextJsonMessages.process_addresses(block, inet_field, notes_field)
285
+ NotesStructuredTextJsonMessages.process_addresses(block, inet_field, notes_field, options)
264
286
  }.should raise_error(/does not match/)
265
287
  end
266
288
 
@@ -268,20 +290,22 @@ EOF
268
290
  inet_field = Object.new
269
291
  notes_field = Object.new
270
292
  block = Object.new
293
+ options={}
271
294
 
272
295
  stub(NotesStructuredTextJsonMessages).header_values(block, inet_field, :split_rfc822_addresses){["foo.mcfoo@foo.com", "bar.mcbar@bar.com"]}
273
296
  stub(NotesStructuredTextJsonMessages).header_values(block, notes_field, :split_rfc822_addresses){["CN=foo mcfoo/OU=main/O=foo", "CN=bar mcbar/OU=main/O=bar"]}
274
297
 
275
- mock(NotesStructuredTextJsonMessages).process_address_pair("foo.mcfoo@foo.com", "CN=foo mcfoo/OU=main/O=foo")
276
- mock(NotesStructuredTextJsonMessages).process_address_pair("bar.mcbar@bar.com", "CN=bar mcbar/OU=main/O=bar")
298
+ mock(NotesStructuredTextJsonMessages).process_address_pair("foo.mcfoo@foo.com", "CN=foo mcfoo/OU=main/O=foo", options)
299
+ mock(NotesStructuredTextJsonMessages).process_address_pair("bar.mcbar@bar.com", "CN=bar mcbar/OU=main/O=bar", options)
277
300
 
278
- NotesStructuredTextJsonMessages.process_addresses(block, inet_field, notes_field)
301
+ NotesStructuredTextJsonMessages.process_addresses(block, inet_field, notes_field, options)
279
302
  end
280
303
 
281
304
  it "should call process_address if an inet header is present" do
282
305
  inet_field = Object.new
283
306
  notes_field = Object.new
284
307
  block = Object.new
308
+ options={}
285
309
 
286
310
  stub(NotesStructuredTextJsonMessages).header_values(block, inet_field, :split_rfc822_addresses){["foo.mcfoo@foo.com", "bar.mcbar@bar.com"]}
287
311
  stub(NotesStructuredTextJsonMessages).header_values(block, notes_field, :split_rfc822_addresses){nil}
@@ -289,13 +313,14 @@ EOF
289
313
  mock(NotesStructuredTextJsonMessages).process_address("foo.mcfoo@foo.com")
290
314
  mock(NotesStructuredTextJsonMessages).process_address("bar.mcbar@bar.com")
291
315
 
292
- NotesStructuredTextJsonMessages.process_addresses(block, inet_field, notes_field)
316
+ NotesStructuredTextJsonMessages.process_addresses(block, inet_field, notes_field, options)
293
317
  end
294
318
 
295
319
  it "should call process_address if a notes header is present" do
296
320
  inet_field = Object.new
297
321
  notes_field = Object.new
298
322
  block = Object.new
323
+ options={}
299
324
 
300
325
  stub(NotesStructuredTextJsonMessages).header_values(block, inet_field, :split_rfc822_addresses){nil}
301
326
  stub(NotesStructuredTextJsonMessages).header_values(block, notes_field, :split_rfc822_addresses){["CN=foo mcfoo/OU=main/O=foo", "CN=bar mcbar/OU=main/O=bar"]}
@@ -303,7 +328,7 @@ EOF
303
328
  mock(NotesStructuredTextJsonMessages).process_address("CN=foo mcfoo/OU=main/O=foo")
304
329
  mock(NotesStructuredTextJsonMessages).process_address("CN=bar mcbar/OU=main/O=bar")
305
330
 
306
- NotesStructuredTextJsonMessages.process_addresses(block, inet_field, notes_field)
331
+ NotesStructuredTextJsonMessages.process_addresses(block, inet_field, notes_field, options)
307
332
  end
308
333
 
309
334
  end
@@ -320,7 +345,7 @@ EOF
320
345
  output_stream = Object.new
321
346
  mock(output_stream).<<(json_struct.to_json){output_stream}
322
347
 
323
- mock(File).open("/a/b/c/d/#{MD5.hexdigest("foo123@foo.com")}", "w") do |fn,m,block|
348
+ mock(File).open("/a/b/c/d/#{MD5.hexdigest("foo123@foo.com")}.json", "w") do |fn,m,block|
324
349
  block.call(output_stream)
325
350
  end
326
351
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: notes-structured-text-json-messages
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 1
10
- version: 0.1.1
9
+ - 4
10
+ version: 0.1.4
11
11
  platform: ruby
12
12
  authors:
13
13
  - craig mcmillan
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-04-26 00:00:00 +01:00
18
+ date: 2011-04-27 00:00:00 +01:00
19
19
  default_executable: notes_structured_text_json_messages
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency