Dokument via E-Mail versenden II

Dieser Tip ist als Ergänzung zum alten Tip Dokument via E-Mail versenden zu sehen. Grund für die Ergänzung sind weitere Möglichkeiten der Gestaltung der E-Mail und deren Versand über eine gesicherte Verbindung.

In diesem Zusammenhang soll auch noch einmal erwähnt werden, dass die Erzeugung von PDF-Dateien als Anhang von E-Mails nicht mehr mit dem Programm der amerikanischen Firma Lincoln & Co erfolgen sollte. Nach einem Verkauf der Firma ist das Programm nicht mehr am Markt erhältlich und es gibt keinen Support mehr. Abgesehen davon unterstützt es einige neue Funktionen von print2forms nicht. 1)

Als Alternative bietet sich das Programm GhostPCL an. Damit lassen sich nicht nur PDF-Dateien erzeugen, sondern auch fast alle Arten von Bilddateien generieren, sodass zur Not auch noch ein Fax-Anschluss realisiert werden könnte. 2)

Wie konkret eine PDF-Datei mit print2forms erzeugt werden kann, ist zum einen dem Tip PDF-Datei erzeugen zu entnehmen. Zusätzlich wird hier das Vorgehen beim Einsatz mit Perl gezeigt.

Der neue Ansatz

Die Gestaltung ansprechender E-Mail Inhalte erfordert heutzutage den Einsatz von HTML für den lesbaren Inhalt der Mail. Gleichzeitig sollte aber auch eine reine Textversion dieses Inhalts in der Mail enthalten sein, weil aus Gründen der Sicherheit viele Mail-Clients nur reine Texte anzeigen und darauf verzichten, den durchaus korrumpierbaren HTML-Teil zu interpretieren.

Deshalb muss die zu erzeugende E-Mail aus drei Teilen bestehen, die richtig verschachtelt werden müssen. Der Text der E-Mail zusammen mit dem oder den Anhängen bildet den äusseren Rahmen der Mail (multipart/mixed), und der Inhalt ist seinerseits in zwei alternativ anzuzeigende Text- und HTML-Inhalte aufgeteilt (multipart/alternative).

Variable Inhalte

Grundlage für die dynamischen Inhalte ist ein einfacher Schablonen-Mechanismus, der Texte innerhalb einer HTML- oder Text-Vorlage gegen Texte ersetzt, die mit print2forms ermittelt worden sind. Das ist am einfachsten mit dem Perl-Paket 'HTML:Lite' und dem Paket 'Template' zu realisieren. 3) 4) 5) 6)

Im nachfolgenden Skript wird als Schablone für den HTML-Teil der E-Mail eine Datei mit dem Namen 'mail.html' eingesetzt, die hier als erstes abgebildet ist. In dieser HTML-Datei sind die variablen Texte in eckigen Klammern mit Prozentzeichen notiert. Diese Schablone kann auch Bezug auf externe Ressourcen wie etwa auf Web-Servern gelagerte Bilder (Firmenlogos) nehmen. 7)

mail.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
  <head>
    <title>Ihre Bestellung [% Bestellnummer %]</title>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
  </head>
 
  <body style="font-size: 70%; font-family: Verdana, Arial, Helvetica, MS Sans Serif; padding: 0px; margin: 0px; background-color: #eee">
 
    <div style="width: 600px; margin: 8px;
                background-color: white; 
                background-image: url(https://www.spe-systemhaus.de/imgs/SPEMAIL.GIF);
                background-repeat: no-repeat; 
                border: 1px solid #000;">
 
      <div style="text-align: right; margin-top: 120px; margin-bottom: 3em; margin-right: 75px;">
        SPE Systemhaus GmbH<br/>
        Waldstrasse 7<br/>
        D-63150 Heusenstamm<br>
        <br/>
        Tel.: +49 6106 860560<br/>
        Fax: +49 6106 860583
      </div>
 
      <div style=" margin-left: 15px; margin-right: 110px;">
 
        <h1 style="color: #CC0000; font-size: 110%; margin-top: 1em; margin-bottom: 2em;">
          Lieferschein für Bestellung [% Bestellnummer %]
        </h1>
 
        <p>[% Anschrift1 %]<br/>
           [% Anschrift2 %]<br/>
           [% Anschrift3 %]<br/>
           [% Anschrift4 %]<br/>
        </p>         
 
        <br/>
 
        <p>Sehr geehrte Damen und Herren,</p>
 
        <p>Mit dieser automatisch erzeugten Nachricht erhalten Sie den Lieferschein 
           zu Ihrer Bestellung [% Bestellnummer %].</p>
 
        <p style="margin-top: 2em;">Mit freundlichen Grüßen<br/>
          <span style="color: #CC0000;"><b>SPE Systemhaus GmbH</b></span>
        </p>
      </div>
 
      <div style="text-align: right; margin-top: 4em; margin-right: 75px;">
        Geschäftsführer: Dipl. Inform. Volker Süßmann<br/>
        Amtsgericht: Offenbach am Main, HRB 8132<br/>
        <br/>
        USt-IdNr.: DE113585835<br/>
        WEEE-Reg-Nr.: DE97546258<br/>
        <br/>
        https://www.spe-systemhaus.de<br/>
        <br/>
      </div>
    </div>
  </body>
</html>


Auch im Text-Teil der E-Mail werden die variablen Daten mit eckigen Klammern und Prozentzeichen markiert. Der Inhalt des Text-Teils kann vollkommen unabhängig vom HTML-Teil formuliert werden. Aufgrund der Spezifikationen für SMTP ist darauf zu achten, dass im Text-Teil für das Zeilenende lediglich Linefeeds genutzt werden dürfen - eventuell vorhandene Carriage Returns erzeugen Leerzeilen.

mail.txt
Lieferschein zur Bestellung [% Bestellnummer %]
 
Sehr geehrte Damen und Herren,
 
im Anhang finden Sie den Lieferschein zu Ihrer Bestellung.
 
Mit freundlichen Grüßen
SPE Systemhaus GmbH


Beide Dateien müssen im gleichen Verzeichnis abgelegt werden, wie das nachfolgende Skript!

Das Skript

Das Perl-Skript 8) liest zunächst aus der vom print2forms-Gateway erzeugten Kontrolldatei die variablen Daten aus. Anschliessend wird die PCL-Datei mit dem Lieferschein durch den Aufruf von GhostPCL in eine PDF-Datei konvertiert. 9)

[Time]13.03.23 08:46:30
[Computer]kvasir
[User]Volker
[Model]p2f Gateway
[Job]Lieferschein
[File]1
[Process]ANLAGEN.XML
[0102C10000]                                                         00001/3
[0103390000]                                                         1704
[0103750000]       Kunde AG
[0103B10000]       z. Hd. Hr. X. Kunde                               347-57897
[0104290000]       Kundengasse 19                                    15595
[0104650000]       D-48535 Kundendorf
[0104A10000]                                                         Hr. G. Muster
[0105190000]                                                         13.03.2023
[0106810000]      1   L1BL50   Schaltlitze 0,14x50 m blau     St     330      0    330
[0106F90000]      2   L1BL500  Schaltlitze 0,14x500 m blau    St      50      0     50
[0107710000]      3   USB2AA1  USB Kabel A/A Stecker 1.0 m    St     210     21    189
[Page]
[End]


Der strukturelle Aufbau des Skriptes ist daher wie folgt:


email.pl
#!/usr/bin/perl
#
# Command:    perl email.pl "%1" "%2" "%4"
#
# Call:       perl email.pl Scriptpath Spoolpath Filename
#
use strict;
use warnings;
use MIME::Lite;
use Template;
 
#------------------------------------------------------------------------------#
 
my $Script = $ARGV [0];    # Params: Scriptpfad Spoolpfad Dateiname
my $Spool  = $ARGV [1];
my $Name   = $ARGV [2];
 
my $PCLFile = $Spool . "\\" . $Name . ".pcl";
my $CTLFile = $Spool . "\\" . $Name . ".ctl";
my $PDFFile = $Spool . "\\" . $Name . ".pdf";
my $PJLFile = $Spool . "\\pjl.pjl";
 
my ($Anschrift1, $Anschrift2, $Anschrift3, $Anschrift4, $Bestellnummer, 
    $Liefernummer, $Id, $mail_html, $mail_text);
 
open (CTL, "<$CTLFile") or die "Kann $CTLFile nicht finden\n";
 
# Auf gültige Kontrolldatei prüfen --------------------------------------------#
 
$Id = <CTL>;
$Id = <CTL>;
chomp ($Id);
unless ($Id =~ /\[p2f\].*/) { die("Keine gültige Kontrolldatei"); }
 
# Daten aus Kontrolldatei auslesen --------------------------------------------#
 
while(<CTL>)
  {
    chomp;
 
    if (/^\[0102C10000\] +([0-9]+).*/) { $Liefernummer = $1; }
 
    if (/^\[0104290000\]/) { $Bestellnummer = substr ($_, 69, 5); }
    if (/^\[0103750000\]/) { $Anschrift1    = substr ($_, 12, 50); }
    if (/^\[0103B10000\]/) { $Anschrift2    = substr ($_, 12, 50); }
    if (/^\[0104290000\]/) { $Anschrift3    = substr ($_, 12, 50); }
    if (/^\[0104650000\]/) { $Anschrift4    = substr ($_, 12, 50); }
    if (/^\[0104A10000\]/) { last; }
  }
 
close (CTL);
 
# Lieferschein als PDF-Datei erzeugen -----------------------------------------#
 
open my $fh, ">:raw", $PJLFile;
 
print $fh "\x1b%-12345X\x0A" .
          "\x40PJL DEFAULT PDFMARK = \"[ " .  
          "/Author (Meine Firma) " .
          "/Creator (print2forms) " .
          "/Keywords (Lieferschein, " . $Liefernummer . ") " .
          "/Title (Lieferschein " . $Liefernummer . ") " .
          "/DOCINFO pdfmark \"";
 
close ($fh);
 
my $Document = $Spool . "\\LI-" . $Liefernummer . ".pdf";
 
my $Cmd = "\"" . $Script . "\\gpcl6win64.exe\"" .
                           " -dNOPAUSE" .
                           " -sDEVICE=pdfwrite" .
                           " -dPDFFitPage" .
                           " -dPDFA=1" .
                           " \"-sOutputFile=" . $Document . "\"" .
                           " \"" . $PJLFile . "\"" .
                           " \"" . $PCLFile . "\"";
system ($Cmd);
 
# Variablen für Schablonen vorbereiten ----------------------------------------#
 
my $tt = Template->new ();
 
my %params = (Anschrift1 => $Anschrift1,
              Anschrift2 => $Anschrift2,
              Anschrift3 => $Anschrift3,
              Anschrift4 => $Anschrift4,
              Bestellnummer => $Bestellnummer);
 
$tt->process ('mail.html', \%params, \$mail_html);
$tt->process ('mail.txt', \%params, \$mail_text);
 
# E-Mail zusammenbauen aus Text, HTML und Anhang ------------------------------#
 
my $Empfaenger = "spe\@spe-systemhaus.de"; 
 
my $msg = MIME::Lite->new(From        => 'abc@spe-systemhaus.de',
                          To          => $Empfaenger, 
                          Subject     => "Lieferschein $Liefernummer", 
                          Type        => 'multipart/mixed');
 
# Innerer Rahmen als multipart/alternative ------------------------------------#
 
my $alternative = $msg->attach (Type => 'multipart/alternative');
 
$alternative->attach (Type => 'text/plain', Data => $mail_text);
$alternative->attach (Type => 'text/html',  Data => $mail_html);
 
$msg->attach (Type     => 'application/pdf',
              Path     => $Document,
              Filename => "Lieferschein $Liefernummer.pdf");
 
MIME::Lite->send('smtp', "mein.smtp.de", 
                 AuthUser=>'mein_benutzername',
                 AuthPass=>'mein_passwort',
                 SSL=>1,
                 Port=>465,
                 Debug=>0,
                 Timeout=>60);
$msg->send;
 
unlink ($PCLFile);    
unlink ($CTLFile);    
unlink ($Document);
 
exit 0;


Das Ergebnis

Nutzt der Empfänger der E-Mail einen Mail-Client, der nur Texte anzeigt, sollte dann etwas ähnliches wie das hier zu sehen sein: 11)



Erlaubt der Mail-Client die Anzeige von HTML-Inhalten, zeigt sich in etwa folgendes:



Öffnet man die angehängte PDF-Datei und betrachtet deren Eigenschaften, sieht man, dass die von print2forms erzeugten Meta-Daten auch korrekt eingebaut worden sind.



1)
Vornehmlich Probleme mit Farbdruck, gedrehtem Text und vor allem alles im Kontext der Nutzung von Unicode.

2)
GhostPCL steht unter einer modifizierten GNU-Lizenz - der AGPL - die auch die kommerzielle Nutzung erlaubt.

3)
Das als möglicherweise besser geeignet erscheinende Perl-Paket MIME::Lite:TT:HTML ist nicht in der Lage, eine E-Mail mit der gewünschten Struktur zu erstellen. Wenn allerdings nur ein HTML- oder ein Text-Teil zusammen mit einem oder mehreren Anhängen gefordert sind, ist das Paket durchaus einsetzbar.

4)
Ist auf dem Rechner Strawberry Perl installiert, muss das Paket 'HTML:Lite' nachinstalliert werden. Das geschieht am einfachsten in einer Eingabeaufforderung. Dort wird der Befehl  cpan HTML:Lite  ausgeführt. Das Paket wird dann aus dem Internet geladen und auf dem aktuellen Rechner übersetzt und installiert.

5)
Bei älteren Versionen von ActiveState Perl kann das Paket 'HTML:Lite' über den eingebauten Paket-Manager bereitgestellt werden. Das geschieht am einfachsten in einer Eingabeaufforderung. Dort wird der Befehl  ppm install HTML:Lite  ausgeführt. Das Paket wird dann aus dem Internet geladen und auf dem aktuellen Rechner übersetzt und installiert.

6)
Die Nutzung von neueren Versionen von ActiveState Perl (ab 5.28) wird von der SPE Systemhaus GmbH aus lizenzrechtlichen Gründen nicht mehr empfohlen.

7)
Im Beispiel wird ein Hintergrundbild über die Einbindung von CSS genutzt. Auffällig ist hier, daß alles CSS inline notiert ist. Das muss aber nicht so sein, sondern kann auch über eine auf einem Web-Server hinterlegte CSS-Datei realisiert werden, was die E-Mail sogar deutlich kleiner werden liesse.

8)
Aus Gründen der Kompatibilität mit den bisherigen Lösungen ist das Skript ebenfalls noch in Perl formuliert, obwohl die SPE Systemhaus GmbH für aktuelle Entwicklungen eher den Einsatz von PHP als Skriptsprache favorisiert. Siehe dazu die Tips Test von PHP Skripten und PHP-Skript ohne Gateway testen.

9)
Für das Beispiel in diesem Tip wird auf die mit der Free-Edition von print2forms mitgelieferte Beispiel-Applikation zurückgegriffen, die im Tutorial beschrieben ist.

10)
Die im Skript verwendeten E-Mail-Adressen sind natürlich anzupassen. Insbesondere ist die Empfängeradresse seltenst konstant, sondern wird den Druckdaten oder gar einer Datenbank entnommen. Das wurde aber wegen der Übersicht­lichkeit des Beispiels hier einmal bewusst außer Acht gelassen.

11)
Die Screenshots wurden vom Mail-Client Thunderbird erstellt.