infused (owner)

Revisions

gist: 117010 Download_button fork
public
Description:
Exchange 2003 log analyzer
Public Clone URL: git://gist.github.com/117010.git
Ruby
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
#!/usr/bin/env ruby
 
require 'optparse'
require 'ostruct'
require 'parsedate'
 
@my_args = ARGV.empty? ? [ "-h" ] : ARGV
 
@options = OpenStruct.new
opts = OptionParser.new
opts.on("-d","--directory DIRECTORY", String, "Directory full of log files to parse") { |val| @options.dir = val }
opts.on("-t","--to ADDRESS", String, "Find emails sent to a specific address") { |val| @options.to = val }
opts.on("-f","--from ADDRESS", String, "Find email sent from a specific address") { |val| @options.from = val }
opts.on("-s","--show-detail", "Output detail instead of summary information") { |val| @options.detail = val }
opts.on("-z=","--time-zone=", "Offset in hours from UTC") { |val| @options.tz }
opts.on_tail("-h", "--help", "Show this message") do
  puts opts
  exit
end
opts.parse!(@my_args)
 
puts "Exchange 2003 Log Analyzer v.1\n" if !@options.detail
puts "Finding all messages sent to: '#{@options.to}'" if @options.to && !@options.detail
puts "Finding all messages sent from: '#{@options.from}'" if @options.from && !@options.detail
 
@smtp_in = 0
@smtp_out = 0
@local_deliver = 0
@msgids = Array.new
@options.tz = -7 if !@options.tz
 
# this function calculates the various statistics -
# messages are tracked so that they are not counted more than once
def process_line(line)
  msgid = line[/^([^\t]+\t){9}([^\t]+)/, 2]
  
  if !@msgids.index(msgid)
    if line =~ /^([^\t]+\t){8}1019/ then @smtp_in += 1
    elsif line =~ /^([^\t]+\t){8}1031/ then @smtp_out += 1
    elsif line =~ /^([^\t]+\t){8}1023/ then @local_deliver += 1
    else
      # make sure that the current msgid is not added to the msgids array
      return
    end
    
    # we only keep track of the last 50 msgid's processed -
    # this should be sufficient to ensure an accurate record count
    @msgids << msgid
    @msgids.shift if @msgids.length > 50
    
    # dump detail information to standard output if the -s flag is set
    if @options.detail
      sdate, stime = line.match(/^([\d]{4}-[\d]{1,2}-[\d]{1,2})\t([\d]{1,2}:[\d]{1,2}:[\d]{1,2})/).captures
      res = ParseDate.parsedate(sdate + ' ' + stime)
      utc = Time.utc(*res)
      local = utc - (@options.tz * 60 * 60)
      datestr = local.strftime('%m-%d-%Y %I:%M:%S %p')
      
      data = line.split("\t")
      puts '"'+datestr+'","'+data[19]+'","'+data[7]+'","'+data[18]+'"'
    end
  end
end
 
# process each .log file in the directory
Dir.glob(@options.dir+'/*.log') do |entry|
  puts "Processing file: #{entry}\n" if !@options.detail
  if @options.to && @options.from
    regexp_to = /^([^\t]+\t){7}#{@options.to}/
    regexp_from = /^([^\t]+\t){19}#{@options.from}/
    File.open(entry, 'r').grep(regexp_to).grep(regexp_from) { |line| process_line(line) }
  elsif @options.to
    regexp = /^([^\t]+\t){7}#{@options.to}/
    File.open(entry, 'r').grep(regexp) { |line| process_line(line) }
  elsif @options.from
    regexp = /^([^\t]+\t){19}#{@options.from}/
    File.open(entry, 'r').grep(regexp) { |line| process_line(line) }
  else
    File.open(entry, 'r').each { |line| process_line(line) }
  end
end
 
puts "#{@smtp_in} inbound total"
puts "#{@smtp_out} outbound total"
puts "#{@local_deliver} local messages"