PDA

Bekijk Volledige Versie : mailman / majordomo alternatieven



Mikey
28/11/11, 16:00
Zoals topic titel al zegt, ben voor een kleine mailinglist opzoek naar alternatief op majordomo.

Nou wordt je op google helemaal onder gesneeuwd voor mailing lists, maar deze zijn voornamelijk one-way.

Een alternatief waar ik zelf tegen aan gelopen was groupserver.org .

Mocht iemand er nog meer weten dan vernemen we die graag !

t.bloo
28/11/11, 16:49
Ik heb hetzelfde aan het handje gehad. Wilde daarbij ook een eigen makkelijke interface naar een backend hebben, dus heb een keer uitgezocht hoe dat nou eigenlijk werkt. Via een eenvoudige hook in Exim een eigen PHP script gemaakt van 400 regels dat heel clean alle standaard functies van een mailinglist doet. Interesse, stuur me dan een PM.

t.bloo
28/11/11, 17:14
DH-Mailer eenvoudig mailing list script in PHP voor Exim.

Deze tutorial gaat uit van een standaard DirectAdmin installatie, maar werkt ongeveer hetzelfde bij een kale Exim opstelling.

Stap 1. Eerst exim.conf aanpassen:



# exim config snippet for dhmailer
#

#
# add this to /etc/exim.conf in the right spot after "begin routers"
#

dhmailer_aliases:
driver = redirect
allow_defer
allow_fail
data = ${if exists{/etc/virtual/${domain}/dhmailer.exim}{${lookup{$local_part}lsearch{/etc/virtual/${domain}/dhmailer.exim}}}}
domains = lsearch;/etc/virtual/domainowners
file_transport = address_file
pipe_transport = dhmailer_pipe
retry_use_local_part
no_rewrite

#
# add this to /etc/exim.conf after "begin transports"
#

dhmailer_pipe:
driver = pipe
return_fail_output
user = "${lookup{$domain}lsearch{/etc/virtual/domainowners}{$value}}"
group = "mail"


Stap 2. Dan een exim router file in je eigen directory plaatsen, noem 'm dhmailer.exim:


# exim router file for dhmailer
#
# one mailing list per line with this format:
# listname: "|/path/to/dhmailer.php listname"
#
# create symlink from /etc/virtual/domain/dhmailer.exim to this file
#
# add relevant router/transport lines to /etc/exim.conf as well
# (see for this the dhmailer.exim.conf file)
#
# example:
# test: "|/home/user/dhmailer/dhmailer.php test"
#

test1: "|/home/user/dhmailer/dhmailer.php test1"
test2: "|/home/user/dhmailer/dhmailer.php test2"


Stap 3. Maak een symbolic link:


ln -s /home/user/dhmailer.exim /etc/virtual/domain/dhmailer.exim


Stap 4. Plaats per mailinglist een ini file in je eigen directory, deze kun je makkelijk in je backend script genereren:


listname = "test"
domain = "testuser.nl"
logfile = "test.log"
senderformat = '"_REALNAME_ @ _LISTNAME_" <_LISTADDRESS_>'
errorsaddress = "webmaster@testuser.nl"
replytolist = "1"
subjecttag = "1"
subjecttag_text = "[Testuser Test]"
restricted = "1"
restricted_text = "error: address @@@ is not allowed to send messages to this list"
restricted_allow = "webmaster@testuser.nl"
maxlength = "100"
maxlength_text = "error: message length $$$ is too large for this list"
addfooter = "1"
addfooter_text = "---
testuser test mailing list - replies go back to the list"
addresses[] = "test1@testuser.nl"
addresses[] = "test2@testuser.nl"
addresses[] = "test3@testuser.nl"


Stap 5. Dit is het script dat het werk doet in je eigen directory:


#! /usr/local/bin/php
<?php

/*
* dhmailer.php - light weight mailing list script
*
* (c) 2009 Dommel Hosting / T. Bloo
*
* history:
* 2011-11-28 cleaned for publication, T
* 2011-11-17 improved address extraction, T
* 2011-11-12 added return path and failure logging, T
* 2011-11-11 added delay on error, T
* 2011-10-21 removed cc and bcc from resend, T
* 2011-10-12 sender format, T
* 2011-10-07 circular addresses, restricted allow, T
* 2011-10-06 improved realname handling, T
* 2011-09-30 changed realname handling, T
* 2011-09-28 sender visible, T
* 2011-09-27 use ini files, T
* 2011-09-23 standalone with .conf file, T
* 2011-09-20 working as part of userbase, T
* 2011-09-19 started from earlier work, T
*
* remark:
* this is a command line script, not a webserver program
*
* dependencies:
* php 5 engine on /usr/local/bin/php
*
* simplified usage:
* phpmailer.php listname
*
*/

### error handling
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
ini_set('html_errors', 0);

### defines
define('VERSION', 'DH-Mailer v1.4');
define('LOCATION', dirname(__FILE__));

define('TIMESTAMP', date('Y-m-d H:i:s'));
define('LOGFILE', LOCATION.'/dhmailer.log');

define('NL', "\n");
define('CRLF', "\r\n");
define('TAB', "\t");

### command line arguments
@list($scriptname, $listname) = $argv;
define('TESTSCRIPT', strpos($scriptname, '_test') !== false);
if ($listname == '')
{
echo 'error: listname empty'.NL;
file_put_contents(LOGFILE, TIMESTAMP.TAB.'empty listname'.NL, FILE_APPEND);
exit(1);
}

### get configuration
$config = dhmailer_readconfig($listname);
dhmailer_logfile($config, 'message', $listname);

### get and parse mail message
$messagetext = dhmailer_readmessage();
if (TESTSCRIPT) file_put_contents(LOGFILE, TIMESTAMP.TAB.'messagein'.TAB.$messagetext.NL, FILE_APPEND);
$message = dhmailer_parsemessage($messagetext);
dhmailer_logfile($config, 'subject', $message->subject);
dhmailer_logfile($config, 'sender', $message->sender);

### handle restricted lists
if ($config->restricted)
{
if (!in_array($message->from, $config->addresses) and !in_array($message->from, $config->restricted_allow))
{
# restricted_text = 'error: address @@@ is not allowed to send messages to this list'
$text = str_replace('@@@', $message->from, $config->restricted_text);
dhmailer_logfile($config, 'restricted', $message->from);
sleep(300);
dhmailer_sendemail($message->from, $message->subject, $text, $config->listaddress, $config->listaddress, '', $config->errorsaddress, $message->from);
exit(0);
}
}

### handle large messages
if ($config->maxlength > 0)
{
$length = strlen($messagetext);
if ($length > $config->maxlength * 1024)
{
# maxlength_text = 'error: message length of $$$ is too large for this list'
$text = str_replace('$$$', $length, $config->maxlength_text);
dhmailer_logfile($config, 'maxlength', $length);
sleep(60);
dhmailer_sendemail($message->from, $message->subject, $text, $config->listaddress, $config->listaddress, '', $config->errorsaddress, $message->from);
exit(0);
}
}

### append subject tag
if ($config->subjecttag)
{
if (stripos($message->subject, @$config->subjecttag_text) === false)
{
$message->subject = $config->subjecttag_text.' '.$message->subject;
}
}

### append footer message
if ($config->addfooter)
{
$message->body[] = $config->addfooter_text;
}

### reply to list or original address
if ($config->replytolist)
{
$realname = dhmailer_realname($message->sender);
if ($realname == '')
{
$message->sender = '"'.$config->listaddress.'" <'.$config->listaddress.'>';
}
else
{
# senderformat = '"_REALNAME_ @ _LISTNAME_" <_LISTADDRESS_>'
$sender = $config->senderformat;
$sender = str_replace('_REALNAME_', $realname, $sender);
$sender = str_replace('_LISTNAME_', $config->listname, $sender);
$sender = str_replace('_LISTADDRESS_', $config->listaddress, $sender);
$message->sender = $sender;
}
$message->replyto = $config->listaddress;
}
else
{
$message->replyto = $message->from;
}
dhmailer_logfile($config, 'sender', $message->sender);

### append mailer program signature
$message->headers[] = 'X-Mailer: '.VERSION;

### send emails
foreach ($config->addresses as $address)
{
dhmailer_sendemail($address, $message->subject, implode(CRLF, $message->body), $message->sender, $config->errorsaddress, '', '', $message->replyto, $message->headers);
dhmailer_logfile($config, 'send', $address);
}

### ready and success
exit(0);

### read and parse config file
function dhmailer_readconfig($listname)
{
# read ini file
$file = LOCATION.'/'.$listname.'.ini';
$inis = @parse_ini_file($file);

# report error
if ($inis === false)
{
echo 'error: ini file error'.NL;
file_put_contents(LOGFILE, TIMESTAMP.TAB.'inifile error'.TAB.$listname.NL, FILE_APPEND);
exit(1);
}

# convert to object
$config->listname = trim(strtolower(@$inis['listname']));
$config->domain = trim(strtolower(@$inis['domain']));
$config->listaddress = $config->listname.'@'.$config->domain;
$config->logfile = trim(@$inis['logfile']);
$config->senderformat = trim(@$inis['senderformat']);
if ($config->senderformat == '')
{
$config->senderformat = '"_REALNAME_ @ _LISTNAME_" <_LISTADDRESS_>';
}
$config->errorsaddress = trim(strtolower(@$inis['errorsaddress']));
if ($config->errorsaddress == $config->listaddress)
{
file_put_contents(LOGFILE, TIMESTAMP.TAB.'circular'.TAB.$config->errorsaddress.NL, FILE_APPEND);
$config->errorsaddress = '';
}
$config->replytolist = intval(@$inis['replytolist']);
$config->subjecttag = intval(@$inis['subjecttag']);
$config->subjecttag_text = @$inis['subjecttag_text'];
if ($config->subjecttag_text == '')
{
$config->subjecttag_text = '['.$config->listname.']';
}
$config->restricted = intval(@$inis['restricted']);
$config->restricted_text = @$inis['restricted_text'];
if ($config->restricted_text == '')
{
$config->restricted_text = 'error: address @@@ is not allowed to send messages to this list';
}
$config->restricted_allow = array();
$addresses = explode(',', @$inis['restricted_allow']);
foreach ($addresses as $address)
{
$address = strtolower(trim($address));
if ($address != '')
{
$config->restricted_allow[] = $address;
}
}
$config->maxlength = intval(@$inis['maxlength']);
$config->maxlength_text = @$inis['maxlength_text'];
if ($config->maxlength_text == '')
{
$config->maxlength_text = 'error: message length of $$$ is too large for this list';
}
$config->addfooter = intval(@$inis['addfooter']);
$config->addfooter_text = @$inis['addfooter_text'];
$config->addresses = array();
foreach (@$inis['addresses'] as $address)
{
$address = strtolower(trim($address));
if ($address == $config->listaddress)
{
file_put_contents(LOGFILE, TIMESTAMP.TAB.'circular'.TAB.$address.NL, FILE_APPEND);
}
else
{
$config->addresses[] = $address;
}
}

# return configuration
return $config;
}

### write to list log file if enabled
function dhmailer_logfile($config, $message, $argument)
{
if ($config->logfile != '')
{
chdir(LOCATION);
$ok = file_put_contents($config->logfile, TIMESTAMP.TAB.$message.TAB.$argument.NL, FILE_APPEND);
if ($ok === false)
{
$ok = file_put_contents(LOGFILE, TIMESTAMP.TAB.'logfile problem'.TAB.$config->logfile.NL, FILE_APPEND);
}
}
}

### send email with headers
function dhmailer_sendemail($to, $subject, $message, $from, $sender, $cc = '', $bcc = '', $replyto = '', $extraheaders = array())
{
$to = trim($to);
$from = trim($from);
$cc = trim($cc);
$bcc = trim($bcc);
$replyto = trim($replyto);
$sender = trim($sender);
$subject = trim($subject);

$headers = '';
if ($from != '') $headers .= 'From: '.$from.CRLF;
if ($cc != '') $headers .= 'Cc: '.$cc.CRLF;
if ($bcc != '') $headers .= 'Bcc: '.$bcc.CRLF;
if ($replyto != '') $headers .= 'Reply-To: '.$replyto.CRLF;
foreach($extraheaders as $extra)
{
if ($extra != '') $headers .= rtrim($extra).CRLF;
}
$success = false;
if (strpos($to, '@') !== false)
{
$success = mail($to, $subject, $message, $headers, '-f'.$sender);
}

if (!$success or TESTSCRIPT)
{
file_put_contents(LOGFILE, TIMESTAMP.TAB.'sendemail'.TAB.'s:'.intval($success ).'|t:'.$to.'|s:'.$subject.'|f:'.$from.'|s:'.$send er.'|c:'.$cc.'|b:'.$bcc.'|r:'.$replyto.'|h:'.$head ers.'|e:'.implode(NL, $extraheaders).'|m:'.$message.NL, FILE_APPEND);
}
return $success;
}

### get data from standard input
function dhmailer_readmessage()
{
$fd = fopen('php://stdin', 'r');
$text = '';
while (!feof($fd))
{
$text .= fread($fd, 1024);
}
fclose($fd);

return $text;
}

### parse email headers and body
function dhmailer_parsemessage($mailmessage)
{
$message->headers = array();
$message->body = array();
$message->to = '';
$message->from = '';
$message->subject = '';

# split into lines
$lines = explode(NL, $mailmessage);
# parse special from line at start
$firstline = array_shift($lines);
@list($label, $address, $rest) = explode(' ', $firstline);
$message->from = dhmailer_cleanaddress($address);

# collect header and body lines
$body = false;
foreach ($lines as $line)
{
$line = rtrim($line);
if (!$body and $line == '')
{
$body = true;
}
else
{
if ($body)
{
$message->body[] = $line;
}
else
{
$parts = explode(':', $line);
$name = strtolower(trim(array_shift($parts)));
$argument = trim(implode(':', $parts));
switch ($name)
{
case 'to' :
$message->to = dhmailer_cleanaddress($argument);
break;
case 'from' :
$message->sender = $argument;
if ($message->from == '')
{
$message->from = dhmailer_cleanaddress($argument);
}
break;
case 'cc' :
$message->cc = $argument;
break;
case 'bcc' :
$message->bcc = $argument;
break;
case 'reply-to' :
$message->replyto = $argument;
break;
case 'return-path' :
$message->returnpath = $argument;
break;
case 'subject' :
$message->subject = $argument;
break;
default :
$message->headers[] = $line;
break;
}
}
}
}

# remove additional empty last lines
if (end($message->body) == '') array_pop($message->body);
if (end($message->body) == '') array_pop($message->body);

# return result
return $message;
}

### remove real names from address line
function dhmailer_cleanaddress($address)
{
$address = strtolower(trim($address));
$address = str_replace('<', '', $address);
$address = str_replace('>', '', $address);
$parts = explode(' ', $address);
$address = array_pop($parts);
return $address;
}

### get real names from address line
function dhmailer_realname($sender)
{
# remove unwanted characters
$sender = trim($sender);
$sender = str_replace('<', '', $sender);
$sender = str_replace('>', '', $sender);

# test for multiple parts
$parts = explode(' ', $sender);
if (count($parts) <= 1)
{
# only plain email address
$name = $sender;
}
else
{
# realname <user@domain>
array_pop($parts);
$name = implode(' ', $parts);
$name = str_replace('"', '', $name);
$name = trim($name);
}
# get user part of user@domain
@list($name, $domain) = explode('@', $name);

return $name;
}

?>


Exim restarten en testen. Misschien moet je in exim.conf nog de trusted_users instelling aanpassen.

Garantie tot aan de deur. Veel plezier er mee!

Mikey
28/11/11, 17:45
Kijk, daar hebben we wat aan :) Ik ga hiermee testen :)!