E-Mail Macro fuer DI-Studio User-Written-Transformation

Aus BI-Snippets - Business Intelligence Code und Module
Wechseln zu: Navigation, Suche

Kennen Sie das Problem? Sie möchten aus einem DI-Studio-Job heraus E-Mails verschicken, allerdings bieten die vom DI-Studio mitgelieferten On-Board-Transformationen hierfür keinerlei Funktionsumfang? Hier lautet die Devise "Selbst ist der Mann!": Warum nicht selbst einmal eine Transformation erstellen?! Denn denkbare Use-Cases gibt es mehr als genug und lassen sich ohne große Überlegungen aufzählen: Z.B. um innerhalb eines komplexen Jobs im Batchbetrieb über den Ablaufstatus zu informieren oder auch um einen standardisierten E-Mail Versand als Distributionsweg im Reporting zu erschließen! Wie dem auch sei, hier finden Sie ein kleines Makro, welches über eine User-Written-Transformation aus dem DI-Studio aber auch aus "normalem" SAS-Code heraus aufgerufen werden kann.

Kleiner Tipp: Den Makro-Code niemals direkt im Codefenster der Transformation pflegen, hier lieber nur den Makroaufruf einfügen. Dies hat den Vorteil, dass bei Änderungen in der Makrologik nur das Makro und nicht alle Jobs welche die Transformation verwenden, auf die folgende Umgebung deployed werden müssen. Das Makro ist dann selbstverständlich in der SAS autocall library zu hinterlegen.

Die hier gezeigte SAS-Makro-Source ist für eine SAS-Installation im UNIX- bzw. LINUX-OS entwickelt worden, ist jedoch ohne großen Auwand nach WINDOWS protierbar und bietet dabei folgenden Funktionsumfang:

  • E-Mail Versand an mehrere Empfänger
  • formatierbarer Messagebody
  • bis zu n-Anhänge welche ab parametrisierbarem Schwellwert via UNIX-Shell-Skript komprimiert (gzip) werden
  • Prüfroutine welche evaluiert, ob einzelne Anhänge aber auch die Gesamtzahl aller Anhänge die konfigurierte Anhanggröße des Exchangeservers überschreitet und gegebenenfalls eine entsprechende Information an den Messagebody anhängt. Anhänge, welche die konfigurierte Anhanggröße übersteigen, werden nicht an die Email angehangen.
  • optionales Housekeeping für Anhänge
  • frei wählbare Satzlänge pro Anhang


<syntaxhighlight lang="SAS" line="1" >

/********************* Standard Programm Header *****************************************
* Programm     : Transformation Einfaches E-mailling  
* Beschreibung : Ziel der Tranformation ist es einen komfortablen E-Mail-Versand aus SAS heraus zu ermöglichen 
*
* Ersteller    : Christopher Gies | accantec consulting AG
* Datum        : 08.07.14
*
* Parameter    :  v_empfaenger    = Empfänger bzw. Empfängerliste der E-Mail
*                                   FORMAT: "max.mustermann@accantec.de" "theo.test@accantec.de"
*                 v_betreff       = Betreff der E-Mail
*                                   FORMAT: Beispielbetreff
*                 v_nachricht     = Nachrichtenbody der E-Mail
*                                   FORMAT: "Zeile 1" / "Zeile 2" / "Zeile 3" / ... / "Zeile n"
*                 v_anhang        = relativer Pfad des E-Mail-Anhangs
*                                   FORMAT: "Pfad Anhang 01" "Pfad Anhang 02" "Pfad Anhang n"
*                 v_schwellwert   = Schwellwert in KB ab welchem Anhänge komprimiert werden
*                                   FORMAT: "1024" "1024" "512"
*                 v_lrecl         = Record-Length (Zeilenlänge) der zu übertragenden Datei
*                                   FORMAT: "2048" "512" "1024"
*                 v_flgDelete      = Flag ob Datei nach Transfer aus dem Dateiverzeichnis gelöscht werden soll
*                                   FORMAT: "Y" "Y" "N"
*
***************************** ToDo ******************************************************
*
* Logik für Nachrichtenbody optimieren, v_nachricht mit formatted put Code blegen
*
***************************** Änderungen ************************************************
*
*  Version    Datum      Autor   Beschreibung der Änderung
*
*  V0.1       08.07.14   ChG     Initale Erstellung 
*  V1.0       20.10.14   ChG     Erweiterung: Wenn Anhang <= 1 KB wird dieser nicht angehangen
*                                Erweiterung: Wenn die Summe aller Anhang <10MB größer als die max. konf. Anhanggröße des Exchange Servers ist,
*                                   wird anstatt der Email eine Warnung versendet.
*  V1.1       12.11.14   ChG     Erweiterung: CSV und TXT Anhänge werden mit Enconding latin1 versendet
*
****************************************************************************************/

/***********************************************************************/
/***  Globale Variablen definieren und vorbelegen                    ***/
/***********************************************************************/
/***/     %global   v_maxFileSizeAttach;                            /***/
/***/     %let      v_maxFileSizeAttach = 10240;                    /***/
/***********************************************************************/

%macro blb_032_sendmail(v_empfaenger=, v_betreff=, v_nachricht=, v_anhang=, v_schwellwert=, v_lrecl=, v_flgDelete=);
/***********************************************************************/
/*** Anzahl Anhänge ermitteln und Variablen vorbereiten              ***/ 
/***********************************************************************/
 %let i = 1;

 %do %while (%scan(&v_anhang.,&i.,%str( ),Q) ne %str( ));

 %let v_anhang&i. = %sysfunc(compress(%scan(&v_anhang.,&i.,%str( ),Q),'"'));
 %*put v_anhang&i. = *&&v_anhang&i..*;

 %let v_schwellwert&i. = %sysfunc(compress(%scan(&v_schwellwert.,&i.,%str( ),Q),'"'));
 %*put v_schwellwert&i. = *&&v_schwellwert&i..*;

 %let v_lrecl&i. = %sysfunc(compress(%scan(&v_lrecl.,&i.,%str( ),Q),'"'));
 %if &&v_lrecl&i. = %str() %then %let v_lrecl&i. = 256;
 %*put v_lrecl&i. = *&&v_lrecl&i..*;

 %let v_flgDelete&i. = %sysfunc(compress(%scan(&v_flgDelete.,&i.,%str( ),Q),'"'));
 %if &&v_flgDelete&i. = %str() %then %let v_flgDelete&i. = Y;
 %*put v_flgDelete&i. = *&&v_flgDelete&i..*;

 %let i = %eval(&i. + 1);
 %end;

/* i um 1 verringern um Anzahl der Anhänge korrekt auf i zu halten. */
 %let i = %eval(&i. - 1);
 %*put i = &i.;

/***********************************************************************/
/*** Datei komprimieren                                              ***/
/***********************************************************************/
/* Zählvariablen initialisieren */
 %let v_FileSizeInsg = 0;
 %let v_anzFile2large = 0;

 %do j = 1 %to &i.;
 data _null_;
 
   %*put v_anhang&j. = &&v_anhang&j..;
   %*put v_schwellwert&j. = &&v_schwellwert&j..;

   /* Hier ist der Pfad des aufzurufenden Skriptes anzupassen */
   _cmd = "../checkSizeAndCompFile.sh &&v_anhang&j.. &&v_schwellwert&j..";
   _rc = system(_cmd);
   put _rc=;
   
   /* Wenn File gezippt wurde, wird _rc mit 1 sonst mit 0 belegt */
   if _rc = 1 then do;
     call symput ("v_anhang&j.","&&v_anhang&j...gz");
   end;
   if _rc = 0 then do;
     call symput ("v_anhang&j.","&&v_anhang&j..");
   end;
 run;
 
 /* Zweiter Data-NULL damit &&v_anhang&j.. korrekt aufgelöst wird. */
 data _null_;
 
   /* Ermittle Dateigröße in KB */
   length  filesize 8
           file2large 8; 
   drop rc fid close; 
   rc=filename("myfile","&&v_anhang&j.."); 
   fid=fopen("myfile"); 
   filesize=ceil(input(finfo(fid,"File Size (bytes)"),32.) / 1024); 
   close=fclose(fid); 
   
   if filesize > &v_maxFileSizeAttach. then
     file2large = 1;
   else
     file2large = 0;
   
   call symput ("v_File2large&j.",strip(file2large));
   call symput ("v_filesize&j.",strip(filesize));
 run;
 
 %let v_anzFile2large=%eval(&v_anzFile2large. + &&v_File2large&j..);
 
 /* Nur die Summe aller Anhänge < v_maxFileSizeAttach sind dafür relevant ob die Email versendet werden kann, */
 /* da Anhänge > v_maxFileSizeAttach ohnehin nicht an die Email angehangen werden.                            */
 %if &&v_filesize&j.. < &v_maxFileSizeAttach. %then %do;
   %let v_FileSizeInsg=%eval(&v_FileSizeInsg. + &&v_filesize&j..);
 %end;
 
 %*put v_anhang&j. = *&&v_anhang&j..*;
 %*put v_anzFile2large = *&v_anzFile2large.*;
 %*put v_filesize&j. in KB = *&&v_filesize&j..*;
 %*put v_FileSizeInsg in KB = *&v_FileSizeInsg.*;
 %end;

/***********************************************************************/
/*** Makrovariable v_nachricht parsen *WORKAROUND*, da formatted put ***/
/*** in diesem Kontext nicht mit mehreren Zeilen zurechtkommt.       ***/
/*** Eigentliche Ursache des Problems ist nicht geklärt              ***/
/***********************************************************************/
 %let k = 1;

 %do %while (%scan(&v_nachricht.,&k.,%str(/),Q) ne %str( ));

 %let v_zeile&k. = %sysfunc(compress(%scan(&v_nachricht.,&k.,%str(/),Q),'"'));
 %*put v_zeile&k. = &&v_zeile&k..;

 %let k = %eval(&k. + 1);
 %end;

 %let k = %eval(&k. - 1);
 %put k = &k.;

/***********************************************************************/
/*** Datei versenden                                                 ***/
/***********************************************************************/
filename v_mail email 
   to=(&v_empfaenger.)
   subject="&v_betreff."
 %*put v_anzFile2large= &v_anzFile2large.;
 %*put i= &i.;
 /* Anhang Statement nur generieren wenn die Anzahl der zu großen Dateien (v_anzFile2large) kleiner als die Anzahl aller Dateien ist und */
 /* die Summe aller Dateianhänge (v_FileSizeInsg) bezogen auf den ben. Plattenplatz kleiner gleich der zulässigen Gesamtanhanggröße des Exchange Servers ist.  */
 %if %length(&v_anhang.) > 0 and &v_anzFile2large. < &i. and &v_FileSizeInsg. <= &v_maxFileSizeAttach. and &v_FileSizeInsg. > 0 %then %do;
   attach=(
   %do j = 1 %to &i.;
     %if &&v_filesize&j.. <= &v_maxFileSizeAttach. and &&v_filesize&j.. > 0 %then %do;
       /* Formatiert CSV und TXT-Files mit latin1 (--> Windows-Encoding) damit Zeilenumbrüche unter Windows korrekt dargestellt werden */
       %if "%scan(&&v_anhang&j..,-1,%str(.))" = "txt" or "%scan(&&v_anhang&j..,-1,%str(.))" = "csv" %then %do;
         "&&v_anhang&j.." LRECL=&&v_lrecl&j.. CONTENT_TYPE="text/plain" outencoding="latin1" 
       %end;
       %else %do;
         "&&v_anhang&j.." LRECL=&&v_lrecl&j.. CONTENT_TYPE="application/octet-stream" 
       %end;
     %end;
   %end;
   )
 %end;
 ;

data _null_ ;
 file v_mail ;
 %if &v_FileSizeInsg. > &v_maxFileSizeAttach. %then %do;
   put "Die Summe aller Dateien <10MB überschreitet die maximal zulässige Anhanggröße des MS Exchange Servers von %eval(&v_maxFileSizeAttach. / 1024)MB. " ;
 %end;
 %else %do;
   %do j = 1 %to &k.;
     put "&&v_zeile&j.. " ;
   %end;
   %do j = 1 %to &i.;
     %if &j. = 1 and &v_anzFile2large. > 0 %then %do;
       put " " ;
       put "******************************" ;
       put " " ;
       put "Folgende Dateianhänge konnten aufgrund ihrer Größe (>10MB) nicht an die E-Mail angehangen werden. Die Anhänge wurden im UNIX-Dateisystem belassen, bitte wenden Sie sich an ihren zuständigen Administrator:" ;
     %end;
     %if &&v_filesize&j.. > &v_maxFileSizeAttach. %then %do;
       put "&&v_anhang&j.."; 
     %end;
   %end;
 %end;
run;

/***********************************************************************/
/*** Datei löschen                                                   ***/
/***********************************************************************/
 %do j = 1 %to &i.;
 %if "&&v_flgDelete&j.." = "Y" and &&v_filesize&j.. <= &v_maxFileSizeAttach. %then %do;
   data _null_;
     _cmd = "rm &&v_anhang&j..";
     _rc = system(_cmd);
     if _rc ne 0 then put "WARNING: Datei &&v_anhang&j.. im Quellverzeichnis konnte nicht gelöscht werden";
   run;
 %end;
 %end;
%mend blb_032_sendmail;

</syntaxhighlight>

Anbei auch das UNIX/LINUX-Shell-Skript welches zur Komprimierung der Anhänge benötigt wird:


<syntaxhighlight lang="BASH" line="1" >

#!/usr/bin/bash

# --- Standard Programm Header ----------------------------
# Programm     : checkSizeAndCompFile.sh  
# Beschreibung : Das Shell-Skript pueft eine uebergebene Datei auf deren Groeße und komprimiert diese, 
#         wenn sie groeßer wie der uebergebene Schwellwert ist.
#
# Ersteller    : Christopher Gies | accantec consulting AG
# Datum        : 08.07.14
#
# --- Änderungen ------------------------------------------
#
#  Version    Datum      Autor   Beschreibung der Änderung
#
#  V0.1       08.07.14   ChG     Initale Erstellung 
#
# ---------------------------------------------------------

QUELLPATH=$1
SCHWELLWERT=$2

DATSPACE=`du -k $QUELLPATH | awk '{print $1}'`
echo $QUELLPATH $DATSPACE

# alle Dateien groesser als der Schwellwert werden komprimiert
if [ $DATSPACE -gt $SCHWELLWERT ]
then
gzip -f $QUELLPATH
exit 1
else
exit 0
fi

</syntaxhighlight>