Dieses Package erlaubt es Text- und HTML-E-Mails aus PL/SQL zu versenden

mam_mail

Features

  • Unformatierte Mails.
  • HTML-Mails
  • Versand auch an CC und BCC
  • Adressen mit Alias möglich
  • Beliebige Anhänge als CLOB, BLOB oder iCalendar

Einschränkungen

Diese Lösung geht davon aus, dass du einen internen smtp-host verwendest. Wenn du z.B. Gmail verwenden willst, dann suche nach stunnel oder "UTL_SMTP over SSL"

Oder verwende utl_smtp.auth

Tutorial

Es ist eine Überlegung wert einen Wrapper um dieses Package zu schreiben, der z.B. sicher stellt, dass in Test/Entwicklung Mails nur an Tester/Entwicker gehen, nicht an tatsächliche externe Adressen. Steven Feuerstein hat hierzu einen Artikel geschrieben:

Ein derartiger Wrapper kann auch verwendet werden um z.B. HTML-Mails mit einheitlichen Kopf- und Fußzeilen zu versehen und einheitliche Schriftarten als Standard vorzugeben

Allgemein

E-Mail Adressen können als kommaseparierte Liste angegeben werden

'meine.adresse@example.com,eine.andere.adresse@example.com'

Die Angabe von Aliasen ist möglich

'Meine Adresse <meine.adresse@example.com>,Eine andere <eine.andere.adresse@example.com>'

Wird immer derselbe Mailserver verwendet, dann kann es sinnvoll sein, diesen im Package Body für g_mailserver direkt einzufügen.

So einfach wie möglich

Der einfachste Aufruf versendet eine Textmail ohne Schnickschnack

BEGIN
    -- Du kannst diesen ersten Aufruf weglassen (siehe oben),
    -- wenn du den Defaultserver im Package Body hart kodierst.
    mam_email.setMailserver('my.mailserver.example.com');
    mam_email.sendSimple(
         'recipient@example.com'-- Empfänger
        ,'sender@example.com'-- Sender
        ,'Testmail'-- Betreff
        ,'Mailtext'-- Text der Mail
        );
END;

Einfache Testmail

Kurze Mail

Wenn der Mailtext (bei HTML-Mails inkl. Tags) nicht mehr als 1000 Zeichen hat.

BEGIN
    mam_email.setMailserver('my.mailserver.example.com');
    mam_email.send(
         'recipient@example.com'-- Empfänger
        ,'cc@example.com'-- Kopie-Empfänger
        ,'bcc@example.com'-- Blindkopie-Empfänger
        ,'sender@example.com'-- Sender
        ,'Testmail'-- Betreff
        ,'Dies ist eine Testmail'-- Unformatierter Text der Mail
        '<h2>Test</h2><p>Das ist eine Testmail</p>'-- Text der Mail als HTML
        );
END;

Kurze Mail mit HTML

Lange Mail

DECLARE
    textbody        mam_email.tbl_mailbody;
    htmlbody        mam_email.tbl_mailbody;
    lineNumber      PLS_INTEGER := 1;
BEGIN
    htmlbody(lineNumber).line  :=
        '<div style="font: 1em/100% Arial, sans-serif;">';
    lineNumber := lineNumber + 1;
    htmlbody(lineNumber).line  :=
        '<table style="font: 1em/100% Arial, sans-serif;" width="95%" '||
        'border="1" cellspacing="0" cellpadding="4"><tbody>'||
        '<tr style="background-color: #c8c8c8">'||
         '<th>Number</th>'||
         '<th>String</th>'||
        '</tr>';
    lineNumber := lineNumber + 1;
    htmlbody(lineNumber).line  :=
        '<tr>'||
        '<td>1</td>'||
        '<td>ABC</td>'||
        '</tr>';
    lineNumber := lineNumber + 1;
    htmlbody(lineNumber).line  := '</tbody></table>';
    lineNumber := lineNumber + 1;
    htmlbody(lineNumber).line  := '<p>A table and some text</p>';
    lineNumber := lineNumber + 1;
    htmlbody(lineNumber).line  := '</div>';

    lineNumber := 1;
    textbody(lineNumber).line  := 'Number|String';
    lineNumber := lineNumber + 1;
    textbody(lineNumber).line  := '------|------';
    lineNumber := lineNumber + 1;
    textbody(lineNumber).line  := '    1 | ABC';
    lineNumber := lineNumber + 1;
    textbody(lineNumber).line  := 'Alternative text if HTML is not displayed';

    mam_email.setMailserver('my.mailserver.example.com');
    mam_email.send(
         'recipient@example.com'-- Empfänger
        ,'cc@example.com'-- Kopie-Empfänger
        ,'bcc@example.com'-- Blindkopie-Empfänger
        ,'sender@example.com'-- Sender
        ,'Testmail'-- Betreff
        ,textbody-- Unformatted text
        ,htmlbody-- Text as HTML
        );
END;

Mail mit HTML Tabelle

Anhänge

DECLARE
    attachments     mam_email.tbl_attachments;
BEGIN
    attachments(1).fileCLOB := 'a,b,c,d';
    attachments(1).fileName := 'abc.csv';
    mam_email.setMailserver('my.mailserver.example.com');
    mam_email.send(
         'recipient@example.com'-- Empfänger
        ,'cc@example.com'-- Kopie-Empfänger
        ,'bcc@example.com'-- Blindkopie-Empfänger
        ,'sender@example.com'-- Sender
        ,'Testmail'-- Betreff
        ,'Mail with CLOB attachment'
        ,'<div style="font: 1em/100% Arial, sans-serif;">'||
         '<p>Mail with CLOB attachment</p>'||
         '</div>'
        ,attachments-- Attachments
        );
END;

Mail mit Anhang

Anhänge (iCal)

Zum Generieren eines Kalenderelements steht die Funktion mam_email.createEvent zur Verfügung. Die Endung .ical wird beim Dateinamen automatisch ergänzt, falls nicht vorhanden. Wird kein Dateiname angegeben, wird ein Default gesetzt

DECLARE
    attachments     mam_email.tbl_attachments;
BEGIN
    attachments(1).fileName := 'Invitation-test';
    attachments(1).fileICAL := mam_email.createEvent(
                         sender      => 'Matzberger Marcus '
                        ,startDate   => SYSDATE + 5/1440
                        ,endDate     => SYSDATE + 10/1440
                        ,subject     => 'Test Event'
                        ,description => 'Description for test event \n Another line'
                        ,vLocation   => 'Somewhere over the rainbow'
                        ,vAlarm      => '15'
                        );
    mam_email.setMailserver('my.mailserver.example.com');
    mam_email.send(
         recipient   => 'recipient@example.com'
        ,sender      => 'sender@example.com'
        ,subject     => 'Testmail'
        ,bodyText    => 'Mail with iCal attachment'
        ,bodyHTML    => '<div style="font: 1em/100% Arial, sans-serif;">'||
                        '<p>Mail with iCal attachment</p>'||
                        '</div>'
        ,attachments => attachments
        );
END;

Inline Bilder

Will man Bilder in HTML-Mails so einbinden, dass sie korrekt dargestellt werden, ist insbesondere bei Outlook die Auswahl nicht groß, da nur eine Möglichkeit funktioniert

Wird bei einem Anhang im attachments-Record das Attribut contentID belegt (z.B. 345678912), dann kann es in der HTML-Mail referenziert werden mit <img src="cid:345678912">

In diesem Beispiel wird das Bild aus einem base64-String in ein BLOB zurückcodiert um keine Abhängigkeiten für den Code zu haben. Das Bild könnte/sollte im echten Leben als BLOB aus einer Tabelle eingefügt werden

DECLARE
    tmpClob         CLOB;
    t_attachments   mam_email.tbl_attachments;

FUNCTION base64_decode
    (
     base64Data         IN CLOB
    )
    RETURN BLOB
IS

    position            PLS_INTEGER := 1;
    isLength            PLS_INTEGER;
    workLength          PLS_INTEGER := 48;
    readRawBuffer       RAW(32767);
    daten               VARCHAR2(32767);
    decodedBlob         BLOB := EMPTY_BLOB();

BEGIN

    dbms_lob.createTemporary(decodedBlob,TRUE,dbms_lob.CALL);
    isLength  := dbms_lob.getLength(base64Data);

    WHILE position <= isLength LOOP

        dbms_lob.read(base64Data,workLength,position,daten);
        readRawBuffer := utl_encode.base64_decode(utl_raw.cast_to_raw(daten));
        dbms_lob.writeAppend(
             decodedBlob
            ,utl_raw.length(readRawBuffer)
            ,readRawBuffer
            );

        position    := position + workLength;

    END LOOP;

    RETURN decodedBlob;

END base64_decode;

BEGIN

    tmpClob :=           'R0lGODlhoQHRAOYAAPR1efWBhfzZ2viipfeWme4lLO87QfilqPm1t/729vV/g/NjaPvQ0f74+PNtcf7x8e4qMfR6fvm0tvFQVvaKjveanfJgZfeeof3q6u0hKPq9v/FMUvm4uvJZXvvNz/mtsPBARe84P/7y8vBITvaPk+0fJvvJy/zc3u4uNO8yOe0gJ/3k5fFKUPrFxvNobfvHyfWGivJeY/zU1vaQlPrAwvBESvmws/BCSPmytPisrvq+wO80Ou4sM/FSWO82PO8wN/WEiO4nLfRzd/BHTMjIyNXV1faOkfRxdvFVWviqrf3j5Pecn//9/f/+/v/8/P3i4//7/P/7+//6+v3n6PJXXf7s7fvP0fego/eYm/zX2O4kK/7u7/iprPRwdP3s7P7t7vFUWf709f3o6firrfaSlfNrcPioq/zb3PaTlvaNkP7z9P3p6v3m5/V9gfJbYPzU1fJfZPaUl/vT1P3l5vq7vfrCxPJWW/zf4P3g4fzc3fze3/7v8PzV1/R3e+0dJP///yH/C1hNUCBEYXRhWE1QPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMwNjcgNzkuMTU3NzQ3LCAyMDE1LzAzLzMwLTIzOjQwOjQyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC';
    tmpClob := tmpClob||'8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxNSAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo5MzFFRUI0RTUwMjAxMUU2Qjg3NEY3NDNBNjMyRTEzRSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo5MzFFRUI0RjUwMjAxMUU2Qjg3NEY3NDNBNjMyRTEzRSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjkzMUVFQjRDNTAyMDExRTZCODc0Rjc0M0E2MzJFMTNFIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjkzMUVFQjRENTAyMDExRTZCODc0Rjc0M0E2MzJFMTNFIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+Af/+/fz7+vn49/b19PPy8fDv7u3s6+rp6Ofm5eTj4uHg397d3Nva2djX1tXU09LR0M/OzczLysnIx8bFxMPCwcC/vr28u7q5uLe2tbSzsrGwr66trKuqqainpqWko6KhoJ+enZybmpmYl5aVlJOSkZCPjo2Mi4qJiIeGhYSDgoGAf359fHt6eXh3dnV0c3JxcG9ubWxramloZ2ZlZGNiYWBfXl1cW1pZWFdWVVRTUlFQT05NTEtKSUhHRkVEQ0JBQD8+PTw7Ojk4NzY1NDMyMTAvLi0sKyopKCcmJSQjIiEgHx4dHBsaGRgXFhUUExIREA8ODQwLCgkIBwYFBAMCAQAAIfkEAAAAAAAsAAAAAKEB0QAAB/+ARIKDhIWGh4iJiouMjY6PkJGSk5SV';
    tmpClob := tmpClob||'lpeYmZqbnIx/n6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5pkVEur6/wMHCw8TFxsfIf7zJzM3Oz9DR0tOny9TX2Nna29zN1t3g4eLj5Nzf5ejp6uvssOft8PHy8+a99Pf4+frC7/v+/wADiuonsKDBg+sIIlzIsCE1hQ4jSpwYDCLFixgztrKosaNHjxw/ihzpMCTJkygBmkzJsqW8lS5jyiQHc6bNm9hq4tzJk5nOnkCDAvsptKjRWUSPKl2aKinTp1A/OY1K9ejUqliBXs3K9ebWrmBdfg1L9uTYsmhB2kvLVuvatnD/vb6NS1fs3Lp4zd7Ny1dt378izwIePE8w4cPsDCNeXE4x48fgHEOenE0y5cvSLGPe7G0v58/pNIMezc8z6dP1UKsWJ3q1a1mtX8veaHq27WOxb+smlXu3b6m1fwu/1Xv47eLGZyNP/no589XOn6OOLp009eqgr2PnrH075u7eKYMPD3k8ecbmzyNOr54w+/aA38PvK39+3vr26+LPH3c//7b+/ZdWgAKWRWCBYR2IYFcKLphVgw5WBWGEUU1I4VMWXrhUhhpaFVyHyn0IYnMijghdiSZOh2KK1q3IYnYuvshdjDJ+R2ON4t2IY3k67ohej/k8YAIOSRRp5JFIGmlD/wtrrIJAklBGaeQHHjRgixpXABABAkzcEoYVEkgpZhIcfBIGklYMA0UWdIwp5RhSfNKEBjAsgUFEHOIiBhlDlODHn4AGKuigfxoAQx6ohEDoooz+WUAXAsxygg+BUpHALA9cMIEKjXbqBxefKCGoAsBAIcECQXja6BGfMOGCBQRcsMEbJQEZzx5tZKDqrn6UUMYcpijKq6cqwOAELFKAMGgfsSSQBgTDLtpBE6GO+osNBkRLaAp7fIIAEApEMMQZVNQaUR0paLtrEDmUIqy6jC4AxSsULNrCK3woC2+gQTwBiqiBkprLHhbsKygCoATAgAILDCFFD+Y2dICfBntKAf8p71';
    tmpClob := tmpClob||'YsaBuu8KEroQZcyooGBWj85wWhAAyowLc8oa/GC4RCBgIKHDABFCxEvNAYjKbAAhJABy300EhskLGgaYySMQRENz30BtAO+gIrODcKBCstfDwoCiM47XQXXf5r7S0YZEtoASBM4DXRVIgRChsjmMEGAkeQoPNBVmgNqA8VAAtLFWbUQCjCoWSMBCxR2ICCoHawgoWgevfKgCor8LC1ESfUovKfLNMCRQ+DZtCFCXHS8kYHG2wQR9gM5Ynsy4DCYCUtTFyghaAofFF4oIfHckLUgPqbyh0lB3qBC4LWEEUqHQzaRbe2bO5H57M8LigLkQrl+itLCFrCB7mYUPz/yrsD2nssBAg6RipN2CHoBk6sAfyfM6DCwaBo5CI99bF8kWqgbhCZ9myFDifsQFBY8MX9AqWFLYDCcLN4gqAuhooDQC4LnxgA5M5wigkIiln6GxstjJC8MHgIITR4H+tyUQZBDeCBvJtFAkRYiinMzw8U/AMTPBioCawwFCcQlA8EeIv92eJoHlDK9lqhAEHRARhBDBQcYGi+WWRBUHY7xQIEBYLZfSILkUMZKSogKDGGMGC1EICgYrAhApZjA4HiwbGAAUdAoYCKfzofLAIgKAmcQgJSGwUMBBWEFZACeYAqQRV8YURamGGNRoikJCdJyUpS0gR+Ocj82BgMPgYK/3oQjIUGKPanDDiwFFtIV6AAQIoEmA1QbiDFCAIFgl80chaDNBnudNeRJbJCUBEQBhkDJbxQtqIJJwACpwJVhlMcQVApeEApUqg+pQWqA7akYSz6oEtB2eAjvlwFMIXRvUDh4ROhPMENIMDOdrrTnZErpR5MQc1A+dEULYzjncr3J07q4payAEA3ARUzcLqRHP/7U0GBAQRBeQGdMfzEFGYJrxeWIgxHswAqMGC5QLlAFIIDVA2yiUZaNHSgEJhCYA46jiEEKgXUAgYYAgUBPPpBj2qIgbryZ4om0pQNqbCgoMoEii0CSgVqYKQ2YSFU';
    tmpClob := tmpClob||'QE3gCFCNqlSnSlWoEtWgCP8RaKCm9ospkNIP2IRoFUPhhAgMawdXJYUHvuqHK6iiCaB7qTQ/QQZBgeqfS32FHAT1USWyVBwIEFRYfdEGQRHApnoERQXYGroeDICIo5DCDQQ1ARHEYG1Bg92fWPmJN3BxXmckH+1+EKgMcPCEB5FCRwEFPl14YJl/UoFKxZrHUnBgfIDqgRVksILlpSINkIuU9dR1r09MNlBGwGtJaeFJQIHBt0UJ5ypIGKgCFPcWJyBtoLrAz5uaQg6q5N0pUyGAyCXtD06oo7ZC9okkeK+1RczrK1YQOQDMcYALUcMBGXiAmNJCA4urriERe4oVhDRQBsjeKdLLxdL9obzwCsD/J5zAAu/NALSak+8rThooCzwUvwvRAaEmwAHouoIJLzCqoNza3cSOQgRuGBQENICKYQYKk6GgrrZKMLk/8OF2yfsAZGEBUBkeN44zcJtbGlJXQgUBDGWoqpSP4AAqrFZQrBKFMU0BBa0GqgQVMMUTcOsHEIYiChdYgprXzGY2zzRQyvuEDRalhQ24YMp4PoK/pHeDPPsZqgjLQ4AHBQI4dOHPVKVxRqTbinoNlFBluC+BVZG+QR3BwaBoQvMCtQMRzEIJZM7iHyY20IJKz2S5+4QctKvLHSR10X9FBxcS+ugSGMG/LWYFAoDcww+D4pFDrQUaggsKGgy6YhBo0h9O/62xe37iCRXWpaJhLRE8FOzRG0iTuyK6Cg+wGlAh4AMoMHDDhc4iWZRlnReEANt9mQEUCSBzxcz9iSgQ4IbqamYvY60OOfThyvAqgAtokChur8JlgwoCUVX8JwgouRYtGJQZP3EHIFAKXlTA9QW6CYF9juIBWKCoulCwyH1jhAl8sAEWLMlyScaBCx7AtCmWMMkkvGIPM6gkCTBQhUoSHBcHoCQWcA0KPSCgAi1vufBCwQAyJP3pk6xDKqqggSvkHOqTvK5GGO0jknC96ysFO4nE7pqvk33r/D47gN';
    tmpClob := tmpClob||'Ku9gGxve0GejvcEyT3uTOo7nZ/EN7zLqG9871Cfv87hgIv+P82Fv4yZj/8QRKv+IIwvvEBeTzk/yH5ye+j8pbPB+Yzf4/Nc74whP88TjwveniQvvSJCT3qZXL61YdG9a5vSetjTxPY0x4ls799OHKv+27wvvfb+D3wK2P74WfS+GgRPvKnofzlR6P5zn8G9KPfGerT3fpgmT72cVP87d/N+4AHP1a0L/7SlJ8q5D//L9Kvfl2wv/24eD/8bSH/+dOi/vaHTffz7w/88/8V/vd/tCGAIEaAPRGABtgU+5eAoMeAPIGADlgKEBiBozCBFBgKFniBwKGBM5GBGuiBFwiCFCiCEUiCDmiCDIiCCaiCBsiCBOiCAgiD/yeD/EeD+WeD9scWC52wgzzYgz74g0AYhEI4hERYhIIQCAA7';
    t_attachments(1).fileName := 'oracle-primary-sig.gif';
    t_attachments(1).contentID := '123456789';
    t_attachments(1).fileBLOB := base64_decode(tmpClob);
    mam_email.setMailserver('my.mailserver.example.com');
    mam_email.send(
         'recipient@example.com'-- Recipient
        ,'cc@example.com'-- Recipient of copy
        ,'bcc@example.com'-- Recipient of blind copy
        ,'sender@example.com'-- Sender
        ,'Testmail with inline image'-- Subject
        ,'Plain Text Body'
        ,'<h1>Inline Image </h1>'||CHR(10)||
         '<p>Oracle Logo </p>
         <p><img src="cid:123456789"></p>'
        ,t_attachments
        );
END;

Mail mit inline Bild

Herunterladen

Haftungsauschluss

Dieses Programm kommt ohne Garantie für den produktiven Einsatz. Wenn du es trotzdem verwendest, stelle bitte sicher, dass du vorher gründlich testst, da ich in keinem Fall eine Haftung übernehme. Ich behaupte insbesondere nicht, dass das Programm frei von Fehlern ist.

Lizenz

oracle@matzberger.de Für Kontakte aller Art, auch Fehlermeldungen zum Programm Impressum