ABAP Email Sending: CL_BCS, Anhänge und HTML-Mails

kategorie
ABAP-Statements
Veröffentlicht
autor
Johannes

Email-Versand in ABAP erfolgt über das BCS-Framework (Business Communication Services). Mit CL_BCS können E-Mails mit Text, HTML-Inhalt und Anhängen versendet werden.

BCS-Klassen

KlasseBeschreibung
CL_BCSHauptklasse für E-Mail-Versand
CL_DOCUMENT_BCSE-Mail-Dokument (Body, Anhänge)
CL_CAM_ADDRESS_BCSExterne E-Mail-Adresse
CL_SAPUSER_BCSSAP-Benutzer als Empfänger

Beispiele

1. Einfache E-Mail senden

DATA: lo_bcs TYPE REF TO cl_bcs,
lo_document TYPE REF TO cl_document_bcs,
lo_sender TYPE REF TO cl_sapuser_bcs,
lo_recipient TYPE REF TO if_recipient_bcs.
TRY.
" BCS-Instanz erstellen
lo_bcs = cl_bcs=>create_persistent( ).
" Dokument erstellen
DATA(lt_text) = VALUE soli_tab(
( line = 'Sehr geehrte Damen und Herren,' )
( line = '' )
( line = 'dies ist eine Testnachricht.' )
( line = '' )
( line = 'Mit freundlichen Grüßen' )
( line = 'Ihr SAP-System' )
).
lo_document = cl_document_bcs=>create_document(
i_type = 'RAW' " Textformat
i_text = lt_text
i_subject = 'Testmail aus SAP'
).
lo_bcs->set_document( lo_document ).
" Absender (aktueller Benutzer)
lo_sender = cl_sapuser_bcs=>create( sy-uname ).
lo_bcs->set_sender( lo_sender ).
" Empfänger
lo_recipient = cl_cam_address_bcs=>create_internet_address(
'empfaenger@example.com'
).
lo_bcs->add_recipient( lo_recipient ).
" Senden
DATA(lv_sent) = lo_bcs->send( ).
IF lv_sent = abap_true.
COMMIT WORK.
WRITE: / 'E-Mail wurde gesendet'.
ENDIF.
CATCH cx_bcs INTO DATA(lx_error).
WRITE: / 'Fehler:', lx_error->get_text( ).
ENDTRY.

2. HTML-E-Mail

TRY.
DATA(lo_bcs) = cl_bcs=>create_persistent( ).
" HTML-Inhalt
DATA(lt_html) = VALUE soli_tab(
( line = '<html><body>' )
( line = '<h1>Willkommen</h1>' )
( line = '<p>Dies ist eine <b>HTML-E-Mail</b>.</p>' )
( line = '<table border="1">' )
( line = '<tr><th>Position</th><th>Menge</th></tr>' )
( line = '<tr><td>Material A</td><td>100</td></tr>' )
( line = '<tr><td>Material B</td><td>250</td></tr>' )
( line = '</table>' )
( line = '</body></html>' )
).
DATA(lo_document) = cl_document_bcs=>create_document(
i_type = 'HTM' " HTML-Format
i_text = lt_html
i_subject = 'HTML-Testmail'
).
lo_bcs->set_document( lo_document ).
" Absender und Empfänger...
lo_bcs->set_sender( cl_sapuser_bcs=>create( sy-uname ) ).
lo_bcs->add_recipient(
cl_cam_address_bcs=>create_internet_address( 'user@example.com' )
).
lo_bcs->send( ).
COMMIT WORK.
CATCH cx_bcs INTO DATA(lx_error).
WRITE: / lx_error->get_text( ).
ENDTRY.

3. E-Mail mit Anhang

TRY.
DATA(lo_bcs) = cl_bcs=>create_persistent( ).
" Hauptdokument (Body)
DATA(lt_body) = VALUE soli_tab(
( line = 'Anbei finden Sie die angeforderten Daten.' )
).
DATA(lo_document) = cl_document_bcs=>create_document(
i_type = 'RAW'
i_text = lt_body
i_subject = 'Datenexport'
).
" CSV als Anhang erstellen
DATA(lt_csv) = VALUE soli_tab(
( line = 'Kunde;Name;Ort' )
( line = '1000;Müller GmbH;Berlin' )
( line = '1001;Schmidt AG;Hamburg' )
( line = '1002;Weber KG;München' )
).
lo_document->add_attachment(
i_attachment_type = 'CSV'
i_attachment_subject = 'kunden_export.csv'
i_att_content_text = lt_csv
).
lo_bcs->set_document( lo_document ).
lo_bcs->set_sender( cl_sapuser_bcs=>create( sy-uname ) ).
lo_bcs->add_recipient(
cl_cam_address_bcs=>create_internet_address( 'user@example.com' )
).
lo_bcs->send( ).
COMMIT WORK.
CATCH cx_bcs INTO DATA(lx_error).
WRITE: / lx_error->get_text( ).
ENDTRY.

4. Binärer Anhang (PDF, Excel)

TRY.
DATA(lo_bcs) = cl_bcs=>create_persistent( ).
DATA(lt_body) = VALUE soli_tab(
( line = 'Anbei das PDF-Dokument.' )
).
DATA(lo_document) = cl_document_bcs=>create_document(
i_type = 'RAW'
i_text = lt_body
i_subject = 'PDF-Dokument'
).
" PDF-Daten (z.B. aus Smartform)
DATA: lv_pdf_xstring TYPE xstring.
" ... PDF generieren ...
" XString in SOLIX-Tabelle konvertieren
DATA(lt_pdf_content) = cl_bcs_convert=>xstring_to_solix( lv_pdf_xstring ).
DATA(lv_size) = xstrlen( lv_pdf_xstring ).
lo_document->add_attachment(
i_attachment_type = 'PDF'
i_attachment_subject = 'dokument.pdf'
i_attachment_size = lv_size
i_att_content_hex = lt_pdf_content
).
lo_bcs->set_document( lo_document ).
lo_bcs->set_sender( cl_sapuser_bcs=>create( sy-uname ) ).
lo_bcs->add_recipient(
cl_cam_address_bcs=>create_internet_address( 'user@example.com' )
).
lo_bcs->send( ).
COMMIT WORK.
CATCH cx_bcs INTO DATA(lx_error).
WRITE: / lx_error->get_text( ).
ENDTRY.

5. Mehrere Empfänger (TO, CC, BCC)

TRY.
DATA(lo_bcs) = cl_bcs=>create_persistent( ).
" Dokument erstellen...
DATA(lo_document) = cl_document_bcs=>create_document(
i_type = 'RAW'
i_text = VALUE soli_tab( ( line = 'Nachricht an mehrere Empfänger' ) )
i_subject = 'Info an Team'
).
lo_bcs->set_document( lo_document ).
" Absender
lo_bcs->set_sender( cl_sapuser_bcs=>create( sy-uname ) ).
" TO-Empfänger
lo_bcs->add_recipient(
i_recipient = cl_cam_address_bcs=>create_internet_address( 'chef@example.com' )
i_express = abap_true " Sofort senden
).
" CC-Empfänger
lo_bcs->add_recipient(
i_recipient = cl_cam_address_bcs=>create_internet_address( 'team@example.com' )
i_copy = abap_true " CC
).
" BCC-Empfänger
lo_bcs->add_recipient(
i_recipient = cl_cam_address_bcs=>create_internet_address( 'archiv@example.com' )
i_blind = abap_true " BCC
).
" SAP-Benutzer als Empfänger
lo_bcs->add_recipient(
i_recipient = cl_sapuser_bcs=>create( 'MUSTERMANN' )
).
lo_bcs->send( ).
COMMIT WORK.
CATCH cx_bcs INTO DATA(lx_error).
WRITE: / lx_error->get_text( ).
ENDTRY.

6. Email Helper Klasse

CLASS zcl_email_sender DEFINITION.
PUBLIC SECTION.
TYPES: ty_recipients TYPE TABLE OF string WITH EMPTY KEY,
ty_attachments TYPE TABLE OF string WITH EMPTY KEY.
METHODS: constructor.
METHODS: set_subject
IMPORTING iv_subject TYPE string
RETURNING VALUE(ro_self) TYPE REF TO zcl_email_sender.
METHODS: set_body_text
IMPORTING iv_text TYPE string
RETURNING VALUE(ro_self) TYPE REF TO zcl_email_sender.
METHODS: set_body_html
IMPORTING iv_html TYPE string
RETURNING VALUE(ro_self) TYPE REF TO zcl_email_sender.
METHODS: add_recipient
IMPORTING iv_email TYPE string
iv_copy TYPE abap_bool DEFAULT abap_false
iv_blind TYPE abap_bool DEFAULT abap_false
RETURNING VALUE(ro_self) TYPE REF TO zcl_email_sender.
METHODS: add_attachment_text
IMPORTING iv_filename TYPE string
iv_content TYPE string
RETURNING VALUE(ro_self) TYPE REF TO zcl_email_sender.
METHODS: add_attachment_binary
IMPORTING iv_filename TYPE string
iv_content TYPE xstring
RETURNING VALUE(ro_self) TYPE REF TO zcl_email_sender.
METHODS: send
RETURNING VALUE(rv_success) TYPE abap_bool.
METHODS: get_error_message
RETURNING VALUE(rv_message) TYPE string.
PRIVATE SECTION.
DATA: mo_bcs TYPE REF TO cl_bcs,
mo_document TYPE REF TO cl_document_bcs,
mv_error TYPE string.
METHODS: string_to_soli
IMPORTING iv_string TYPE string
RETURNING VALUE(rt_lines) TYPE soli_tab.
METHODS: get_file_extension
IMPORTING iv_filename TYPE string
RETURNING VALUE(rv_extension) TYPE string.
ENDCLASS.
CLASS zcl_email_sender IMPLEMENTATION.
METHOD constructor.
TRY.
mo_bcs = cl_bcs=>create_persistent( ).
CATCH cx_bcs.
ENDTRY.
ENDMETHOD.
METHOD set_subject.
" Subject wird beim Dokument-Erstellen gesetzt
ro_self = me.
ENDMETHOD.
METHOD set_body_text.
TRY.
mo_document = cl_document_bcs=>create_document(
i_type = 'RAW'
i_text = string_to_soli( iv_text )
i_subject = 'Nachricht'
).
CATCH cx_document_bcs.
ENDTRY.
ro_self = me.
ENDMETHOD.
METHOD set_body_html.
TRY.
mo_document = cl_document_bcs=>create_document(
i_type = 'HTM'
i_text = string_to_soli( iv_html )
i_subject = 'Nachricht'
).
CATCH cx_document_bcs.
ENDTRY.
ro_self = me.
ENDMETHOD.
METHOD add_recipient.
TRY.
mo_bcs->add_recipient(
i_recipient = cl_cam_address_bcs=>create_internet_address( iv_email )
i_copy = iv_copy
i_blind = iv_blind
).
CATCH cx_bcs.
ENDTRY.
ro_self = me.
ENDMETHOD.
METHOD add_attachment_text.
TRY.
DATA(lv_ext) = get_file_extension( iv_filename ).
mo_document->add_attachment(
i_attachment_type = lv_ext
i_attachment_subject = iv_filename
i_att_content_text = string_to_soli( iv_content )
).
CATCH cx_document_bcs.
ENDTRY.
ro_self = me.
ENDMETHOD.
METHOD add_attachment_binary.
TRY.
DATA(lv_ext) = get_file_extension( iv_filename ).
DATA(lt_content) = cl_bcs_convert=>xstring_to_solix( iv_content ).
mo_document->add_attachment(
i_attachment_type = lv_ext
i_attachment_subject = iv_filename
i_attachment_size = xstrlen( iv_content )
i_att_content_hex = lt_content
).
CATCH cx_document_bcs.
ENDTRY.
ro_self = me.
ENDMETHOD.
METHOD send.
TRY.
mo_bcs->set_document( mo_document ).
mo_bcs->set_sender( cl_sapuser_bcs=>create( sy-uname ) ).
rv_success = mo_bcs->send( ).
IF rv_success = abap_true.
COMMIT WORK.
ENDIF.
CATCH cx_bcs INTO DATA(lx_error).
mv_error = lx_error->get_text( ).
rv_success = abap_false.
ENDTRY.
ENDMETHOD.
METHOD get_error_message.
rv_message = mv_error.
ENDMETHOD.
METHOD string_to_soli.
SPLIT iv_string AT cl_abap_char_utilities=>newline INTO TABLE DATA(lt_lines).
LOOP AT lt_lines INTO DATA(lv_line).
APPEND VALUE #( line = lv_line ) TO rt_lines.
ENDLOOP.
ENDMETHOD.
METHOD get_file_extension.
DATA(lv_pos) = find( val = iv_filename sub = '.' occ = -1 ).
IF lv_pos > 0.
rv_extension = to_upper( iv_filename+lv_pos ).
ELSE.
rv_extension = 'BIN'.
ENDIF.
ENDMETHOD.
ENDCLASS.
" Verwendung
DATA(lo_email) = NEW zcl_email_sender( ).
DATA(lv_success) = lo_email->set_body_html(
'<html><body><h1>Report</h1><p>Daten im Anhang</p></body></html>'
)->add_recipient(
'empfaenger@example.com'
)->add_recipient(
iv_email = 'cc@example.com'
iv_copy = abap_true
)->add_attachment_text(
iv_filename = 'daten.csv'
iv_content = 'A;B;C' && cl_abap_char_utilities=>newline && '1;2;3'
)->send( ).
IF lv_success = abap_false.
WRITE: / lo_email->get_error_message( ).
ENDIF.

7. E-Mail aus Smartform

" Smartform als PDF generieren und per E-Mail senden
DATA: lv_pdf TYPE xstring,
lt_lines TYPE TABLE OF tline,
lv_function TYPE rs38l_fnam.
" Smartform-Funktionsbaustein ermitteln
CALL FUNCTION 'SSF_FUNCTION_MODULE_NAME'
EXPORTING
formname = 'ZSMARFORM_ORDER'
IMPORTING
fm_name = lv_function
EXCEPTIONS
no_form = 1
no_function_module = 2
OTHERS = 3.
" PDF generieren
DATA: ls_output_options TYPE ssfcompop,
ls_control TYPE ssfctrlop.
ls_output_options-tdgetotf = abap_true.
ls_control-no_dialog = abap_true.
ls_control-getotf = abap_true.
CALL FUNCTION lv_function
EXPORTING
control_parameters = ls_control
output_options = ls_output_options
is_order = ls_order
IMPORTING
job_output_info = DATA(ls_job_info)
EXCEPTIONS
OTHERS = 1.
" OTF nach PDF konvertieren
CALL FUNCTION 'CONVERT_OTF'
EXPORTING
format = 'PDF'
IMPORTING
bin_file = lv_pdf
TABLES
otf = ls_job_info-otfdata
lines = lt_lines
EXCEPTIONS
OTHERS = 1.
" Per E-Mail senden
DATA(lo_email) = NEW zcl_email_sender( ).
lo_email->set_body_text( 'Anbei Ihre Bestellbestätigung.' ).
lo_email->add_recipient( 'kunde@example.com' ).
lo_email->add_attachment_binary(
iv_filename = 'bestellung.pdf'
iv_content = lv_pdf
).
lo_email->send( ).

8. E-Mail-Vorlagen

CLASS zcl_email_template DEFINITION.
PUBLIC SECTION.
METHODS: constructor
IMPORTING iv_template_id TYPE string.
METHODS: set_placeholder
IMPORTING iv_name TYPE string
iv_value TYPE string
RETURNING VALUE(ro_self) TYPE REF TO zcl_email_template.
METHODS: get_subject
RETURNING VALUE(rv_subject) TYPE string.
METHODS: get_body
RETURNING VALUE(rv_body) TYPE string.
PRIVATE SECTION.
DATA: mv_subject TYPE string,
mv_body TYPE string,
mt_placeholders TYPE TABLE OF string.
ENDCLASS.
CLASS zcl_email_template IMPLEMENTATION.
METHOD constructor.
" Vorlage aus Datenbank/Customizing laden
CASE iv_template_id.
WHEN 'ORDER_CONFIRMATION'.
mv_subject = 'Bestellbestätigung {{ORDER_NO}}'.
mv_body = |<html><body>| &&
|<h1>Vielen Dank für Ihre Bestellung</h1>| &&
|<p>Ihre Bestellnummer: <b>\{\{ORDER_NO\}\}</b></p>| &&
|<p>Kunde: \{\{CUSTOMER_NAME\}\}</p>| &&
|<p>Betrag: \{\{AMOUNT\}\} \{\{CURRENCY\}\}</p>| &&
|</body></html>|.
WHEN 'SHIPPING_NOTICE'.
mv_subject = 'Versandbenachrichtigung {{DELIVERY_NO}}'.
mv_body = '...'.
ENDCASE.
ENDMETHOD.
METHOD set_placeholder.
REPLACE ALL OCCURRENCES OF |{\\{{iv_name}\\}}|
IN mv_subject WITH iv_value.
REPLACE ALL OCCURRENCES OF |{\\{{iv_name}\\}}|
IN mv_body WITH iv_value.
ro_self = me.
ENDMETHOD.
METHOD get_subject.
rv_subject = mv_subject.
ENDMETHOD.
METHOD get_body.
rv_body = mv_body.
ENDMETHOD.
ENDCLASS.
" Verwendung
DATA(lo_template) = NEW zcl_email_template( 'ORDER_CONFIRMATION' ).
lo_template->set_placeholder( iv_name = 'ORDER_NO' iv_value = '0000001234' ).
lo_template->set_placeholder( iv_name = 'CUSTOMER_NAME' iv_value = 'Müller GmbH' ).
lo_template->set_placeholder( iv_name = 'AMOUNT' iv_value = '1.234,50' ).
lo_template->set_placeholder( iv_name = 'CURRENCY' iv_value = 'EUR' ).
DATA(lo_email) = NEW zcl_email_sender( ).
lo_email->set_body_html( lo_template->get_body( ) ).
lo_email->add_recipient( 'kunde@example.com' ).
lo_email->send( ).

9. E-Mail-Status prüfen

" Gesendete E-Mails in SOST anzeigen
" Transaktion: SOST (SAPconnect-Sendeaufträge)
" Programmatisch Status prüfen
DATA: lt_messages TYPE TABLE OF soos1.
CALL FUNCTION 'SO_OBJECT_READ'
EXPORTING
folder_id = 'OUTBOX'
object_id = lv_object_id
TABLES
objhead = lt_objhead
objcont = lt_objcont
EXCEPTIONS
OTHERS = 1.

10. Sofortversand aktivieren

TRY.
DATA(lo_bcs) = cl_bcs=>create_persistent( ).
" ... Dokument und Empfänger ...
" Sofortversand (nicht warten auf Job)
lo_bcs->set_send_immediately( abap_true ).
lo_bcs->send( ).
COMMIT WORK AND WAIT. " Warten auf Commit
CATCH cx_bcs INTO DATA(lx_error).
" ...
ENDTRY.
" Alternative: SAPconnect Job manuell starten
CALL FUNCTION 'RSCP_START_SENDING'
EXCEPTIONS
OTHERS = 1.

Wichtige Transaktionen

TransaktionBeschreibung
SOSTSendeaufträge anzeigen
SCOTSAPconnect Administration
SO01SAP Office Eingang

Wichtige Hinweise / Best Practice

  • COMMIT WORK nach send( ) nicht vergessen.
  • cl_bcs=>create_persistent für dauerhaften Versand.
  • HTM-Typ für HTML-E-Mails verwenden.
  • Binäre Anhänge über solix-Tabelle.
  • SOST zum Prüfen des Sendestatus.
  • set_send_immediately für sofortigen Versand.
  • Vorlagen für wiederkehrende E-Mail-Typen.
  • Fehlerbehandlung mit TRY-CATCH.
  • In ABAP Cloud: Alternative APIs nutzen.
  • Kombinieren Sie mit Smartforms für PDF-Generierung.