Aliases file Migration

The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

This script will parse a sendmail style aliases file including any aliases that are in an ":include:" directive. If you have appropriate comments in the included file they will be placed in the LDAP attributes of the distribution list object.

#!/usr/bin/perl
################################################################################
# $Id: aliases2zmprov,v 1.4 2007/03/07 22:18:56 dlbewley Exp $
#-------------------------------------------------------------------------------
# Description:
#   Tool to create commands suitable for zmprov from a unix aliases file.
#
#   Handles the case of an :include: construct.
#   - Comments in include file are parsed as follows
#   - "Foo" goes in LDAP description attribute, "Bar" in the displayname.
#     # Description: foo
#     # Name: Bar
#
#   Handles the case of remote and multiple recipients by making a dist list.
#   - A Zimbra alias must be associated with exactly one Zimbra account.
#   - A Zimbra distribution list may contain users on remote hosts.
#
# See Also:
#   http://wiki.zimbra.com/index.php?title=Bulk_Create
#
# Usage:
#    ./aliases2zmprov /etc/aliases 1> aliases.zmp 2> aliases.err
#    zmprov < aliases.zmp
#
################################################################################

my @CNAME_SKIP= qw( ftp news postmaster root webmaster );
my @ALIAS_SKIP= qw( abuse mailer-daemon postmaster  );
my @DISTRIBUTION_LISTS;
my $DOMAIN = 'foo.bar.com';
my $SOURCE_HOST = 'mail';

use File::Basename;

while(<>) {
    chomp;
    s/#.*$//; # skip comments
    next if /^\s*$/; # skip blank lines

    my ($description,$display_name,@cnames);
    my ($alias,$cname) = split(/:/,$_,2);

    $alias =~ s/\s*//g;
    # scrutinize the aliases
    if (grep /^$alias$/, @ALIAS_SKIP) {
        warn "skipping alias $alias -> $cname";
        next;
	}

    $cname =~ s/\s*//g; # remove all spaces

    # scrutinize the canonical names
    if ($cname =~ m/:include:/) {
        (($description, $display_name, $cnames_ref) = parse_include($cname)) || next;
        @cnames = @{$cnames_ref};
    }
    if ($cname =~ m/,/) {
        # multiple recipients make this a list instead of an alias
        @cnames = split(/,/,$cname);
    }

    # if more than one cname then it is a dist list
    if (length($cnames[0])) {
        print "\n";
        print "createDistributionList $alias\@$DOMAIN\n";
        push (@DISTRIBUTION_LISTS, $alias);
        if ($display_name) {
            print "modifyDistributionList $alias\@$DOMAIN displayname \"$display_name\"\n";
            $display_name = undef;
        }
        if ($description) {
            print "modifyDistributionList $alias\@$DOMAIN description \"$description\"\n";
            $description = undef;
        }
        foreach my $member (@cnames) {
            # skip aliases to certain users
            if (grep /^$member$/, @CNAME_SKIP) {
                warn "skipping cname $member <- $alias";
                next; # go to next member
            }
            # A Zimbra distribution list may contain users on remote hosts.
            if ($member =~ m/\@/) {
                print "addDistributionListMember $alias\@$DOMAIN $member\n";
            } else {
                print "addDistributionListMember $alias\@$DOMAIN $member\@$DOMAIN\n";
            }
        }
        print "\n";
        @cnames=();
        next; # go to next line of aliases file
    } 

    # skip aliases to certain users
    if (grep /^$cname$/, @CNAME_SKIP) {
        warn "skipping cname $cname <- $alias";
        next;
	}
    if ($cname =~ m/\/|\|/) {
        # alias to a file or a program. don't try to accomodate
        warn "WARNING skipping cname $cname <- $alias it is a file or pipe";
        next;
    }

    # A Zimbra alias must be associated with exactly one Zimbra account.
    if ($cname =~ m/\@/) {
        # alias to remote host. this could be created as a dist list with 1 member
        # that seems undersirable though.
        print "\n";
        print "createDistributionList $alias\@$DOMAIN\n";
        print "addDistributionListMember $alias\@$DOMAIN $cname\n";
        print "\n";
        next; # go to next line of aliases file
    }
    # is the cname a distribution_list already?
    if (grep /^$cname$/, @DISTRIBUTION_LISTS) {
        print "addDistributionListAlias $cname\@$DOMAIN $alias\@$DOMAIN\n";
    }
    # are we sure that account $cname\@$DOMAIN exists?
    else {
        print "addAccountAlias $cname\@$DOMAIN $alias\@$DOMAIN\n";
    }
}

# read an included alias file. commens with Name: and Description:
# are placed into LDAP attributes for the list
sub parse_include {
    my $cname = shift;
    my @cnames;
    # need to pull in contents of file and make a dist
    # list instead of an alias
    my $fullfile = $cname;
    $fullfile =~ s/:include://;
    my ($file,$path) = fileparse($fullfile);
    if (! -e $file) {
        warn "WARNING skipping $alias -> $cname Please run 'scp $SOURCE_HOST:$fullfile .'";
        return; # go to next line of aliases file
    } else {
        # process include file
        open(F,$file) || warn "Can not read $file";
        while (<F>) {
            chomp;
            (m/#\s*Department:*\s*(.*)/) && ($ou = $1); # can't make use of this in zmprov mdl :(
            if (m/#\s*Description:*\s*(.*)/) {
                $description = $1;
                $description =~ s/"/'/g; # don't blow our command line
            }
            if (m/#\s*Name:*\s*(.*)/) {
                $display_name = $1;
                $display_name =~ s/"/'/g; # don't blow our command line
            }
            s/#.*$//; # skip comments
            next if /^\s*$/; # skip blank lines
            push @cnames, $_;
        }
    }
    return $description, $display_name, \@cnames;
}
# example data
__DATA__
admin: root
dudes: me,you
postmaster: sarah
wsu: :include:/etc/mail/lists/wsu.list
jon.doe: jdoe
  • Tip - Put a comma at the end of the line in the aliases file if you want to make a distribution list with one member instead of an alias! Useful if you plan on adding more members later.


Verified Against: unknown Date Created: 4/28/2009
Article ID: https://wiki.zimbra.com/index.php?title=Aliases_file_Migration Date Modified: 2015-03-24



Try Zimbra

Try Zimbra Collaboration with a 60-day free trial.
Get it now »

Want to get involved?

You can contribute in the Community, Wiki, Code, or development of Zimlets.
Find out more. »

Looking for a Video?

Visit our YouTube channel to get the latest webinars, technology news, product overviews, and so much more.
Go to the YouTube channel »

Jump to: navigation, search