Commit 9d3d3f1b authored by IKEDA Soji's avatar IKEDA Soji
Browse files

Refactoring. Introduced Sympa::Aliases subclasses and obsoleted alias_manager.pl

- If value of alias_manager parameter has full path of alias_manager.pl as value, Sympa::Aliases::Template module will be used instead of invoking alias_manager.pl.
- alias_manager.pl would be removed in the future.
parent dc450f27
......@@ -153,7 +153,7 @@ Upgrading password in database
=item L<alias_manager(8)>
Manage Sympa Aliases
Manage Sympa aliases (Obsoleted)
=item L<ldap_alias_manager(8)>
......
......@@ -32,6 +32,9 @@ nobase_modules_DATA = \
Sympa.pm \
Sympa/Alarm.pm \
Sympa/Aliases.pm \
Sympa/Aliases/CheckSMTP.pm \
Sympa/Aliases/External.pm \
Sympa/Aliases/Template.pm \
Sympa/Archive.pm \
Sympa/Auth.pm \
Sympa/Bulk.pm \
......
......@@ -26,194 +26,118 @@ package Sympa::Aliases;
use strict;
use warnings;
use English qw(-no_match_vars);
BEGIN { eval 'use Net::SMTP'; }
use Conf;
use Sympa::Constants;
use Sympa::Log;
my $log = Sympa::Log->instance;
sub new {
bless {} => shift;
}
# OLd name: Sympa::Admin::list_check_smtp().
sub check {
$log->syslog('debug2', '(%s, %s, %s)', @_);
my $self = shift;
my $name = shift;
my $robot_id = shift;
my $conf = '';
my $smtp;
my $smtp_relay = Conf::get_robot_conf($robot_id, 'list_check_smtp');
my $smtp_helo = Conf::get_robot_conf($robot_id, 'list_check_helo')
|| $smtp_relay;
$smtp_helo =~ s/:[-\w]+$// if $smtp_helo;
my $suffixes = Conf::get_robot_conf($robot_id, 'list_check_suffixes');
return 0
unless $smtp_relay and $suffixes;
$log->syslog('debug2', '(%s, %s)', $name, $robot_id);
my @suf = split /\s*,\s*/, $suffixes;
return 0 unless @suf; #FIXME
my @addresses = (
$name . '@' . $robot_id,
map { $name . '-' . $_ . '@' . $robot_id } @suf
);
unless ($Net::SMTP::VERSION) {
$log->syslog('err',
'Unable to use Net library, Net::SMTP required, install it first'
);
return undef;
}
if ($smtp = Net::SMTP->new(
$smtp_relay,
Hello => $smtp_helo,
Timeout => 30
)
) {
$smtp->mail('');
foreach my $address (@addresses) {
$conf = $smtp->to($address);
last if $conf;
}
$smtp->quit();
return $conf;
}
return undef;
}
# Old name: Sympa::Admin::install_aliases().
sub add {
$log->syslog('debug', '(%s, %s)', @_);
my $self = shift;
my $list = shift;
return 1
if lc Conf::get_robot_conf($list->{'domain'}, 'sendmail_aliases') eq
'none';
my $alias_manager = $Conf::Conf{'alias_manager'};
$log->syslog('debug2', '%s add %s %s', $alias_manager, $list->{'name'},
$list->{'admin'}{'host'});
unless (-x $alias_manager) {
$log->syslog('err', 'Failed to install aliases: %m');
return undef;
my $class = shift;
my $type = shift;
my %options = @_;
return undef unless $type;
# Special cases:
# - To disable aliases management, specify "none" as $type.
# - "External" module is used for full path to program.
# - However, "Template" module is used instead of obsoleted program
# alias_manager.pl.
return bless {} => $class if $type eq 'none';
if ($type eq Sympa::Constants::SBINDIR() . '/alias_manager.pl') {
$type = 'Sympa::Aliases::Template';
} elsif (0 == index $type, '/' and -x $type) {
$options{program} = $type;
$type = 'Sympa::Aliases::External';
}
#FIXME: 'host' parameter is passed to alias_manager: no 'domain'
# parameter to determine robot.
my $status =
system($alias_manager, 'add', $list->{'name'},
$list->{'admin'}{'host'}) >> 8;
if ($status == 0) {
$log->syslog('info', 'Aliases installed successfully');
return 1;
}
if ($status == 1) {
$log->syslog('err', 'Configuration file %s has errors',
Conf::get_sympa_conf());
} elsif ($status == 2) {
$log->syslog('err',
'Internal error: Incorrect call to alias_manager');
} elsif ($status == 3) {
# Won't occur
$log->syslog('err',
'Could not read sympa config file, report to httpd error_log');
} elsif ($status == 4) {
# Won't occur
$log->syslog('err',
'Could not get default domain, report to httpd error_log');
} elsif ($status == 5) {
$log->syslog('err', 'Unable to append to alias file');
} elsif ($status == 6) {
$log->syslog('err', 'Unable to run newaliases');
} elsif ($status == 7) {
$log->syslog('err',
'Unable to read alias file, report to httpd error_log');
} elsif ($status == 8) {
$log->syslog('err',
'Could not create temporay file, report to httpd error_log');
} elsif ($status == 13) {
$log->syslog('info', 'Some of list aliases already exist');
} elsif ($status == 14) {
$log->syslog('err',
'Can not open lock file, report to httpd error_log');
} elsif ($status == 15) {
$log->syslog('err', 'The parser returned empty aliases');
} else {
$log->syslog('err', 'Unknown error %s while running alias manager %s',
$status, $alias_manager);
# Returns appropriate subclasses.
if ($type !~ /[^\w:]/) {
$type = sprintf 'Sympa::Aliases::%s', $type unless $type =~ /::/;
unless (eval sprintf('require %s', $type)
and $type->isa('Sympa::Aliases')) {
$log->syslog(
'err', 'Unable to use %s module: %s',
$type, $EVAL_ERROR || 'Not a Sympa::Aliases class'
);
return undef;
}
return bless {%options} => $type;
}
return undef;
}
# Old names: Sympa::Admin::remove_aliases() & Sympa::List::remove_aliases().
sub del {
$log->syslog('info', '(%s, %s)', @_);
my $self = shift;
my $list = shift;
sub check {0}
return 1
if lc Conf::get_robot_conf($list->{'domain'}, 'sendmail_aliases') eq
'none';
sub add {0}
my $alias_manager = $Conf::Conf{'alias_manager'};
unless (-x $alias_manager) {
$log->syslog('err', 'Cannot run alias_manager %s', $alias_manager);
return undef;
}
my $status =
system($alias_manager, 'del', $list->{'name'},
$list->{'admin'}{'host'}) >> 8;
if ($status == 0) {
$log->syslog('info', 'Aliases for list %s removed successfully',
$list);
return 1;
} else {
$log->syslog('err', 'Failed to remove aliases; status %d: %m',
$status);
return undef;
}
}
sub del {0}
1;
__END__
=encoding utf-8
=head1 NAME
=head1 NAME
Sympa::Aliases - Base class for alias management
=head1 SYNOPSIS
package Sympa::Aliases::FOO;
use base qw(Sympa::Aliases);
sub check { ... }
sub add { ... }
sub del { ... }
1;
=head1 DESCRIPTION
TBD.
This module is the base class for subclasses to manage list aliases of Sympa.
=head2 Methods
=over
=item new ( )
=item new ( $type, [ key =E<gt> value, ... ] )
I<Constructor>.
Creates new instance of L<Sympa::Aliases>.
Returns one of appropriate subclasses according to $type:
=over
=item C<'none'>
No aliases management.
=item Full path to executable
Use external program to manage aliases.
See L<Sympa::Aliases::External>.
=item Name of subclass
Use a subclass C<Sympa::Aliases::I<name>> to manage aliases.
=back
For invalid types returns C<undef>.
Optional C<I<key> =E<gt> I<value>> pairs are included in the instance as
hash entries.
=item check ($listname, $robot_id)
I<Instance method>.
Checks if the requested list exists already using SMTP 'rcpt to'.
I<Instance method>, I<overridable>.
Checks if the addresses of requested list exist already.
Parameters:
......@@ -231,11 +155,15 @@ List's robot.
Returns:
L<Net::SMTP> object or false value.
True value if one of addresses exists.
C<0> if none found.
C<undef> if something wrong happened.
By default, this method always returns C<0>.
=item add ($list)
I<Instance method>.
I<Instance method>, I<overridable>.
Installs aliases for the list $list.
Parameters:
......@@ -250,11 +178,15 @@ An instance of L<Sympa::List>.
Returns:
C<undef> if not applicable or aliases not installed. or C<1> if OK.
C<1> if installation succeeded.
C<0> if there were no aliases to be installed.
C<undef> if not applicable.
By default, this method always returns C<0>.
=item del ($list)
I<Instance method>.
I<Instance method>, I<overridable>.
Removes aliases for the list $list.
Parameters:
......@@ -269,11 +201,20 @@ An instance of L<Sympa::List>.
Returns:
C<undef> if not applicable. C<1> (if ok) or concated string of alias not
removed.
C<1> if removal succeeded.
C<0> if there were no aliases to be removed.
C<undef> if not applicable.
By default, this method always returns C<0>.
=back
=head1 SEE ALSO
L<Sympa::Aliases::CheckSMTP>,
L<Sympa::Aliases::External>,
L<Sympa::Aliases::Template>.
=head1 HISTORY
F<alias_manager.pl> as a program to automate alias management appeared on
......
# -*- indent-tabs-mode: nil; -*-
# vim:ft=perl:et:sw=4
# $Id$
# Sympa - SYsteme de Multi-Postage Automatique
#
# Copyright 2017 The Sympa Community. See the AUTHORS.md file at the top-level
# directory of this distribution and at
# <https://github.com/sympa-community/sympa.git>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
package Sympa::Aliases::CheckSMTP;
use strict;
use warnings;
BEGIN { eval 'use Net::SMTP'; }
use Conf;
use Sympa::Log;
use base qw(Sympa::Aliases);
my $log = Sympa::Log->instance;
# Old name: Sympa::Admin::list_check_smtp().
sub check {
$log->syslog('debug2', '(%s, %s, %s)', @_);
my $self = shift;
my $name = shift;
my $robot_id = shift;
my $smtp_relay = Conf::get_robot_conf($robot_id, 'list_check_smtp');
return 0 unless defined $smtp_relay and length $smtp_relay;
my $smtp_helo = Conf::get_robot_conf($robot_id, 'list_check_helo')
|| $smtp_relay;
$smtp_helo =~ s/:[-\w]+$// if $smtp_helo;
my $suffixes = Conf::get_robot_conf($robot_id, 'list_check_suffixes');
return 0
unless $smtp_relay and $suffixes;
$log->syslog('debug2', '(%s, %s)', $name, $robot_id);
my @suf = split /\s*,\s*/, $suffixes;
return 0 unless @suf; #FIXME
my @addresses = (
$name . '@' . $robot_id,
map { $name . '-' . $_ . '@' . $robot_id } @suf
);
unless ($Net::SMTP::VERSION) {
$log->syslog('err',
'Unable to use Net library, Net::SMTP required, install it first'
);
return undef;
}
if (my $smtp = Net::SMTP->new(
$smtp_relay,
Hello => $smtp_helo,
Timeout => 30
)
) {
$smtp->mail('');
my $conf = 0;
foreach my $address (@addresses) {
$conf = $smtp->to($address);
last if $conf;
}
$smtp->quit();
return $conf;
}
return undef;
}
1;
__END__
=encoding utf-8
=head1 NAME
Sympa::Aliases::CheckSMTP - Alias management: Check addresses using SMTP
=head1 SYNOPSIS
use Sympa::Aliases;
my $aliases = Sympa::Aliases->new('CheckSMTP');
$aliases->check('listname', 'domain');
=head1 DESCRIPTION
TBD.
=head2 Methods
=over
=item check ($listname, $robot_id)
I<Instance method>.
Checks if the requested list exists already using SMTP 'RCPT TO'.
Parameters:
=over
=item $listname
Name of the list.
=item $robot_id
List's robot.
=back
Returns:
Instance of L<Net::SMTP> class or false value.
=back
=head2 Configuration parameters
Following parameters in F<sympa.conf> or F<robot.conf> are referred by
this module.
=over
=item list_check_helo
SMTP HELO (EHLO) parameter used for address verification.
Default value is the host part of C<list_check_smtp> parameter.
=item list_check_smtp
SMTP server to verify existence of the same addresses as the list.
=item list_check_suffixes
List of suffixes used for list addresses.
=back
=head1 SEE ALSO
L<Sympa::Aliases>.
=head1 HISTORY
The feature which allows Sympa to check listname on SMTP server
before list creation, contributed by Sergiy Zhuk, appeared on Sympa 3.3.
C<list_check_helo> parameter was added by S. Ikeda on Sympa 6.1.5.
L<Sympa::Aliases::CheckSMTP> as a separate module appeared on Sympa 6.2.23b.
=cut
# -*- indent-tabs-mode: nil; -*-
# vim:ft=perl:et:sw=4
# $Id$
# Sympa - SYsteme de Multi-Postage Automatique
#
# Copyright 2017 The Sympa Community. See the AUTHORS.md file at the top-level
# directory of this distribution and at
# <https://github.com/sympa-community/sympa.git>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
package Sympa::Aliases::External;
use strict;
use warnings;
use English qw(-no_match_vars);
use Conf;
use Sympa::Log;
use base qw(Sympa::Aliases::CheckSMTP);
my $log = Sympa::Log->instance;
# Old name: Sympa::Admin::install_aliases().
sub add {
$log->syslog('debug', '(%s, %s)', @_);
my $self = shift;
my $list = shift;
#FIXME: 'host' parameter is passed to the program: No 'domain'
# parameter to determine robot.
my $program = $self->{program};
system($program, 'add', $list->{'name'},
$list->{'admin'}{'host'},
($self->{file} ? ($self->{file}) : ())
);
if ($CHILD_ERROR & 127) {
$log->syslog('err', '%s was terminated by signal %d',
$program, $CHILD_ERROR & 127);
return undef;
} elsif ($CHILD_ERROR) {
return _error($CHILD_ERROR >> 8, $ERRNO);
} else {
$log->syslog('info', 'Aliases for list %s installed successfully',
$list);
return 1;
}
}
# Old names: Sympa::Admin::remove_aliases() & Sympa::List::remove_aliases().
sub del {
$log->syslog('info', '(%s, %s)', @_);
my $self = shift;
my $list = shift;
#FIXME: 'host' parameter is passed to the program: No 'domain'
# parameter to determine robot.
my $program = $self->{program};
system($program, 'del', $list->{'name'},
$list->{'admin'}{'host'},
($self->{file} ? ($self->{file}) : ())
);
if ($CHILD_ERROR & 127) {
$log->syslog('err', '%s was terminated by signal %d',
$program, $CHILD_ERROR & 127);
return undef;
} elsif ($CHILD_ERROR) {
return _error($CHILD_ERROR >> 8, $ERRNO);
} else {
$log->syslog('info', 'Aliases for list %s removed successfully',
$list);
return 1;
}
}
use constant ERR_CONFIG => 1;
use constant ERR_PARAMETER => 2;
use constant ERR_WRITE_ALIAS => 5;
use constant ERR_NEWALIASES => 6;
use constant ERR_READ_ALIAS => 7;
use constant ERR_CREATE_TEMP => 8;
use constant ERR_ALIAS_EXISTS => 13;
use constant ERR_LOCK => 14;
use constant ERR_ALIASES_EMPTY => 15;
use constant ERR_OTHER => 127;
sub _error {
my $status = shift;
my $errno = shift;
unless ($status) {
$log->syslog('info', 'Aliases installed successfully');
return 1;