Initial checkin on Exim module
authorJamie Cameron <jcameron@webmin.com>
Fri, 21 Mar 2008 22:24:05 +0000 (22:24 +0000)
committerJamie Cameron <jcameron@webmin.com>
Fri, 21 Mar 2008 22:24:05 +0000 (22:24 +0000)
exim/CHANGELOG [new file with mode: 0644]
exim/config.info [new file with mode: 0644]
exim/exim-lib.pl [new file with mode: 0644]
exim/install_check.pl [new file with mode: 0644]
exim/module.info [new file with mode: 0644]

diff --git a/exim/CHANGELOG b/exim/CHANGELOG
new file mode 100644 (file)
index 0000000..b6b924a
--- /dev/null
@@ -0,0 +1,2 @@
+---- Changes since 1.400 ----
+First version of this module, thanks to Bill Moyers and John Gray.
diff --git a/exim/config.info b/exim/config.info
new file mode 100644 (file)
index 0000000..18bf360
--- /dev/null
@@ -0,0 +1,8 @@
+exim_dir=Exim directory,0
+exim_virt_dir=Exim aliases directory,0
+exim_addrfile=Exim local domains file,3,
+exim_aliasfileext=Exim domain alias file extension,3,
+exim_dbmfile=Exim local domains file,3,
+exim_dbmext=Exim local domain mapping extension,3,
+mail_system=Create mbox or maildir for new users?,1
+exim_mail_file=Name of mbox file or maildir directory,0
diff --git a/exim/exim-lib.pl b/exim/exim-lib.pl
new file mode 100644 (file)
index 0000000..1014cd6
--- /dev/null
@@ -0,0 +1,326 @@
+# exim-lib.pl
+# Common functions for parsing exim config files
+
+do '../web-lib.pl';
+&init_config();
+do '../ui-lib.pl';
+use Tie::File;
+
+$exim_virt_dir = "$config{'exim_virt_dir'}";
+
+$config{'exim_aliasfileextre'} = "$config{'exim_aliasfileext'}";
+$config{'exim_aliasfileextre'} =~ s/\./\\./g;
+
+# user_mail_file(&user)
+# get mbox/maildir name
+sub user_mail_file
+{
+       my ($user) = @_;
+       if( !$user->{'home'} )
+       { return 0; }
+
+       return "$user->{'home'}/$config{'exim_mail_file'}";
+}
+
+# remove_domain(&domain)
+# Remove exim data regarding the domain
+sub remove_domain($)
+{
+       my ($domain) = @_;
+
+       # remove alias file
+       my $file = &alias_path($domain);
+       `rm $file`;
+
+       if( $config{'exim_dbmfile'} )
+       {
+               # remove local_domains entry
+               &process_file(op=>'delete',
+                       file=>$config{'exim_dbmfile'},
+                       pat=>"^\\*\\.$domain:",
+                       onlyFirst=>1);
+
+               # remove dbm file
+               my $file = &alias_path($domain,1);
+               if( -e $file )
+               { `rm $file`; }
+       }
+}
+
+# add_local_domain(&domain)
+# Add a local domain
+sub add_local_domain($)
+{
+       my ($domain) = @_;
+
+       if( $config{'exim_dbmfile'} )
+       {
+               open( LD, ">>$config{'exim_dbmfile'}" );
+               print LD "*.$domain:\t".&alias_path($domain,1)."\n";
+               close( LD );
+       }
+}
+
+# alias_path(&domain,[dbm])
+# Return path to an alias file
+sub alias_path($)
+{
+       my ($domain,$dbm) = @_;
+       if( $dbm )
+       { return "$exim_virt_dir/$domain$config{'exim_dbmext'}"; }
+       else
+       { return "$exim_virt_dir/$domain$config{'exim_aliasfileext'}"; }
+}
+
+# create_aliases_file(&domain)
+# Creates an exim alias file
+sub create_aliases_file($)
+{
+       my($domain) = shift(@_);
+
+       $file = &alias_path($domain);
+
+       if ( ! -e $file )
+    {
+        open(CONF,"> $file");
+        print CONF <<EOF;
+
+*: :fail: That user does not exist.
+EOF
+               close(CONF);
+       }
+}
+
+# create_alias(&alias)
+# Creates a new exim alias
+sub create_alias
+{
+       local $alias = $_[0]->{'name'};
+       local $domain = $_[0]->{'dom'};
+       local $to = $_[0]->{'values'};
+
+
+    local $tos;
+       for (@$to)
+       { s/^\\+//; }                       
+       $tos = join(',',@$to);
+
+       &create_aliases_file($domain);
+    
+       &process_file(op=>"insertBefore",
+               file=>&alias_path($domain),
+               pat=>"^\\*:",
+               text=>"$alias:\t$tos",
+               onlyFirst=>1);
+
+       # update email-addresses
+       if( $alias =~ /\@/ )
+       { return; }
+
+       if( $config{'exim_addrfile'} )
+       {
+               local $em = `cat $config{'exim_addrfile'}`;
+
+               if( !($em =~ /@$to[0]\t/) )
+               {
+                       &process_file(op=>"insertBefore",
+                   file=>$config{'exim_addrfile'},
+                   text=>"@$to[0]\t$alias\@$domain" );
+               }
+       }
+}
+
+# modify_alias(&old, &alias)
+# Modifies an existing exim alias
+sub modify_alias(&old, &alias)
+{
+       &delete_alias($_[0]);
+       &create_alias($_[1]);
+}
+
+# delete_alias(&alias)
+# Deletes an existing exim alias file
+sub delete_alias
+{
+       local $alias = $_[0]->{'name'};
+       local $domain = $_[0]->{'dom'};
+
+       &process_file(op=>"delete",
+               file=>&alias_path($domain),
+               pat=>"^$alias\[:\\s\]",
+               onlyFirst=>1);
+
+       if( $config{'exim_addrfile'} )
+       {
+               &process_file(op=>"delete",
+               file=>$config{'exim_addrfile'},
+               pat=>"\\t\\S*\@$domain\$" );
+       }
+}
+
+# list_virtusers
+# Go through exim alias files and build list of users.
+sub list_virtusers
+{
+       opendir(DIR,$exim_virt_dir);
+       @files = sort(grep(/$config{'exim_aliasfileextre'}$/,readdir(DIR)));
+       closedir(DIR);
+
+       local $num = 1;
+
+       local (@virts);
+
+       $all_data = "";
+       foreach $file (@files) {
+               $file =~ /^(.*)$config{'exim_aliasfileextre'}/;
+               $domain = $1;
+               $file_line = 1;
+               open(FILE,"$exim_virt_dir/$file") || die("Could not find $file. $!");
+               while ( <FILE> )
+               {
+                       if ( /^([^\*\#\s:]+):?\s+(.*)$/ )
+                       {
+                               $lhs = $1;
+                               $rhs = $2;
+                               if ( $rhs =~ /mailman/ )
+                               {
+                                       #print $line;
+                               }
+                               else
+                               {
+                                       if ( $rhs ne "dummyspamaccount" )
+                                       {
+                                               my $from = "$lhs\@$domain";
+                                               local @tos = split(/,/,$rhs);
+                                               local %rv = ( 'from' => $from,
+                                                                               'cmt' => undef);
+
+                                               local %virt = ( 'number' => $num++,
+                                                                               'value' => @tos,
+                                                                               'file' => "$dir/$file",
+                                                                               'name' => $from,
+                                                                               'cmt' => undef,
+                                                                               'eline' => $file_line,
+                                                                               'map_file' => "$dir/$file",
+                                                                               'line' => $file_line);
+
+                                               $rv{'virt'} = \%virt;
+                                               $rv{'to'} = \@tos;
+                                               push(@virts, \%rv);
+                                       }
+                               }
+                       }
+                       $file_line++;
+               }
+               close(FILE);
+       }
+       return @virts;
+}
+
+# process_file(...)
+# Go through lines of a file and do various operations based on regexp
+# matching.
+sub process_file
+{
+       my(%args) = @_;
+       
+       my $hitunless = 0;
+       my $inrange = 0;
+       my $endfound = 0;
+       my $operation = $args{'op'};
+       my $file = $args{'file'};
+       my $pattern = $args{'pat'};
+       my $cc = defined $args{'cc'} ? $args{'cc'} : "#"; 
+
+       my $opCount = 0;
+       if ( $operation eq "uncomment" )
+       {
+               $pattern = "^$cc.*" . $pattern;
+       }
+       
+       my $tie_obj =
+       tie my @contents, 'Tie::File', $file || die "Couldn't open $file: $!.  Exiting...\n";
+       $tie_obj->flock;
+
+       my $i=0;
+       my $skip = 0;
+       for ( @contents )
+       {
+               if ( $skip == 1 )
+               {
+                       $skip = 0;
+                       next;
+               }
+               if ( defined($args{'startrange'}) && defined($args{'endrange'}) && $_ =~ /$args{'startrange'}/ )
+               {
+                       $inrange = 1;
+               }
+               if ( defined($args{'endrange'}) && $_ =~ /$args{'endrange'}/ )
+               {
+                       $endfound = 1;
+               }
+               if ( defined($args{'unless'}) && $_ =~ /$args{'unless'}/ )
+               {
+                       $hitunless = 1;
+                       last;
+               }
+
+               if ( ( defined($pattern) && $_ =~ /$pattern/ ) || $inrange == 1 )
+               {
+                       if ( $operation eq "comment" )
+                       {
+                               s/$_/$cc $&/;
+                               $opCount++;
+                       }
+                       elsif ( $operation eq "uncomment" )
+                       {
+               s/$cc\s?//;
+                               $opCount++;
+                       }
+                       elsif ( $operation eq "delete" )
+                       {
+                               splice(@contents,$i,1);
+                               $opCount++;
+                               if ( $endfound == 1 )
+                               {
+                                       $inrange = 0;
+                                       $endfound = 0;
+                               }
+                               redo if ( ( !defined($args{'onlyFirst'}) || $inrange == 1 ) && $#contents != -1 );
+                       }
+                       elsif ( $operation eq "insertBefore" )
+                       {
+                               splice(@contents,$i,0,$args{'text'});
+                               $opCount++;
+                               $skip++;
+                       }
+                       elsif ( $operation eq "replace" )
+                       {
+                               $_ = $args{'text'};
+                               $opCount++;
+                       }
+                       if ( defined $args{'onlyFirst'} )
+                       {
+                               last;
+                       }
+               }
+               if ( $endfound == 1 )
+               {
+                       $inrange = 0;
+                       $endfound = 0;
+               }
+               $i++;
+       }
+
+       if ( $operation eq "insertBefore" && $opCount == 0 && $hitunless == 0 )
+       {
+               push(@contents, $args{'text'}); 
+       }
+       
+       untie @contents;
+}
+
+
+
+1;
+
diff --git a/exim/install_check.pl b/exim/install_check.pl
new file mode 100644 (file)
index 0000000..e61d856
--- /dev/null
@@ -0,0 +1,14 @@
+# install_check.pl
+
+do 'exim-lib.pl';
+
+# is_installed(mode)
+# For mode 1, returns 2 if the server is installed and configured for use by
+# Webmin, 1 if installed but not configured, or 0 otherwise.
+# For mode 0, returns 1 if installed, 0 if not
+sub is_installed
+{
+return 0 if (!-d $config{'exim_dir'});
+return $_[0] ? 2 : 1;
+}
+
diff --git a/exim/module.info b/exim/module.info
new file mode 100644 (file)
index 0000000..cb9491d
--- /dev/null
@@ -0,0 +1,3 @@
+name=Exim Mail Server
+category=servers
+hidden=1