Formmail mit blat.exe statt sendmail
Tobias Weisserth
- perl
Hallo liebe Helferlein!
Ich benutze bisher das formmail Perlskript von Matt Wright (www.worldwidemart.com/scripts) zum Versenden von Formulardaten. Nun möchte ich das Skript anpassen, damit es anstelle von sendmail das NT basierte blat.exe zum Versenden verwendet. Hat jemand Erfahrung mit blat in Kombination mit Perlskripten? Vielleicht gibt es sogar jemanden, der das formmail Skript von Matt Wright kennt?! :-?
Hilfreich wäre schon mal, ob die Art, wie blat Daten entgegen nimmt sich grundlegend von sendmail unterscheidet.
Nächste Frage in diesem Zusammenhang:
Im Skript von Matt Wright gibt es in der Routine, die die Daten an sendmail übergibt folgenden Code:
print MAIL "-" x 75 . "\n\n";
Was heisst das genau?
Ich weiss nur, dass damit Input von der console (STDIN) gemeint ist, der mit "-" angesprochen wird. Was bewirkt diese print Anweisung auf MAIL und was bedeutet das "x 75 . "?
In der blat-readme steht, dass anstelle von Files auf STDIN verwendet werden kann, mit dem "special filename "-"". Kann ich die Subroutine für sendmail unverändert auf blat übertragen bzw. übernehmen?
Jede Hilfe ist willkommen!
Gruß,
Tobias
Hallo, Tobias!
Ich kann dir nur beim Verstehen des Sendmail-Skriptes helfen, die Infos über blat.exe mußt du selber suchen.
Nächste Frage in diesem Zusammenhang:
Im Skript von Matt Wright gibt es in der Routine, die die Daten an sendmail übergibt folgenden Code:
print MAIL "-" x 75 . "\n\n";
Was heisst das genau?
Diese Zeile schreibt 75 mal "-" (einen Strich), und danach zwei Returns "\n". Das x ist ein Zeichenmultiplikator, der Punkt verkettet Zeichenketten. Ziel der Druckausgabe ist das Mailprogramm, diese Zeile druckt den Inhalt der Mail.
Deine Vermutung mit STDIN ist also falsch.
In der blat-readme steht, dass anstelle von Files auf STDIN verwendet werden kann, mit dem "special filename "-"". Kann ich die Subroutine für sendmail unverändert auf blat übertragen bzw. übernehmen?
Ich kenne den Aufruf von blat.exe nicht. Das Sendmail-Skript öffnet eine Pipe mit Ziel sendmail und sendet die Mail dann auf dem Dateihandle "MAIL". Das sendmail empfängt diese Daten auf der Standardeingabe STDIN. Wenn du blat dazu bewegen kannst, ebenso zu reagieren, dann hast du schon gewonnen.
Testszenario: Erstelle eine Textdatei mit den Informationen, die an blat übergeben werden sollen. Mit "type datei.txt | blat.exe ...(weitere Optionen)" muß blat zur Mitarbeit überredet werden, sonst brauchst du einen anderen Ansatz (der z.B. darin bestehen könnte, erst eine temporäre Datei mit dem Mailinhalt zu schreiben, die Datei dann zu senden und zu löschen).
- Sven Rautenberg
Hallo Sven,
erstmal Dankeschön für die erste Antwort. Ich habe die das Readme von Blat aufgetrieben und da heisst es:
syntax:
Blat <filename> -t <recipient> [optional switches (see below)]
Blat -install <server addr> <sender's addr> [<try>[<port>[<profile>]]] [-q]
Blat -profile [-delete | "<default>"] [profile1] [profileN] [-q]
Blat -h [-q]
-install <server addr> <sender's addr> [<try n times> [<port> [<profile>]]]
: set's SMTP server, sender, number of tries and port for profile
(<try n times> and <port> may be replaced by '-').
<filename> : file with the message body ('-' for console input, end with ^Z)
-t <recipient> : recipient list (comma separated)
-s <subj> : subject line
-f <sender> : overrides the default sender address (must be known to server)
-i <addr> : a 'From:' address, not necessarily known to the SMTP server.
-c <recipient> : carbon copy recipient list (comma separated)
-b <recipient> : blind carbon copy recipient list (comma separated)
-o <organization>: Organization field
-x <X-Header: detail>: Custom 'X-' header. eg: -x "X-INFO: Blat is Great!"
-r : Request return receipt.
-d : Request disposition notification.
-h : displays this help.
-q : supresses *all* output.
-debug : Echoes server communications to screen (disables '-q').
-noh : prevent X-Mailer header from showing homepage of blat
-noh2 : prevent X-Mailer header entirely
-p <profile> : send with SMTP server, user and port defined in <profile>.
-server <addr> : Specify SMTP server to be used. (optionally, addr:port)
-port <port> : port to be used on the server, defaults to SMTP (25)
-hostname <hst>: select the hostname used to send the message
-mime : MIME Quoted-Printable Content-Transfer-Encoding.
-uuencode : Send (binary) file UUEncoded
-base64 : Send (binary) file using base64 (binary Mime)
-try <n times> : how many time blat should try to send. from '1' to 'INFINITE'
-attach <file> : attach binary file to message (may be repeated)
-attacht <file>: attach text file to message (may be repeated)
-ti <n> : Set timeout to 'n' seconds.
Note that if the '-i' option is used, <sender> is included in 'Reply-to:'
and 'Sender:' fields in the header of the message.
---------------------------------------------------------------------
Interessant ist der Teil mit dem <filename>. Wenn ich das richtig verstehe, kann ich also an STDIN über einen Dateistream Daten an Blat schicken. Wie teile ich ihm aber mit, dass er alles hat und senden soll?
So sieht der entsprechende Teil für sendmail aus:
open(MAIL,"|$mailprog -t");
print MAIL "To: $Config{'recipient'}\n";
...
close (MAIL);
Schluckt Blat das genauso? Wie muss ich das mit dem ^Z verstehen? Dann galube ich, dass ich auch noch die Parameter etwas anders benutzen muss.
Meinst Du, das könnte funktionieren? Einziges Problem dürfte sein, dass Blat vielleicht die Steuerzeichen nicht interpretiert, oder? Wenn nämlich die Formatierung verloren geht, war der Sinn und Zweck der Aktion umsonst.
sub send_to_blat {
# Benötigte Variablen lokal zur Verfügung stellen #
local($print_config,$key,$sort_order,$sorted_field,$env_report);
# Email Subject bestimmen
$betreff = '';
if ($Config{'subject'}) { $betreff = $Config{'subject'} }
else { $betreff = WWW Form Submission }
# Adresse bestimmen
$address = $Config{'recipient'};
# Messageinhalt bestimmen
# Variable initialisieren, hier soll der komplette Textkörper hineingeschrieben werden
$message = 'Anbei die Resultate der Befragung. Sie wurden abgeschickt durch:\n' . '$Config{'realname'} ($Config{'email'}) on $date\n';
# Prüft die Option print_config und handelt entsprechend
if (@Print_Config) {
foreach $print_config (@Print_Config) {
if ($Config{$print_config}) {
$message .= '$print_config: $Config{$print_config}\n\n';
}
}
}
# Alphabetisch sortieren, falls verlangt #
if ($Config{'sort'} eq 'alphabetic') {
foreach $field (sort keys %Form) {
# If the field has a value or the print blank fields option #
# is turned on, print out the form field and value. #
if ($Config{'print_blank_fields'} || $Form{$field} ||
$Form{$field} eq '0') {
$message .= '$field: $Form{$field}\n\n';
}
}
}
# Felder nach angegebener Reihenfolge sortieren, falls verlangt #
elsif ($Config{'sort'} =~ /^order:.*,.*/) {
# Remove extraneous line breaks and spaces, remove the order: #
# directive and split the sort fields into an array. #
$Config{'sort'} =~ s/(\s+|\n)?,(\s+|\n)?/,/g;
$Config{'sort'} =~ s/(\s+)?\n+(\s+)?//g;
$Config{'sort'} =~ s/order://;
@sorted_fields = split(/,/, $Config{'sort'});
# For each sorted field, if it has a value or the print blank #
# fields option is turned on print the form field and value. #
foreach $sorted_field (@sorted_fields) {
if ($Config{'print_blank_fields'} || $Form{$sorted_field} || $Form{$sorted_field} eq '0') {
$message .= '$sorted_field: $Form{$sorted_field}\n\n';
}
}
}
# Ansonsten in der angegeben Reihenfolge verschicken #
else {
# For each form field, if it has a value or the print blank #
# fields option is turned on print the form field and value. #
foreach $field (@Field_Order) {
if ($Config{'print_blank_fields'} || $Form{$field} || $Form{$field} eq '0') {
$message .= '$field: $Form{$field}\n\n';
}
}
}
# System Umgebungsvariablen mit in die Nachricht einpacken #
foreach $env_report (@Env_Report) {
if ($ENV{$env_report}) {
$message .= '$env_report: $ENV{$env_report}\n';
}
}
# Zusammenstellen der Kommandozeile für späteren Systemaufruf
$commandline = $mailprog;
$commandline .= $message;
$commandline .= "-s "$betreff" " if $betreff;
$commandline .= "-t "$recipients" " if $recipients;
# $commandline .= "-f $config{'email'} " if $config{'email'};
# Senden der Email
system($commandline);
Dummerweise kann ich nichts ausprobieren, bis das Skript live geht, ich habe keinen Zugang zum Server.
Gruß,
Tobias
Moin Tobias,
syntax:
Blat <filename> -t <recipient> [optional switches (see below)]
Blat -install <server addr> <sender's addr> [<try>[<port>[<profile>]]] [-q]
Blat -profile [-delete | "<default>"] [profile1] [profileN] [-q]
Blat -h [-q]
ich stand vor einer Weile vor dem selben Problem. Dabei ist folgendes Perlmodul herausgekommen:
package Blat;
################################################################################
# #
# #
# #
# #
# and/or modify it under the same terms as Perl itself. #
# #
################################################################################
use strict;
use vars qw(
@EXPORT
@ISA
);
################################################################################
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(
send_blat
);
sub get_list ($) {
my $list = shift;
return $list if (defined $list and not ref $list and length $list);
return join (', ',@$list) if (ref $list);
'';
}
# to => To (string oder arrayref)
# cc => Cc (string oder arrayref)
# bcc => Bcc (string oder arrayref)
# subject => Subject
# from => From
# reply => Reply-To
# body => Mail Body
# }
# send_blat ({
# to => 'mymother@herdomain.com',
# cc => [other@otherdomain.com', 'mybrother@hisdomain.com'],
# subject => 'Hey, I found a nice module!',
# from => 'me@mydomain.com',
# body => "Hi!\nI found this very nice package Blat.pm.\n\n Regards - me. ;-))"
# }) or die "could not send mail.";
sub send_blat {
my $param = shift;
my $to = {
-to => get_list($param -> {to} || ''),
-cc => get_list($param -> {cc} || ''),
-bcc => get_list($param -> {bcc} || '')
};
my $subject = $param -> {subject};
my $from = $param -> {from};
for ($subject, $from) {
$$_ =~ s/"/\"/g;
$$_ =~ y/\n/ /s;
}
my $body = $param -> {body};
$body =~ s/^.$/. /gm;
my $reply='';
if (defined $param->{reply} and length $param->{reply}) {
$reply = $param->{reply};
$reply =~ s/"/\"/g;
$reply =~ y/\n/ /s;
$reply = qq[-replyto "$reply" ];
}
my $command = '| blat - -q -mime -noh2 -f "'.$from.'" -s "'.$subject.'" '.$reply
# ^ ^ ^ ^
# | | | |
# | | | -- no X-Mailer Header # | | -------- encode Quoted Printable
# | ------------ quiet mode (no output to STDOUT) # --------------- mail body from STDIN
#
. join ' ' => map {
my $ret = $to -> {$_};
if (defined ($ret) and length ($ret)) {
$ret =~ s/"/\"/g;
$ret =~ y/\n/ /s;
$ret =~ s/[1]*://;
$ret = qq[$_ "$ret"]
}
$ret || ();
} keys %$to;
open MAIL, $command or return;
print MAIL $body or return;
close MAIL and return 1;
# anything failed
#
return;
}
1;
Verbesserungsvorschlaege erwuenscht ;-)
HTH &
Viele Gruesse,
n.d.p.
^: ↩︎
Moin, Moin,
Danke für das Modul! Hast Du es schon mal genutzt?
Da ich mit Perl recht unsicher bin, noch mal zur Bestätigung, ob ich es verstanden habe:
In meinem Skript muss ich das Modul am Anfang mit
use Blat;
einbinden.
Danach sollte mir dann durch das Modul die Routine send_blat () zur Verfügung stehen.
Möchte ich also aus meinem Skript heraus Daten an Blat übergeben, sähe das in meinem Skript so aus:
send_blat ({
to => $Config{'recipient'},
cc => '',
subject => $Config{'subject'},
from => $Config{'email'},
body => $message
});
Beim Aufruf der Routine muss ich kein "&" vorstellen, oder?
Muss cc => einen Wert haben, damit es funktioniert? Was passiert, wenn $Config{'email'} == '' ?
$message enthält Text mit Steuerzeichen (\n etc.). Wird das richtig formatiert? Eigentlich schon, oder (print)?
Danke erstmal jedenfalls für die Hilfe!
Gruß,
Tobias
Moin,
Danke für das Modul! Hast Du es schon mal genutzt?
jup. sonst haette ich es nicht schreiben muessen ;-)
In meinem Skript muss ich das Modul am Anfang mit
use Blat;
Danach sollte mir dann durch das Modul die Routine send_blat () zur Verfügung stehen.
send_blat ({
to => $Config{'recipient'},
cc => '',
subject => $Config{'subject'},
from => $Config{'email'},
body => $message
});
Beim Aufruf der Routine muss ich kein "&" vorstellen, oder?
alles korrekt.
Muss cc => einen Wert haben, damit es funktioniert?
Was passiert, wenn $Config{'email'} == '' ?
nein. damit die Mail ankommt ist vor allem 'to' wichtig. ohne 'from' duerfte sich blat oder der smtp-Server beschweren.
der rest ist optional, sollte aber angegeben werden, wenn er gebraucht wird (subject, body, macht alles irgendwie sinn ;-)
wenn du -w benutzt und subject, body oder from undefined laesst, duerfte es auch eine warnung geben. (nach nochmaligem ueberfliegen des codes ;)
$message enthält Text mit Steuerzeichen (\n etc.). Wird das richtig formatiert? Eigentlich schon, oder (print)?
ja, die Mail wird an Blat gepiped, dieses setzt sie dann in Quoted-Printable um. (wenn du das nicht willst, kannst du das aendern an der Stelle wo $command zusammengebaut wird)
Tip: falls du sowas brauchst...: http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/selfforum/selfforum-cgi/shared/CheckRFC.pm?only_with_tag=HEAD, damit kannst du beispielsweise Emailadressen ueberpruefen.
Viele Gruesse,
n.d.p.
Hi,
falls du das Script in einer Win32 Umgebung lediglich testen willst, bist du ggf. auch damit gut beraten:
http://i-netlab.de/offonline/fakesendmail.htm
Rolf