Linux – Tracking down dovecot IMAP user bandwidth usage

dovecotimaplinuxscripting

One of my customers is using massive amounts of bandwidth, it appears to be related to IMAP and not their actual website.

There is a logfile /var/log/maillog which logs each IMAP connection and the amount of bytes sent/read to the client:

I'm trying to put together a little shell script that will count each users bandwidth so we can figure out which email account it is.

Oct  1 10:43:00 web1 dovecot: IMAP(user1@userdomain.com): Disconnected: Logged out bytes=363/4407
Oct  1 10:43:00 web1 dovecot: IMAP(user1@userdomain.com): Disconnected: Logged out bytes=63/492
Oct  1 10:43:00 web1 dovecot: IMAP(user2@userdomain.com): Disconnected: Logged out bytes=386/15378
Oct  1 10:43:00 web1 dovecot: IMAP(user2@userdomain.com): Disconnected: Logged out bytes=63/509
Oct  1 10:43:20 web1 dovecot: IMAP(user3@userdomain.com): Disconnected: Logged out bytes=345/3044
Oct  1 10:43:20 web1 dovecot: IMAP(user3@userdomain.com): Disconnected: Logged out bytes=63/492
Oct  1 10:43:20 web1 dovecot: IMAP(user4@userdomain.com): Disconnected: Logged out bytes=784/40163
Oct  1 10:43:20 web1 dovecot: IMAP(user4@userdomain.com): Disconnected: Logged out bytes=63/622

Logging format is:

# IMAP logout format string:
#  %i - total number of bytes read from client
#  %o - total number of bytes sent to client
#imap_logout_format = bytes=%i/%o

So it should just add both of the last fields and include the email address:

I found the following script, but I'm not using directadmin, but should be able to come up with something similar, however I've not been able to get it to work properly.

http://forum.directadmin.com/showthread.php?t=36588

Anyone have any ideas?

Thanks in advance!

Best Answer

This script might work. Well, worked for me using the example output you provided.

#!/usr/bin/python
import os
import sys
import re

logline = re.compile(".+?dovecot: IMAP\((.+?)\): Disconnected: Logged out bytes=(\d+)/(\d+)")
matched = 0
totallines = 0
results = {}

if __name__ == "__main__":
  if len(sys.argv) < 2:
    print "Need logfile to continue"

  logfile = open(sys.argv[1])
  for line in logfile.readlines():
    totallines += 1
    log = logline.match(line)
    if log:
      matched += 1
      user, inb, outb = log.group(1), int(log.group(2)), int(log.group(3))
      if user in results:
        results[user][0] += inb
        results[user][1] += outb
      else:
        results[user] = [inb, outb]
    else:
      continue

  print "Matched {0} of {1} lines".format(matched, totallines)
  for k in results.keys():
    r = results[k]
    print "{0}: {1}/{2} Total: {3}".format(k, r[0], r[1], r[0]+r[1])