Initial commit

This commit is contained in:
Daniel Berteaud 2012-11-22 09:48:02 +01:00
commit 754accf27d
9 changed files with 689 additions and 0 deletions

10
createlinks Normal file
View File

@ -0,0 +1,10 @@
#!/usr/bin/perl -w
use esmith::Build::CreateLinks qw(:all);
panel_link('minilist','manager');
event_link("qmail-update-list", "list-create", "20");
event_link("qmail-update-list", "list-modify", "20");
event_link("qmail-delete-list", "list-delete", "20");
templates2events("/var/service/qpsmtpd/config/goodrcptto", qw(list-create list-modify list-delete));

View File

@ -0,0 +1,18 @@
#!/usr/bin/perl -w
package esmith;
use strict;
use Errno;
my $event = $ARGV [0];
my $list = $ARGV [1];
die "list name argument missing." unless defined ($list);
$list =~ s/\./:/g;
unlink "/var/qmail/alias/.qmail-$list";
unlink "/var/qmail/alias/.qmail-$list-default";
exit (0);

View File

@ -0,0 +1,53 @@
#!/usr/bin/perl -w
package esmith;
use strict;
use Errno;
use esmith::ConfigDB;
use esmith::AccountsDB;
use esmith::util;
my $c = esmith::ConfigDB->open_ro || die "Couldn't open config db\n";
my $a = esmith::AccountsDB->open_ro || die "Couldn't open accounts db\n";
my $event = $ARGV [0] || die "Event name arg missing\n";;
my @lists;
if ($ARGV[1]){
@lists = $a->get($ARGV[1]);
}
@lists = $a->get_all_by_prop(type=>'minilist')
if (scalar @lists lt 1);
foreach my $list (@lists){
my $name = $list->key;
unless ($list->prop('type') eq 'minilist'){
warn "Account $name is not a mailinglist account.\n";
next;
}
my $members = $list->prop('Members') || '';
esmith::util::processTemplate(
{
CONFREF =>
{
Members => $members,
},
TEMPLATE_PATH =>
"/var/qmail/alias/.qmail-group",
OUTPUT_FILENAME => "/var/qmail/alias/.qmail-$name",
}
);
unless (-f "/var/qmail/alias/.qmail-$name-default"){
symlink "/var/qmail/alias/.qmail-$name",
"/var/qmail/alias/.qmail-$name-default";
}
}
exit (0);

View File

@ -0,0 +1,118 @@
<lexicon lang="en-us">
<entry>
<base>MINILIST</base>
<trans>Mailing lists</trans>
</entry>
<entry>
<base>FORM_TITLE</base>
<trans>Create, modify, or remove mailing lists</trans>
</entry>
<entry>
<base>CREATE_LIST</base>
<trans>Create a new list</trans>
</entry>
<entry>
<base>DESC_NAME</base>
<trans>
The list name will be used as mail address for the list.
It needs to contains only lowercases letters, numbers, periods (.), hyphens (-) and undescores (_).
It must start with a letter or a number.
</trans>
</entry>
<entry>
<base>LABEL_NAME</base>
<trans>Name</trans>
</entry>
<entry>
<base>LABEL_DESC</base>
<trans>Description</trans>
</entry>
<entry>
<base>DESC_DESC</base>
<trans>You can enter a description for this list</trans>
</entry>
<entry>
<base>LABEL_MEMBERS</base>
<trans>Members</trans>
</entry>
<entry>
<base>DESC_MEMBERS</base>
<trans>Enter here the mail addresses which will be part of this list. One address per line. You can also enter user login.</trans>
</entry>
<entry>
<base>VALIDATE</base>
<trans>Validate</trans>
</entry>
<entry>
<base>REMOVE_LIST</base>
<trans>Remove a list</trans>
</entry>
<entry>
<base>DESC_REMOVE</base>
<trans>You are about to remove the following list. Are you sure you want to continue ?</trans>
</entry>
<entry>
<base>REMOVE</base>
<trans>Remove</trans>
</entry>
<entry>
<base>MODIFY_LIST</base>
<trans>Modify a list</trans>
</entry>
<entry>
<base>LIST_ADD</base>
<trans>Add a new list</trans>
</entry>
<entry>
<base>NO_LIST_CREATED</base>
<trans>Ther's no list configured</trans>
</entry>
<entry>
<base>LIST</base>
<trans>List</trans>
</entry>
<entry>
<base>DESCRIPTION</base>
<trans>Description</trans>
</entry>
<entry>
<base>ACTION</base>
<trans>Action</trans>
</entry>
<entry>
<base>MODIFY</base>
<trans>Modify</trans>
</entry>
<entry>
<base>CREATE_ERROR</base>
<trans>An error occured during list creation</trans>
</entry>
<entry>
<base>CREATE_SUCCESS</base>
<trans>List successfully created</trans>
</entry>
<entry>
<base>MODIFY_ERROR</base>
<trans>An error occured during list modification</trans>
</entry>
<entry>
<base>MODIFY_SUCCESS</base>
<trans>List successfully modified</trans>
</entry>
<entry>
<base>DELETE_ERROR</base>
<trans>An error occured during list removal</trans>
</entry>
<entry>
<base>DELETE_SUCCESS</base>
<trans>List successfully deleted</trans>
</entry>
<entry>
<base>INVALID_CHARS</base>
<trans>{$string} contains invalid characters</trans>
</entry>
<entry>
<base>ACCOUNT_CLASH</base>
<trans>Another account named {$string} allready exists on this system</trans>
</entry>
</lexicon>

View File

@ -0,0 +1,118 @@
<lexicon lang="fr">
<entry>
<base>MINILIST</base>
<trans>Mailing lists</trans>
</entry>
<entry>
<base>FORM_TITLE</base>
<trans>Création, modification ou suppression des listes</trans>
</entry>
<entry>
<base>CREATE_LIST</base>
<trans>Création d'une nouvelle liste</trans>
</entry>
<entry>
<base>DESC_NAME</base>
<trans>
Le nom de la liste sera utilisé comme adresse mail.
Il ne doit contenir que des lettres minuscules, des nombres, des points (.), des traits d'union (-) et des underscores (_).
Il doit commencer par une lettre ou un nombre.
</trans>
</entry>
<entry>
<base>LABEL_NAME</base>
<trans>Nom</trans>
</entry>
<entry>
<base>LABEL_DESC</base>
<trans>Description</trans>
</entry>
<entry>
<base>DESC_DESC</base>
<trans>Vous pouvez entrer une description pour cette liste</trans>
</entry>
<entry>
<base>LABEL_MEMBERS</base>
<trans>Membres</trans>
</entry>
<entry>
<base>DESC_MEMBERS</base>
<trans>Entrez ici les adresses mail membres de la liste. Une adresse par ligne. Vous pouvez aussi entrer des identifiants d'utilisateurs.</trans>
</entry>
<entry>
<base>VALIDATE</base>
<trans>Valider</trans>
</entry>
<entry>
<base>REMOVE_LIST</base>
<trans>Suppression d'une liste</trans>
</entry>
<entry>
<base>DESC_REMOVE</base>
<trans>Vous êtes sur le point de supprimer la liste suivante. Êtes-vous sûre de vouloir continuer ?</trans>
</entry>
<entry>
<base>REMOVE</base>
<trans>Supprimer</trans>
</entry>
<entry>
<base>MODIFY_LIST</base>
<trans>Modification d'une liste</trans>
</entry>
<entry>
<base>LIST_ADD</base>
<trans>Ajouter une liste</trans>
</entry>
<entry>
<base>NO_LIST_CREATED</base>
<trans>Aucune liste n'est configurée</trans>
</entry>
<entry>
<base>LIST</base>
<trans>Liste</trans>
</entry>
<entry>
<base>DESCRIPTION</base>
<trans>Description</trans>
</entry>
<entry>
<base>ACTION</base>
<trans>Action</trans>
</entry>
<entry>
<base>MODIFY</base>
<trans>Modifier</trans>
</entry>
<entry>
<base>CREATE_ERROR</base>
<trans>Une erreur est sruvenue pendant la création de la liste</trans>
</entry>
<entry>
<base>CREATE_SUCCESS</base>
<trans>La liste a été créée</trans>
</entry>
<entry>
<base>MODIFY_ERROR</base>
<trans>Une erreur est survenue durant la modification de la liste</trans>
</entry>
<entry>
<base>MODIFY_SUCCESS</base>
<trans>La liste a été modifiée</trans>
</entry>
<entry>
<base>DELETE_ERROR</base>
<trans>Une erreur est survenue durant la suppression de la liste</trans>
</entry>
<entry>
<base>DELETE_SUCCESS</base>
<trans>La liste a été supprimée</trans>
</entry>
<entry>
<base>INVALID_CHARS</base>
<trans>{$string} contient des caractères invalides</trans>
</entry>
<entry>
<base>ACCOUNT_CLASH</base>
<trans>Un autre compte nommé {$string} existe sur ce système</trans>
</entry>
</lexicon>

View File

@ -0,0 +1,17 @@
{
use esmith::AccountsDB;
$OUT = "";
my $a = esmith::AccountsDB->open_ro();
foreach my $list ($a->get_all_by_prop(type=>'minilist')){
my $key = $list->key;
if ($key =~ /\@/){
$OUT .= "$key\n";
}
else{
$OUT .= "$key\@$_\n" for (@domains);
}
}
}

View File

@ -0,0 +1,93 @@
#!/usr/bin/perl -wT
# vim: ft=xml ts=4 sw=4 et:
#----------------------------------------------------------------------
# heading : Collaboration
# description : MINILIST
# navigation : 2200 2400
#----------------------------------------------------------------------
#----------------------------------------------------------------------
# copyright (C) 2012 Firewall Services
# daniel@firewall-services.com
#
# 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, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#----------------------------------------------------------------------
use strict;
use esmith::FormMagick::Panel::minilist;
my $f = esmith::FormMagick::Panel::minilist->new();
$f->display();
__DATA__
<form title="FORM_TITLE" header="/etc/e-smith/web/common/head.tmpl" footer="/etc/e-smith/web/common/foot.tmpl">
<page name="First" pre-event="print_status_message()">
<subroutine src="show_initial()"/>
</page>
<page name="CreateList" pre-event="turn_off_buttons()"
post-event="create_list()">
<title>CREATE_LIST</title>
<description>DESC_NAME</description>
<field type="text" id="listName"
validation="validate_list_name">
<label>LABEL_NAME</label>
</field>
<field type="text" id="listDesc" validation="validate_description">
<label>LABEL_DESC</label>
<description>DESC_DESC</description>
</field>
<field type="textarea" id="members" validation="validate_list_members()"
rows="12">
<label>LABEL_MEMBERS</label>
<description>DESC_MEMBERS</description>
</field>
<subroutine src="print_button('VALIDATE')" />
</page>
<page name="Delete" pre-event="turn_off_buttons()"
post-event="delete_list()">
<title>REMOVE_LIST</title>
<field type="literal" id="listName" value="$q->param('listName')">
<label>LABEL_NAME</label>
<description>DESC_REMOVE</description>
</field>
<field type="literal" id="listDesc" value="get_description()">
<label>LABEL_DESC</label>
</field>
<field type="literal" id="members" value="get_html_members()">
<label>LABEL_MEMBERS</label>
</field>
<subroutine src="print_button('REMOVE')" />
</page>
<page name="Modify" pre-event="turn_off_buttons()"
post-event="modify_list()">
<title>MODIFY_LIST</title>
<field type="literal" id="listName" value="$q->param('listName')">
<label>LABEL_NAME</label>
</field>
<field type="text" id="listDesc" value="get_description()"
validation="validate_list_description">
<label>LABEL_DESC</label>
</field>
<field type="textarea" id="members" validation="validate_list_members()"
value="get_members()" rows="12">
<label>LABEL_MEMBERS</label>
<description>DESC_MEMBERS</description>
</field>
<subroutine src="print_button('VALIDATE')" />
</page>
</form>

View File

@ -0,0 +1,210 @@
#!/usr/bin/perl -w
package esmith::FormMagick::Panel::minilist;
use strict;
use esmith::FormMagick;
use esmith::ConfigDB;
use esmith::AccountsDB;
use File::Basename;
use Exporter;
use Carp;
our @ISA = qw(esmith::FormMagick Exporter);
our @EXPORT = qw(
new
get_accounts_prop
get_members
get_html_members
get_description
show_initial
create_list
modify_list
delete_list
validate_list_name
validate_list_description
validate_list_members
);
our $a = esmith::AccountsDB->open() || die "Couldn't open accounts";
our $db = esmith::ConfigDB->open || die "Couldn't open config db";
sub new {
shift;
my $self = esmith::FormMagick->new();
$self->{calling_package} = (caller)[0];
bless $self;
return $self;
}
# return the value of a prop from an account object
sub get_accounts_prop {
my $fm = shift;
my $item = shift;
my $prop = shift;
my $record = $a->get($item);
if ($record) {
return $record->prop($prop);
}
else {
return '';
}
}
# Return the members of a list
sub get_members {
my $fm = shift;
my $q = $fm->{cgi};
my $list = $q->param('listName') || '';
my @members = split /[;,]/, get_accounts_prop($fm,$list,'Members');
my $members = join "\n", @members;
return $members;
}
# return the members of a list
# to display in HTML
sub get_html_members {
my $fm = shift;
my $q = $fm->{cgi};
my $list = $q->param('listName') || '';
my $members = get_members($fm,$list);
$members =~ s/\n/<br>/g;
return $members;
}
# return the description of a list
sub get_description {
my $fm = shift;
my $q = $fm->{cgi};
my $list = $q->param('listName') || '';
return get_accounts_prop($fm,$list,'Description');
}
# Print a table with the actual list and a button to create new ones
sub show_initial () {
my $fm = shift;
my $q = $fm->{cgi};
my @lists = $a->get_all_by_prop(type=>'minilist');
print $q->Tr($q->td(
"<p><a class=\"button-like\" href=\"minilist?page_stack=;page=0;&wherenext=CreateList\">"
. $fm->localise("LIST_ADD")
. "</a></p>"));
if ( scalar @lists == 0 ) {
print $q->Tr($q->td(
'<p><b>' . $fm->localise("NO_LIST_CREATED") . '</p></b>'));
}
else {
print $q->start_table({-CLASS => "sme-border"}),"\n";
print "<tr><th class=\"sme-border\">"
. $fm->localise("LIST")
. "</th> <th class=\"sme-border\">"
. $fm->localise('DESCRIPTION')
. "</th><th class=\"sme-border\" colspan=\"2\">"
. $fm->localise('ACTION')
. "</th></tr>";
foreach my $list ( @lists ) {
my $name = $list->key;
print "<tr>" . "<td class=\"sme-border\">"
. $name . "</td>" . "<td class=\"sme-border\">"
. $list->prop('Description') . "</td>"
. "<td class=\"sme-border\"><a href=\"minilist?page_stack=;page=0;&listName=$name&wherenext=Modify\">"
. $fm->localise("MODIFY") . "</a></td>"
. "<td class=\"sme-border\"><a href=\"minilist?page_stack=;page=0;&listName=$name&wherenext=Delete\">"
. $fm->localise("REMOVE") . "</a>" . "</td></tr>";
}
print $q->end_table,"\n";
}
return;
}
# Create a new list
sub create_list {
my $fm =shift;
my $q = $fm->{cgi};
my $name =$q->param('listName') || '';
my @members = split /\r?\n/, ($q->param('members') || '');
my $members = join ",", @members;
my %props = (
'type', 'minilist', 'Description',
$q->param('listDesc'), 'Members', $members
);
$a->new_record( $name, \%props );
($name) = ($name =~ /^([a-z0-9][\-\_\.a-z0-9]*)$/);
return system("/sbin/e-smith/signal-event", "list-create", "$name") ?
$fm->error('CREATE_ERROR') : $fm->success('CREATE_SUCCESS');
}
# modify an existinbg list
sub modify_list {
my $fm =shift;
my $q = $fm->{cgi};
my $name =$q->param('listName') || '';
my @members = split /\r?\n/, ($q->param('members') || '');
my $members = join ",", @members;
$a->set_prop($name,'Description',$q->param('listDesc'));
$a->set_prop($name,'Members',$members);
($name) = ($name =~ /^([a-z0-9][\-\_\.a-z0-9]*)$/);
return system("/sbin/e-smith/signal-event", "list-modify", "$name") ?
$fm->error('MODIFY_ERROR') : $fm->success('MODIFY_SUCCESS');
}
# delete a list (after confirmation)
sub delete_list {
my $fm =shift;
my $q = $fm->{cgi};
my $name =$q->param('listName') || '';
return $fm->error('DELETE_ERROR') unless $a->get($name)->delete;
($name) = ($name =~ /^([a-z0-9][\-\_\.a-z0-9]*)$/);
return system("/sbin/e-smith/signal-event", "list-delete", "$name") ?
$fm->error('DELETE_ERROR') : $fm->success('DELETE_SUCCESS');
}
# Validate list name
sub validate_list_name {
my $fm = shift;
my $name = shift;
unless ($name =~ /^([a-zA-Z0-9][\_\.\-a-zA-Z0-9]*)$/){
return $fm->localise('INVALID_CHARS',{string => $name});
}
if ($a->get($name)){
return $fm->localise('ACCOUNT_CLASH',{string => $name});
}
return "OK";
}
# Validate list description
sub validate_list_description {
my $fm = shift;
my $desc = shift;
unless ($desc =~ /^([a-zA-Z0-9][\s\w\.\-]*)$/){
return $fm->localise('INVALID_CHARS',{string => $desc});
}
return "OK";
}
# Validate memebrs of a list
sub validate_list_members {
my $fm = shift;
my $members = shift;
foreach my $member (split /\r?\n/, $members) {
my $acc = $a->get($member);
if ($acc){
my $type = $acc->prop('type') || 'none';
next if ($type eq 'user');
}
unless ($member =~ /^[a-zA-Z0-9][\w\.\-]*\@([a-zA-Z0-9\._\-]+\.[a-zA-Z0-9\._\-]+)$/){
return $fm->localise('INVALID_CHARS',{string => $member});
}
}
return "OK";
}

52
smeserver-minilist.spec Normal file
View File

@ -0,0 +1,52 @@
%define version 0.1.1
%define release 1
%define name smeserver-minilist
Summary: minilist provide a panel to manage simple mailing lists
Name: %{name}
Version: %{version}
Release: %{release}%{?dist}
License: GPL
Group: Networking/Daemons
Source: %{name}-%{version}.tar.gz
BuildRoot: /var/tmp/%{name}-%{version}-%{release}-buildroot
BuildArchitectures: noarch
BuildRequires: e-smith-devtools
Requires: e-smith-base >= 5.2.0
%description
Provides group like mail fonctionnality, but lets you enter arbitrary email addresses
%changelog
* Thu Nov 22 2012 Daniel Berteaud <daniel@firewall-services.com> - 0.1.1-1
- Add template for qpsmtpd goodrcptto
* Thu Nov 22 2012 Daniel Berteaud <daniel@firewall-services.com> - 0.1.0-1
- initial release
%prep
%setup -q -n %{name}-%{version}
%build
perl createlinks
%install
/bin/rm -rf $RPM_BUILD_ROOT
(cd root ; /usr/bin/find . -depth -print | /bin/cpio -dump $RPM_BUILD_ROOT)
/bin/rm -f %{name}-%{version}-filelist
/sbin/e-smith/genfilelist $RPM_BUILD_ROOT \
> %{name}-%{version}-filelist
%files -f %{name}-%{version}-filelist
%defattr(-,root,root)
%clean
rm -rf $RPM_BUILD_ROOT
%pre
%post