Re: [EXIM] Problems calling externat programs

Top Page
Delete this message
Reply to this message
Author: Rick Williams
Date:  
To: exim-users
Subject: Re: [EXIM] Problems calling externat programs
> I have been trying to post some automated programs from the old
> sendmail server over. Both the files were called from the `aliases` 
> file ie prog1:    "|/usr/local/bin/program1". The first program was a 
> C program to generate a list of all the current email addresses and 
> who they belonged to and the second was a Perl program that 
> send a single email to all users on the system. Neither of the 
> programs work now properly. I do not claim to be a programmer, so 
> I got some help from our senoir programmer but to no avail.
> The messages I am getting in error are "Child returned error code 
> 1" and "process failed (1) when writing error message to 
> r_williams@??? (frozen)"


The problems are solved! The first problem was that the perl
program was calling sendmail with the -n option which does not
seem to translate into exim. The second problem was that there
was no human set up in the config file to receive error messages,
this was fixed by using "errors_address = "

I was asked for a copy of the programs we were using to mail
everybody and as they are not too big I hope you don't mind me
posting them here. There are two programs emailrequest.pl and
post_all.pl, they both require Mail.pm which I understand is
generally available.

These programs have been completely re-written from scratch by
one of our programmers and work <G>. The usual disclaimers
apply.

emailrequest.pl generates a list of all current users from the
password list sorted on company, surname and firstname, this is
very useful for us here because our staff constantly changes. The
other, post_all.pl takes a message and sends it on to all users in
the password list as a BCC, there are certain filters in the program
to miss out non-human users.

You will need some settings in your aliases file to call these
programs (although rather obvious). The first setting is needed.

### Alias File ###
discard:    :blackhole:


#email list request
email:        "|/where/you/put/it/emailrequest.pl"


#mail to everyone
everyone:    "|/where/you/put/it/post_all.pl"


#If you want to send a mass message to one part of your org only
#and it is defined in the company setting in the password file
#then use
company:    "|/where/you/put/it/post_all.pl \"Company Section\""


Any more questions, just ask.

Thanks.

Rick.

Rick Williams - Systems Support - The Charlesworth Group
http://www.charlesworth.com

#!/usr/bin/perl
#
#
#  Internal EMail List Generator
#
#  Version 2.0
#
#  William F. McCaw  1999
#
#
#  Returns an email containing a sorted list of all valid users on the
#  system, grouped according to company.
#
#  For this program to work properly, the following conditions must be met
#  for all valid email recipients...
#
#  * Their UID must be between 1000 and 60000 (inclusive).
#  * Their Name must be defined.
#  * Their Name must not start with a lower case 'x'.
#  * Their Name must not be 'nobody'.
#  * Their must be of the following format...
#
#       "Forename Surname, Company"
#
#    Note... The ", Company" must be present.
#            Forename is assumed to be the first word.
#            Surname is assumed to be everything else.
#



#
# Read the message from standard input
#
$MsgSender = '';
# Extract the required details from the message's header
while ( defined($Line = <STDIN>) && ($Line =~ /^[^\r\n]/) )
   {
   $Line =~ s/[\r\n]//gs;
   if ( $Line =~ /^Return-Path:\s*<([^>]+)>/i )     # First choice for sender
      { $MsgSender = $1; }
   if ( $Line =~ /^From:\s*(.*)/i && !$MsgSender )  # May be no return path
      { $MsgSender = $1; }
   }
# Ensure we have a sender's address
exit(0) if ( !$MsgSender );


#
# Read the contents of the system's password file
#
open(PASS, '/etc/passwd') || exit(0);
@Users = <PASS>;
close(PASS);

#
# Extract the details of all valid users from the password file and batch
# them according to the company name associated with them.
#
%Companies = ();
foreach $User ( @Users )
   {
# Separate the current user's details and determine whether to include them
# within the generated email list
   ( $EMail, $Password, $UID, $GID, $Name, $Home, $Shell ) = split(/:/, $User);
   next if ( !defined($UID) || ($UID < 1000) || ($UID > 60000) ||
             !defined($Name) || ($Name =~ /^x/) || ($Name eq 'nobody') );
# Ensure the name field contains a company name
   next if ( !($Name =~ /^(.*?)\s*\,\s*(.*?)$/) );
   $Name = $1;
   $Company = $2;
# Get the reference to the members array for this company, creating the
# company entry as and when required
   if ( exists($Companies{uc($Company)}) )
      { $Members = $Companies{uc($Company)}->[1]; }
   else
      {
      $Members = [];
      $Companies{uc($Company)} = [ $Company, $Members ];
      }
# Massage the user's name into the required "Surname, Forename" format
   if ( $Name =~ /^\s*([^\s]+)\s+(.+)$/ )
      { $Name = "$2, $1"; }
# Append the user to the list for the current company
   push(@$Members, [ $Name, $EMail ]);
   }


#
# Generate the email back to the original sender containing the full list
#
open(MAIL, "|/usr/bin/exim -t");
#
# Output the message headers and leading message body text
print(MAIL "From: $MsgSender\n",
           "To: $MsgSender\n",
           "Subject: Requested EMail List\n\n",
           "Internal EMail addresses as of: ", scalar(localtime()), "\n");
#
# Output the sorted list of companies, and within that, output the sorted
# list of individuals within that company
foreach $Company ( sort(keys(%Companies)) )
   {
   $Company = $Companies{$Company};
   print(MAIL "\n", 
              $Company->[0], "\n",
              ('~' x (length($Company->[0]) + 1)), "\n");
   foreach $Member ( sort({ uc($a->[0]) cmp uc($b->[0]) } @{$Company->[1]}) )
      { printf(MAIL "   %-34s   %s\n", $Member->[0], $Member->[1]); }
   }
#
# Output the trailing message footer
print(MAIL "\n",
           "Remember to received an updated email list, just send a blank message to\n",
           "email\@charlesworth.com and you should get a reply within 30 seconds.\n\n",
           "For more information or any queries contact sysadmin\@charlesworth.com\n\n");
close(MAIL);



#
# End of File
#
#!/usr/bin/perl
#
#
# "Everyone" EMail Exploder
#
# Version 2.0
#
# William F. McCaw 1999
#
#
# Sends body of message supplied on STDIN to all valid users listed within
# the computer's /etc/passwd file.
#
# * Original headers, apart from the sender and subject are discarded.
# * Recipients are batched with up to 60 per email.
# * Recipients are specified via 'Bcc:'.
#

#
# Function Prototypes
#
sub SendMessage();


#
# Determine the target company for sending out the email to
#
$TargetCompany = (( defined($ARGV[0]) ) ? $ARGV[0] : '');

#
# Read the message from standard input
#
$MsgSender = '';
$MsgSubject = '';
# Extract the required details from the message's header
while ( defined($Line = <STDIN>) && ($Line =~ /^[^\r\n]/) )
   {
   $Line =~ s/[\r\n]//gs;
   if ( $Line =~ /^Return-Path:\s*<([^>]+)>/i )     # First choice for sender
      { $MsgSender = $1; }
   if ( $Line =~ /^From:\s*(.*)/i && !$MsgSender )  # May be no return path
      { $MsgSender = $1; }
   elsif ( $Line =~ /^Subject:\s*(.+)/i )           # Preserve the subject
      { $MsgSubject = $1; }
   }
# If we are missing certain information then provide some defaults
$MsgSubject = '*** Unknown Subject ***' if ( !$MsgSubject );
# Read in the message body and signature
@MsgBody = <STDIN>;


#
# Read the contents of the system's password file
#
open(PASS, '/etc/passwd') || exit(0);
@Users = <PASS>;
close(PASS);

#
# Send the message to all the users within the password file
#
@MsgRecipients = ();
foreach $User ( @Users )
   {
# Split the current users's details and determine whether to send the
# message to them or not
   ( $EMail, $Password, $UID, $GID, $Name, $Home, $Shell ) = split(/:/, $User);
   next if ( !defined($UID) || ($UID < 1000) || ($UID > 60000) ||
             !defined($Name) || ($Name =~ /^x/) || ($Name eq 'nobody') );
   next if ( $TargetCompany && !($Name =~ /\,\s*$TargetCompany/io) );
# If we have already reached the recipient limit for this message then
# dispatch it and reset the recipient list ready for the next message
   if ( scalar(@MsgRecipients) == 60 )
      {
      SendMessage();
      @MsgRecipients = ();
      }
# Append the current email address to the recipient list
   push(@MsgRecipients, $EMail);
   }
#
# Ensure the folk at the end of the user list receive the message
if ( scalar(@MsgRecipients) )
   { SendMessage(); }




#
#
#  Routine to send the specified message
#
sub SendMessage()
   {
   open(MAIL, "|/usr/bin/exim -t");
   print(MAIL "From: $MsgSender\n") if ( $MsgSender );
   print(MAIL "To: Everyone <discard>\n",
              "Subject: TO EVERYONE: $MsgSubject\n",
              "Bcc: ", join(", ", @MsgRecipients), "\n\n",
              @MsgBody,
              "\n");
   close(MAIL);
   }



#
# End of File
#