On m’a demandé récemment un petit coup de main pour solutionner un petit problème de mail. En gros les méchants sys admins ont décidé, pour des raisons obscures que je n’évoquerai pas, que sendmail ne devait plus etre utilisé sur les serveurs. D’un coup, tout un tas de gens qui envoyaient des mails simplement avec la commande mail ou mailx se retrouvaient à ne plus pouvoir envoyer de mail. Cela les a bien mis dans l’embarras.

En même temps envoyer un mail n’est pas ce qu’il y a de plus compliqué. Le mail tel qu’on le connait est en fait régi par le protocole SMTP (Simple Mail Transfer Protocol). Examinons une simple session SMTP:

[dalwyn@ks355577]~% nc gmail-smtp-in.l.google.com 25
220 mx.google.com ESMTP 5si27232822ewy.52
helo localhost.localdomain
250 mx.google.com at your service
mail from: <usurpateur@mechant.com>;
250 2.1.0 OK 5si27232822ewy.5
rcpt to: <nospam@truc.bidule.co>;
250 2.1.5 OK 5si27232822ewy.52
data
354  Go ahead 5si27232822ewy.52
To: <nospam@truc.bidule.co>;
Subject: Test SMTP
Ceci est un test de SMTP
.


En gros envoyer un mail, c’est telnet sur le port 25 du serveur mail, puis HELO, MAIL FROM:, RCPT TO: et DATA puis on finit par un point.

Mes utilisateurs très habitués à leur petite commande unix ne se sentaient pourtant pas de se développer leur script. En voila donc un qui mimique le comportement de la commande unix mail. Il nécessite les modules Net::SMTP et Net::Domain et permet d’envoyer des mails a plusieurs destinataires à la fois.

Enfin il nécessite de préciser le smarthost (relai smtp) soit en option, soit dans la variable d’environnement MAILHOST.

Voici le script:

#!/usr/bin/perl -w
# use libs ('/SERVICE/bin/perl/');
#
# Copyright (C) Vin0x64 <vincent@vin0x64.fr>
#
# 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

use strict;
use Net::SMTP;
use Getopt::Long;
use Net::Domain qw(hostfqdn);

my $_o_subject;
my $_o_from;
my @_o_to;
my $_o_smarthost=$ENV{MAILHOST};
my $_o_help;

## Read command line options
my $result = GetOptions("subject|s=s" => \$_o_subject,
		"from|f=s" => \$_o_from,
		"to|t=s" => \@_o_to,
		"smarthost|D=s" => \$_o_smarthost,
		"help|h" => \$_o_help);
$result or die &usage();
$_o_help && die &usage();
die "(EE) No smarthost specified used -D option\n" unless $_o_smarthost;

## Handle recipient list
push @_o_to,@ARGV;
@ARGV=();
die "(EE) You should have at least one recipient\n" if (0 eq @_o_to);

## Create connection to the SMTP server
my $smtp = Net::SMTP->new($_o_smarthost)
	or die "(EE) Could not create SMTP connection\n";
my $host=hostfqdn;
$smtp->mail(($_o_from)?$_o_from:$ENV{USER}."@".$host);

## Prepare mail recipients
my @goodrecips=$smtp->recipient(@_o_to,
	{ SkipBad => 1 });

## Mail data part
$smtp->data();

# Send To: headers
foreach my $to (@_o_to) {
	$smtp->datasend("To: $to\n");
}

# Send Subject: header
$_o_subject && $smtp->datasend("Subject: $_o_subject\n");

# Message body
$smtp->datasend("\n");
my $line;
while (<>) {
	$smtp->datasend($_);
}

# End data part
$smtp->dataend();

# Close SMTP connection
$smtp->quit();

sub usage () {
	my $usage="
Usage: mail.pl [OPTIONS] [RECIPIENTS]
Expects you to write mail on STDIN until you type Ctrl-D or as a pipe, and will
send the mail via the specified mailhost.
Example: echo 'Test mail' | ./mail.pl -D mailhost
		-s 'Test mail' toto\@mail.co

Oprions:
   -s, --subject	Subject of the mail
   -f, --from		Mail Sender
   -t, --to		Mail recipient (can be invoked several times)
   -D, --smarthost	SMTP server name or IP address of the mailhost. This can
			also be specified as environment variable MAILHOST
   -h, --help		Writes this help message
";
	return $usage;
}


Quelques exemples d’utilisation à la “mail” unix:

[vincent@guiraud 11:39 ~/DEVEL/perl] MAILHOST=smtp-gateway.co
[vincent ~/DEVEL/perl] export MAILHOST
[vincent ~/DEVEL/perl] echo "This is a test text-only email\n Cheers\!" |./mail.pl -s 'Testing mail.pl with text' nospam@truc.bidule.co
[vincent ~/DEVEL/perl] uuencode /bin/ls "/bin/ls" | ./mail.pl -s 'Testing mail.pl with uuencoded atachment' nospam@truc.bidule.co
[vincent ~/DEVEL/perl] uuencode ./mail.pl "mail.pl" | ./mail.pl -s 'Auto sending mail.pl in attachment' nospam@truc.bidule.co


Voici un exemple plus specifique en utilisant les options en ligne de commande de GetOpt::Long

[vincent ~/DEVEL/perl] echo "Testing email sending\nCheers\!" |./mail.pl --smarthost=smtp-goss.fr.world.socgen --to machin@truc.bidule.co --subject='Testing email'

Vous etes libres d’utiliser ce script à vos risques et perils, je ne fournis aucune garantie, ni support. Si vous avez besoin de me contacter à ce propos, laissez un message ci dessous ou utilisez le formulaire de la page “a propos” ci dessus.