+#!/usr/bin/ruby -wKU
+#
+# mailshears, to prune unused mail directories.
+#
+# Mail accounts for virtual hosts are stored in SQL, and managed by
+# Postfixadmin. However, the physical directories are handled by
+# Postfix/Dovecot and are left untouched by Postfixadmin. This is good
+# for security, but comes at a cost: Postfixadmin can't remove a
+# user's mail directory when his or her account is deleted.
+#
+# This program compares the list of filesystem accounts with the ones
+# in the database. It outputs any accounts that exist in the
+# filesystem, but not the database.
+#
+
+# We need Pathname to get the real filesystem path
+# of this script (and not, for example, the path of
+# a symlink which points to it.
+require 'pathname'
+
+# This bit of magic adds the parent directory (the
+# project root) to the list of ruby load paths.
+# Thus, our require statements will work regardless of
+# how or from where the script was run.
+executable = Pathname.new(__FILE__).realpath.to_s
+$: << File.dirname(executable) + '/../'
+
+# Load our config file.
+require 'bin/configuration'
+
+# And the necessary classes.
+require 'src/errors.rb'
+require 'src/exit_codes.rb'
+require 'src/dovecot_mailstore'
+require 'src/postfixadmin_db'
+
+dms = DovecotMailstore.new(Configuration::MAIL_ROOT)
+
+pgadb = PostfixadminDb.new(Configuration::DBHOST,
+ Configuration::DBPORT,
+ Configuration::DBOPTS,
+ Configuration::DBTTY,
+ Configuration::DBNAME,
+ Configuration::DBUSER,
+ Configuration::DBPASS)
+
+begin
+ # Get the list of accounts according to the filesystem.
+ fs_accts = dms.get_accounts_from_filesystem()
+rescue StandardError => e
+ puts "There was an error retrieving accounts from the filesystem: #{e.to_s}"
+ Kernel.exit(ExitCodes::FILESYSTEM_ERROR)
+end
+
+begin
+ # ...and according to the Postfixadmin database.
+ db_accts = pgadb.get_accounts_from_db()
+rescue DatabaseError => e
+ puts "There was an error connecting to the database: #{e.to_s}"
+ Kernel.exit(ExitCodes::DATABASE_ERROR)
+end
+
+
+# Figure out which addresses are in the filesystem, but not in the
+# database.
+difference = [fs_accts - db_accts]
+
+# Don't output any unnecessary junk. Cron might mail it to someone.
+if difference.size > 0
+ puts difference
+end