#!/usr/bin/env perl
#----------------------------------------------------------------------------
# NAME 
# 	testaddr - searchs through aliases, in the same order as
#		qmail, and reports the first working alias or delivery box.
#
# SYNOPSIS
#	testaddr email_address
#
# FEEDBACK
#	The increasing functionality and usefullness of this script relies on
#	YOU, the user.  If this script does not behave in the intended way, or
#	if there is a lacking feature, please provide feedback to the author
#	of this script so that your feedback can be looked into and possibly
#	integrated into this script.
# 	
# John C. Koen 12/01/2004
# johnk@southwestern.edu
# $Id: testaddr.pl,v 1.36 2004/12/14 19:44:22 root Exp $
#----------------------------------------------------------------------------

#----------------------------------------------------------------------------
# Begin of POD 
#----------------------------------------------------------------------------

=head1 NAME

testaddr - test a local e-mail address on a qmail system

=head1 SCRIPT CATEGORIES

UNIX/System_administration
Mail/qmail

=head1 SYNOPSIS

testaddr email_address

=head1 PREREQUISITES

This script requres that QMAIL be installed on the system that
this script runs on.

=head1 COPYRIGHT

Copyright (c) 2004 John C. Koen <johnk@southwestern.edu>. All rights reserved.
This program is free software.  You may modify and/or distribute it
under the same terms as Perl itself.  This copyright notice
must remain attached to the file.

=head1 REVISION

$Id: testaddr.pl,v 1.36 2004/12/14 19:44:22 root Exp $

=head1 FEEDBACK

The increasing functionality and usefullness of this script relies on
YOU, the user.  If this script does not behave in the intended way, or
if there is a lacking feature, please provide feedback to the author
of this script so that your feedback can be looked into and possibly
integrated into this script.

=head1 README

testaddr.pl -  searchs through aliases on a B<qmail server>, in the same 
order as the qmail services, and reports the first working alias or 
delivery box.

=head1 AUTHOR

John C. Koen
johnk@southwestern.edu
http://www.southwestern.edu/~johnk

=cut
#----------------------------------------------------------------------------
# End of POD
#----------------------------------------------------------------------------

#----------------------------------------------------------------------------
# CONFIGURATION - adjust these variables to fit your system
#----------------------------------------------------------------------------

# dot-foward specific variables
my $DOT_FORWARD_ENABLE 	=	1;
my $DOT_FORWARD_BIN	=	"/var/qmail/bin/dot-forward";
my @FORWARD_FILES	=	qw(.qmail .forward);

# fastforward specific variables
my $FASTFORWARD_ENABLE 	=	0;
my $FASTFORWARD_BIN	=	"/var/qmail/bin/fastforward";
my $FASTFORWARD_DB	=	"/var/qmail/alias/aliases.cdb";

# site specific variables
my $QMAIL_PATH		=	"/var/qmail";
my $QMAIL_RC		=	"$QMAIL_PATH/rc";
my $QMAIL_CONTROL_DIR	=	"$QMAIL_PATH/control";
my $QMAIL_DD		=	"$QMAIL_CONTROL_DIR/defaultdelivery";
my $QMAIL_ALIAS_DIR	=	"$QMAIL_PATH/alias";
my $QMAIL_MAIL_DIR	=	'./Maildir/';
my $QMAIL_USER_BASE	=	"/home";
my $QMAIL_DEFAULT_DOMAIN=	
	`/bin/cat $QMAIL_CONTROL_DIR/defaultdomain|/usr/bin/xargs /bin/echo -n 2>&1` or warn "Could not open $QMAIL_CONTROL_DIR/defaultdomain.\n";

#----------------------------------------------------------------------------
# Unless you are hacking, there is no reason to modify anything below
#----------------------------------------------------------------------------

require 5;

use strict;
use warnings;
use POSIX;

use vars qw(
	%DELIVERY_LINE
);

my $PROGNAME	=	$0;

my $EMAIL_ADDRESS = 	$ARGV[0];

#----------------------------------------------------------------------------
#	Code Section
#----------------------------------------------------------------------------

#----------------------------------------------------------------------------
# Begin main logic
#----------------------------------------------------------------------------

# Explain usage if missing an argument
die usage() if (!@ARGV);

# Extract e-mail address from command argument
grab_mailbox();

# Grab delivery options from QMAIL_RC or from defaultdelivery
parse_defaultdelivery() unless parse_qmail_rc();

# Consult aliases in users home directory
check_defaultdelivery();

# Consult aliases in ~alias
check_qmail_alias();

# If enabled, consult aliases in fastforward database
if ($FASTFORWARD_ENABLE) {check_fastforward()} else {print_sorry()}

#----------------------------------------------------------------------------
# End main logic
#----------------------------------------------------------------------------

#----------------------------------------------------------------------------
#	sub usage 
#----------------------------------------------------------------------------
sub usage{

	die <<"EOT";

Usage: $PROGNAME e-mail_address

e-mail_addresses can be in the form of:
	mailbox_name
	-or-
	mailbox_name\@$QMAIL_DEFAULT_DOMAIN

EOT
}

#----------------------------------------------------------------------------
#       sub grab_mailbox
#----------------------------------------------------------------------------
sub grab_mailbox{

	# Grab the e-mail address domain, everything after the '@'
   	$EMAIL_ADDRESS =~ /.*\@(.*)/;
	my $email_domain = $1;

	# Compare e-mail domain to site_domain, be sure address is local
	if (defined($email_domain) && !($email_domain =~ m/$QMAIL_DEFAULT_DOMAIN/)) { die {&usage} }

	# Grab the mailbox name, everything before the '@'
	$EMAIL_ADDRESS =~ s/\@.*$//;
}

#----------------------------------------------------------------------------
#       sub check_defaultdelivery
#----------------------------------------------------------------------------
sub check_defaultdelivery{

	my $command;
	my $file;
	my $line;
	my $flag=0;

	foreach $command (reverse(keys(%DELIVERY_LINE)))	{
	
		if ($command =~ m/$DOT_FORWARD_BIN/) {
			foreach $file (@FORWARD_FILES) {

				if (open my $fh, "$QMAIL_USER_BASE/$EMAIL_ADDRESS/$file") {
					print "\n$EMAIL_ADDRESS\@$QMAIL_DEFAULT_DOMAIN -> $QMAIL_USER_BASE/$EMAIL_ADDRESS/$file:\n";
					while (<$fh>) {
						if ($_ =~ m/@/) {print "Delivery to: $_"; $flag=1;} elsif ($_ =~ m/^|/) {print "Program: $_";$flag=1;}
					}
					print "\n";
				}
				if ($flag == 1) {exit 1};
			}
		} elsif ($DELIVERY_LINE{$command} =~ m/$QMAIL_MAIL_DIR/) {
			if (-d "$QMAIL_USER_BASE/$EMAIL_ADDRESS/$QMAIL_MAIL_DIR") {
				print "\n$EMAIL_ADDRESS\@$QMAIL_DEFAULT_DOMAIN -> local account: $EMAIL_ADDRESS\n\n";
				exit 1;
			}
		}
	}
}

#----------------------------------------------------------------------------
#       sub check_qmail_alias
#----------------------------------------------------------------------------
sub check_qmail_alias{
	if (open my $fh,"$QMAIL_ALIAS_DIR/.qmail-$EMAIL_ADDRESS") {
		while (<$fh>) {
			print "\n$EMAIL_ADDRESS\@$QMAIL_DEFAULT_DOMAIN -> $QMAIL_ALIAS_DIR/.qmail-$EMAIL_ADDRESS:\n $_\n";
		}
		exit 1;
	}
}

#----------------------------------------------------------------------------
#       sub check_fastforward
#----------------------------------------------------------------------------
sub check_fastforward{

	my $fastforward_results = `DEFAULT=$EMAIL_ADDRESS HOST=$QMAIL_DEFAULT_DOMAIN $FASTFORWARD_BIN -nd $FASTFORWARD_DB 2>&1`;
	
	if ($fastforward_results =~ m/^from/) {
		print "\n$EMAIL_ADDRESS\@$QMAIL_DEFAULT_DOMAIN -> $FASTFORWARD_DB:\n";
		print "$fastforward_results\n";
		exit 1;
	} else {&print_sorry}

}

#----------------------------------------------------------------------------
#	sub print_sorry
#----------------------------------------------------------------------------
sub print_sorry{

	print "\nNo mailbox here by that name. (#5.1.1)\n\n";
}
#----------------------------------------------------------------------------
#       sub parse_defaultdelivery
#----------------------------------------------------------------------------
sub parse_defaultdelivery{

	my ($first_opt,$second_opt);

	if ( open my $fh, $QMAIL_DD or die "Could not open $QMAIL_DD: $!" ) {

		while (<$fh>) {

			if (/^\.\/Maildir\/$/) {last}
			# Break up the program command, from the argument
			($first_opt, $second_opt) = split /\s/, $_;
			$DELIVERY_LINE{$first_opt} = $second_opt;

		}

		close $fh;
	}

}
#----------------------------------------------------------------------------
#       sub parse_qmail_rc
#----------------------------------------------------------------------------
sub parse_qmail_rc{

	my @commands;
	my $trash;

        if ( open my $fh,$QMAIL_RC or die "Could not open $QMAIL_RC: $!" ) {

                while (<$fh>) {

			if ($_ =~ m/^qmail-start/) {
				@commands = split /[|`]/, $_;

				# Drop the first element
				shift(@commands);

				# Remove the trash from the last element
				($commands[$#commands],$trash) = split /[\'|\"]/, $commands[$#commands];
				# Remove last element, if it is blank
				if ($commands[$#commands] eq "") {pop @commands}
			}
                }

		foreach (@commands) {
			# Break up the program command, from the argument
                        $_ =~ m/(^.*) (.*$)/;
			if (($1 eq "cat") && ($2 eq $QMAIL_DD)) {
				return 0
			} else {$DELIVERY_LINE{$1} = $2}
                }

                close $fh;
        }
	return 0;
}
