# $Id$
# $URL$
+=head1 NAME
+
+mail2sms.pl
+
+=head1 DESCRIPTION
+
+Script, das aus entgegengenommenen Mails SMS'en generiert und diese
+in das Ausgangsverzeichnis des SMS-Daemons legt.
+
+Desweiteren wird an eine festgelegte Empfaengeradresse eine Bestaetigungsmail gesendet.
+
+=head1 SYNOPSIS
+
+ mail2sms.pl [Options...] <SMS-Empfaenger-Nr. 1> [ <SMS-Empfaenger-Nr. 2> ... ]
+ mail2sms.pl -h
+ mail2sms.pl -V
+
+I<Hinweis:> Falls eine der SMS-Empfaenger-Nummern mit einem C<-> oder C<+> beginnt, dann muessen
+diese mit zwei Bindestrichen abgetrennt werden, wie zum Beispiel:
+
+ mail2sms.pl -- +491721234567
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<--smsc E<lt>SMSC-NummerE<gt>>
+
+Die SMS-Zentrale (ueberschreibt die im Handy eingetragene).
+
+=item B<-s E<lt>sendmail-ProgrammE<gt>>
+
+=item B<--sendmail E<lt>sendmail-ProgrammE<gt>>
+
+Benutzt das angegebene Programm zum Versenden der Bestaetigungsmail.
+
+Default: C</usr/lib/sendmail>
+
+=item B<-r E<lt>Empfaenger-AdresseE<gt>>
+
+=item B<--rcpt E<lt>Empfaenger-AdresseE<gt>>
+
+Gibt die Adresse des Empfaengers der Bestaetigungsmails an.
+
+Default: C<brehm@strato.de>
+
+=item B<-f E<lt>Sender-AdresseE<gt>>
+
+=item B<--from E<lt>Sender-AdresseE<gt>>
+
+Gibt die Adresse des Absenders der Bestaetigungsmails an.
+
+Default: C<SMS Daemon E<lt>sms@smc.technik.berlin.strato.deE<gt>>
+
+=item B<-n>
+
+=item B<--nomail>
+
+Es wird keine Bestaetigungsmail geschickt.
+
+=item B<-S E<lt>spool-directoryE<gt>>
+
+=item B<--spooldir E<lt>spool-directoryE<gt>>
+
+Gibt das Spool-Verzeichnis an, in das die generierte SMS abgelegt wird.
+
+Default: C</var/spool/sms/outbox/>
+
+=item B<-m E<lt>XXXE<gt>>
+
+=item B<--max E<lt>XXXE<gt>>
+
+=item B<--maxlen E<lt>XXXE<gt>>
+
+Gibt (numerisch) die Maximallaenge einer SMS an.
+
+Ein Text der groesser ist, wird bei dieser Laenge abgeschnitten.
+
+I<Hinweis:> Zur Laenge des Textes zaehlt auch der Btreff der Mail mit dazu.
+
+Default: C<144>
+
+=item B<-v> Verbose-Level (Debug-Level)
+
+Wird durch Mehrfach-Aufzaehlung erhoeht.
+
+=item B<-D E<lt>levelE<gt>> - Debug-Level
+
+Numerische Angabe des Debug-Levels.
+
+I<Hinweise>:
+
+Die Parameter C<-v> und C<-D> wirken sich gleich aus.
+Wenn beide angegeben werden, wird der hoehere von beiden verwendet.
+
+=item B<-h>
+
+=item B<-?>
+
+=item B<-help>
+
+Gibt diesen Hilfebildschirm aus und beendet sich.
+
+=item B<-V>
+
+Gibt die Versionsnummer dieses Programms aus und beendet sich.
+
+=back
+
+=cut
+
+#---------------------------------------------------------------------------
+
use strict;
+use 5.8.0;
use warnings;
use Email::Simple;
use Email::MIME;
use Data::Dumper;
+use Getopt::Long qw( :config no_gnu_getopt require_order no_getopt_compat bundling );
+use Pod::Usage;
$Data::Dumper::Indent = 1;
$Data::Dumper::Sortkeys = 1;
+my $Revis = <<'ENDE';
+ $Revision$
+ENDE
+$Revis =~ s/^.*:\s*(\S+)\s*\$.*/$1/s;
+our $VERSION = $Revis;
+
$| = 1;
+# Vorgabewerte und andere Variablen deklarieren
+
my $sendmail = "/usr/lib/sendmail";
my $rcpt = 'brehm@strato.de';
my $from = 'SMS Daemon <sms@smc.technik.berlin.strato.de>';
my $dir = "/var/spool/sms/outbox/";
-#my $dir = "/tmp/";
-my $filepat = $dir . "mail2sms_" . time() . "-" . $$ . '_%d.txt';
my $maxlen = 144;
my $subject = "SMS gesendet an: ";
-my $maxenv = 1;
+my ( $cmdline_verbose, $help, $show_version, $DebugLevel, $smsc, $nomail );
+
+# Kommandozeile auswerten
+unless (
+ GetOptions(
+ "smsc=s" => \$smsc,
+ "sendmail|s=s" => \$sendmail,
+ "rcpt|r=s" => \$rcpt,
+ "from|f=s" => \$from,
+ "nomail|n" => \$nomail,
+ "spooldir|spool|S=s" => \$dir,
+ "maxlen|max|m=i" => \$maxlen,
+ "help|h|?" => \$help,
+ "verbose|v+" => \$cmdline_verbose,
+ "version|V" => \$show_version,
+ "DebugLevel|Debug|D=i" => \$DebugLevel,
+ )
+ )
+{
+ pod2usage( { -exitval => 1, -verbose => 1 } );
+} ## end unless ( GetOptions( "smsc=s"...
+
+$cmdline_verbose ||= 0;
+$cmdline_verbose = $DebugLevel if $DebugLevel and $DebugLevel > $cmdline_verbose;
+
+my $verbose = $cmdline_verbose;
+
+# Es wurde nach Hilfe gerufen
+if ($help) {
+ $verbose ? pod2usage( -exitstatus => 1, -verbose => 2 ) : pod2usage(1);
+}
+
+# Versionsausgabe
+if ($show_version) {
+ print "Version $0: " . $VERSION . "\n";
+ print "\n";
+ exit 0;
+}
+
+my $maxenv = 1;
my ( $attr, $env, $input, $text, $body, $content, $r, $file, $lockfile, $i, $mail, $part );
-my ( @Rcpts );
+my (@Rcpts);
+# Ausgabe des Environments vorbereiten
foreach ( keys %ENV ) {
- $maxenv = length( $_ ) if length( $_ ) > $maxenv;
+ $maxenv = length($_) if length($_) > $maxenv;
}
-$env = join( "\n", map( { sprintf( " - %-*s: '%s'", $maxenv + 2, "'" . $_ . "'", $ENV{$_} ) } sort( { lc($a) cmp lc($b) } keys %ENV ) ) );
-$attr = join( "\n", map( { sprintf( " - '%s'", $_ )} @ARGV ) );
+$env = join( "\n", map( { sprintf( " - %-*s: '%s'", $maxenv + 2, "'" . $_ . "'", $ENV{$_} ) } sort( { lc($a) cmp lc($b) } keys %ENV ) ) );
+$attr = join( "\n", map( { sprintf( " - '%s'", $_ ) } @ARGV ) );
+
+# Alle Empfaengernummern zusammensammeln
@Rcpts = @ARGV;
+
+unless (@Rcpts) {
+ warn $0 . ": Keine Empfaengernummern angegeben!\n";
+ pod2usage( { -exitval => 10, -verbose => 1 } );
+}
+
+# Moegliche Fehlerursachen ausschalten ...
+unless ( -x $sendmail ) {
+ warn $0 . ": Sendmail-Executable '" . $sendmail . "' existiert nicht!\n";
+ pod2usage( { -exitval => 10, -verbose => 1 } );
+}
+unless ( -d $dir ) {
+ warn $0 . ": Spoolverzeichnis '" . $dir . "' existiert nicht!\n";
+ pod2usage( { -exitval => 10, -verbose => 1 } );
+}
+unless ( -w $dir ) {
+ warn $0 . ": Spoolverzeichnis '" . $dir . "' ist nicht beschreibbar!\n";
+ pod2usage( { -exitval => 10, -verbose => 1 } );
+}
+
+my $filepat = $dir . "mail2sms_" . time() . "-" . $$ . '_%d.txt';
+
@ARGV = ();
+
+# Mail enlesen von STDIN
{
- local $/ = undef;
- $input = <>;
+ local $/ = undef;
+ $input = <>;
}
$body = undef;
+# Mail zerpflücken und den plain-text-Teil heraussuchen
$mail = Email::Simple->new($input);
-if ( $mail->header("content-type" ) =~ m#multipart/alternative#i ) {
- $mail = Email::MIME->new($input);
- foreach $part ( @{$mail->{'parts'}} ) {
- if ( $part->header("content-type" ) =~ m#text/plain#i ) {
- $body = $part->body();
- last;
+if ( $mail->header("content-type") =~ m#multipart/alternative#i ) {
+
+ # Es ist eine zusammengesetzte Mail
+ $mail = Email::MIME->new($input);
+
+ # Nach einem Teil suchen, dessen content-type text/plain ist
+ foreach $part ( @{ $mail->{'parts'} } ) {
+ if ( $part->header("content-type") =~ m#text/plain#i ) {
+ $body = $part->body();
+ last;
+ }
}
- }
- $body = $mail->body_raw() unless $body;
-} else {
- $body = $mail->body();
+
+ # Es gab keinen plain-text-Teil, dann den gesamten Mailtext nehmen
+ $body = $mail->body_raw() unless $body;
+} ## end if ( $mail->header("content-type"...
+else {
+
+ # Es eine einfache Mail
+ $body = $mail->body();
}
+
+##############################
+# SMS-Text zusammemsetzen
+
+# Zuerst der Mail-Betreff
$text = $mail->header("subject");
$text .= "\n" if $text;
+
+# Dann der Mail-Text
$text .= $body;
+
+# Text trimmen und auf Länge stutzen
$text =~ s/\s+$//;
$text = substr( $text, 0, $maxlen );
-$subject .= "'" . join( "', '", @Rcpts ) . "'";
+# Bestätigungs-Mail rausjagen, falls nicht untersagt ..
+unless ($nomail) {
-open MAIL, "| $sendmail $rcpt" or die "Konnte $sendmail nicht starten.\n";
-print MAIL "From: " . $from . "\n";
-print MAIL "To: " . $rcpt . "\n";
-print MAIL "Subject: $subject\n\n";
+ $subject .= "'" . join( "', '", @Rcpts ) . "'";
-print MAIL "Gesendeter Text:\n" . $text . "\n";
-print MAIL "---------------------\n";
-print MAIL "Environment:\n" . $env . "\n\n";
-print MAIL "Kommando-Parameter:\n" . $attr . "\n\n";
-print MAIL "Standard-Input:\n" . $input . "\n\n";
-#print MAIL "Mail-Objekt: " . Dumper( $mail );
+ open MAIL, "| $sendmail $rcpt" or die "Konnte $sendmail nicht starten.\n";
+ print MAIL "From: " . $from . "\n";
+ print MAIL "To: " . $rcpt . "\n";
+ print MAIL "Subject: $subject\n\n";
-close( MAIL );
+ print MAIL "Gesendeter Text:\n" . $text . "\n";
+ if ( $verbose ) {
+ print MAIL "---------------------\n";
+ print MAIL "Environment:\n" . $env . "\n\n";
+ print MAIL "Kommando-Parameter:\n" . $attr . "\n\n";
+ print MAIL "Standard-Input:\n" . $input . "\n\n";
+ print MAIL "Mail-Objekt: " . Dumper($mail) if $verbose > 1;
+ }
+
+ close(MAIL);
+
+} ## end unless ($nomail)
+
+# Jetzt die einzelnen Empfaenger abklappern
$i = 0;
-foreach $r ( @Rcpts ) {
-
- $i++;
- $file = sprintf( $filepat, $i );
- $lockfile = $file . ".lock";
- $content = "Recipient: " . $r . "\n\n" . $text;
- if ( open( LOCK, ">", $lockfile ) ) {
- close LOCK;
- } else {
- warn "Konnte Lockfile '" . $lockfile . "' nicht anlegen: $!\n";
- next;
- }
-
- if ( open( SMS, ">", $file ) ) {
- print SMS $content . "\n";
- close SMS;
- chmod 0666, $file;
- } else {
- warn "Konnte SMS-File '" . $file . "' nicht anlegen: $!\n";
- }
-
- unlink $lockfile;
+foreach $r (@Rcpts) {
-}
+ $i++;
+
+ # Ausgabedatei festlegen
+ $file = sprintf( $filepat, $i );
+
+ print "Erzeuge Spool-Datei '" . $file . "' fuer Empfaenger '" . $r . "'\n" if $verbose;
+
+ # Lockdatei anlegen
+ $lockfile = $file . ".lock";
+ if ( open( LOCK, ">", $lockfile ) ) {
+ close LOCK;
+ }
+ else {
+ warn "Konnte Lockfile '" . $lockfile . "' nicht anlegen: $!\n";
+ next;
+ }
+
+ # Inhalt der Ausgabedatei festlegen
+ $content = "Recipient: " . $r . "\n";
+ $content .= "SMSC: " . $smsc . "\n" if $smsc;
+ $content .= "\n" . $text;
+
+ # eigentliche Ausgabedatei anlegen und füllen
+ if ( open( SMS, ">", $file ) ) {
+ print SMS $content . "\n";
+ close SMS;
+ chmod 0666, $file;
+ }
+ else {
+ warn "Konnte SMS-File '" . $file . "' nicht anlegen: $!\n";
+ }
+
+ # Lock-Datei wegschmeissen
+ unlink $lockfile || warn("Konnte Lockdatei '$lockfile' nicht loeschen: $!\n");
+
+} ## end foreach $r (@Rcpts)
exit 0;
+#------------------------------------------------------------------------------------------
+
+__END__
+