#!/usr/local/bin/perl -w
#!/usr/bin/perl
##
## based on Linux Mail2News HOWTO by ???
## improved by Frank Strauss <strauss@ibr.cs.tu-bs.de>, Apr 1997
## worsened by Joerg Schumacher <schuma@gaertner.de>, Feb 1998
## never return error codes by Oliver Wellnitz <wellnitz@ibr.cs.tu-bs.de>, Nov 1998
## no longer munge msgid by default, only if otherwise rejected <strauss@escape.de>, Aug 2000
## pass through header as originally as possible <strauss@escape.de>, Aug 2000
## 
## TODO: options -a approve, -o emtpyorg, -s enptysubj, -i inews, -j junk
##

# use 5.004;
use File::Basename;
use Sys::Syslog;
use Getopt::Std;


# some defaults:

# the inews program and its required to options
#$inews = "/usr/bin/inews -h";
$inews = "/usr/local/bin/inews -h";

# where to store the article temporarily
$tmp = "/tmp/mail2news.$$";

# group to junk artikles in
$junk = "ibr.mailinglists.junk";

## subject of news article if no subject in email
$emptysubject = "<none>";

## organization of news article if no organization in email
$emptyorganization = "<unknown>";

## approved header content in news article (might be empty)
$approved = "mail2news gateway";

## distribution
#$distribution = "local";
$distribution = "";

## for debugging: write to stdout instead of inews
#$inews = "cat";



getopts('i:j:s:o:a:');
if ($opt_i) { $inews = $opt_i; }
if ($opt_j) { $junk = $opt_j; }
if ($opt_s) { $emptysubject = $opt_s; }
if ($opt_o) { $emptyorganization = $opt_o; }
if ($opt_a) { $approved = $opt_a; }
if ($opt_d) { $distribution =$opt_d; }

# from <sysexits.h>
$EX_OK = 0;


$me = basename("$0");
# prepare syslog 
Sys::Syslog::setlogsock('unix');  # use unix sock /dev/log instead of inet sock
openlog($me, 'pid', 'mail'); 


if ($#ARGV != 0) {  
   # missing or too many arg(s), junk article
   syslog('warning', "missing newsgroup, posting article to $junk");
   $newsgroups = $junk;
} else {
   $newsgroups = $ARGV[0];
} 

# get an identifier for the group out of the last pattern of the newsgroup
# name. this is appended to the message id, to reduce news server rejects
# due to duplicates.
$groupid = $newsgroups;
$groupid =~ s/^.*\.([^\.]*)$/$1/;

# in case inews dumps core or something crazy.
$SIG{'PIPE'} = "plumber";
sub plumber { 
   syslog('err', "inews died prematurely! (SIGPIPE)");
   exit $EX_OK;
}

open (TMP, ">$tmp") || do {
   syslog('err', "can't open temporary article file: $!");
   exit $EX_OK;
};

# header munging loop.
while (<STDIN>) {
    last if /^$/;  

    # strip off path header from mail message. who does such things?
    s/^Path:\s+(.*)/X-Mail2News-Path: $1/;

    s/^Approved:\s+(.*)/X-Mail2News-Approved: $1/;
    s/^Received:\s+(.*)/X-Mail2News-Received: $1/;

    # transform from_ line to path header; also works locally.
    s/^From\s+(\S+)\@(\S+).*/Path: $2!$1/
	|| s/^From\s+(\S+)[^\@]*$/Path: $1\n/;
    
    # transform in-reply-to to references line.
    s/^References:\s+(.*)/X-References: $1/;
    s/^In-Reply-To:\s+.*<(.*)>.*/References: <$1>/;

    if (/^Message-ID:\s*(<.*>).*/i) {
	$msgid = $1;
    }

#    if (! /^[ \t]/) {
#	$inskipping = 0;
#    }
#    if (/^(Received|Approved):/i) {
#	$inskipping = 1;
#	next;
#    }
#    if (/^[ \t]/ && $inskipping) {
#	next;
#    }

    print TMP;
    
    if ( /^Subject:/) { $saw_subject = 1; }
    if ( /^Organization:/) { $saw_organization = 1; }
} 

printf TMP "Newsgroups: %s\n", $newsgroups;
printf TMP "Subject: %s\n", $emptysubject unless $saw_subject;
printf TMP "Approved: %s\n", $approved if $approved;
printf TMP "Organization: %s\n", $emptyorganization unless $saw_organization;
printf TMP "Distribution: %s\n", $distribution if $distribution;
print  TMP "\n";

# gobble rest of message.
while (<STDIN>) {
    print TMP;
}

close TMP;

# try to post the article.
open (INEWS, "| $inews") || do {
   syslog('err', "can't open pipe to inews: $!");
   # unlink $tmp;
   exit $EX_OK;
};
open(STDIN, "<$tmp");
while (<STDIN>) {
	print INEWS;
}
close INEWS;

if ($? >> 8 == 1) {
    # maybe this article has been rejected as a duplcaited message id,
    # because we have received this mail (with this message id)
    # previously through another mailing list. in this case (and only
    # in this case) we munge the message id and try once again to post it.
    open (INEWS, "| $inews") || do {
	syslog('err', "can't open pipe to inews: $!");
        # unlink $tmp;
	exit $EX_OK;
    };
    open(STDIN, "<$tmp");
    while (<STDIN>) {
	# transform message id to suppress duplicates.
	s/^Message-ID:\s*(<[^\@]+)/Message-ID: $1.$groupid/i;
	if (/^Message-ID:\s*(<.*>).*/i) {
	    $msgid = $1;
	}
	# now add groupid to every references message id.
	s/^References:\s+.*<(.*)\@(.*)>.*/References: <$1.groupid\@$2>/g;
	print INEWS;
    }
    close INEWS;
}

if ($?) {
    $ec = $? >> 8; 
    $sig = $? & 255;
    syslog('err', "error from pipe to inews: ec=$ec sig=$sig msgid=$msgid ng=$newsgroups");
    # drop article, dont bother poor list admins
    # unlink $tmp;
    exit $EX_OK;
}
syslog('debug', "posted article: msgid=$msgid ng=$newsgroups"); 

unlink $tmp;

exit $EX_OK;

