Manchmal reicht eine einfache CDS View nicht aus, um die Daten für eine E-Mail zusammen zu tragen. Bei komplexen Business Logiken kann der Aufwand, dies in Views abzubilden, groß sein. Möglicherweise existieren aber bereits Funktionsbausteine oder Klassen, welche die Daten bereitstellen.
Auf der folgenden Seite ist beschrieben, wie ein E-Mail Template mittels ABAP Code mit Daten versorgt werden kann.
Voraussetzungen
Zunächst muss ein E-Mail Template, basierend auf einer CDS View, erstellt werden. Auch wenn die Daten nicht mit der CDS View ermittelt werden, muss diese dennoch erstellt werden. Zudem muss die View alle Spalten enthalten, die in der E-Mail verwendet werden.
Lösung
Wie zuvor werden zunächst Instanzen der BCS und E-Mail API erstellt
DATA(lo_bcs) = cl_bcs=>create_persistent( ). " Create instance of BCS class
" create instance of eMail API, provide name of Mail template
DATA(lo_email_api) = cl_smtg_email_api=>get_instance( iv_template_id = 'ZMAIL_TEMPLATE1' ).
Um Daten an die Schnittstelle übergeben zu können, muss eine Referenz vom Typ DATA erstellt werden. Dies kann beispielsweise wie folgt geschehen.
DATA: lt_comp TYPE cl_abap_structdescr=>component_table.
DATA: ls_comp LIKE LINE OF lt_comp.
DATA lr_data TYPE REF TO data.
ls_comp-name = 'PRUEFLOS'.
ls_comp-type ?= cl_abap_typedescr=>describe_by_name( 'QPLOS' ).
APPEND ls_comp TO lt_comp.
" Fill table with concrete data
DATA(lo_struct) = cl_abap_structdescr=>get( p_components = lt_comp ).
CREATE DATA lr_data TYPE HANDLE lo_struct.
ASSIGN lr_data->* TO FIELD-SYMBOL(<ls_data>).
ASSIGN COMPONENT 1 OF STRUCTURE <ls_data> TO FIELD-SYMBOL(<fs_value>).
<fs_value> = '777888999'. " No of inspection lot
Das Rendern des E-Mail Dokuments erfolgt diesmal mit der Methode RENDER_BCS_W_DATA. Leider ist diese seitens SAP nicht dokumentiert und allgemein finden sich kaum Beispiele hierzu.
" Render E-Mail for CL_BCS class. This replaces all placeholders with real data
lo_email_api->render_bcs_w_data(
EXPORTING
io_bcs = lo_bcs
iv_language = sy-langu
ir_data = lr_data
).
Die weitere Verarbeitung, etwa das Hinzufügen der Absender und Empfänger, sowie das senden selbst, entspricht dem bereits beschriebenen vorgehen.
Vollständiges Programm
*&---------------------------------------------------------------------*
*& Report z_mail_template1
*&---------------------------------------------------------------------*
*& Send E-Mail based on Template by using data from code instead from CDS View
*&
*& E-Mail Template must be defined with relation to an existing CDS view.
*& CDS View needs to contain all relevant columns but we will not use it to read
*& data.
*& Instead, relevant data gets collected by ABAP. Therefore a reference to data table
*& gets instantiated and we use method render_bcs_w_data of
*& class cl_smtg_email_api
*&
*& This demo can be helpful, if you can't simply read data by CDS view because of
*& business complexity.
*&---------------------------------------------------------------------*
REPORT z_mail_template1.
DATA: gv_subrc_send_email TYPE sy-subrc.
DATA: ls_recip TYPE bcss_re3,
lr_recipient TYPE REF TO if_recipient_bcs,
lo_email_document TYPE REF TO cl_document_bcs.
TRY.
DATA(lo_bcs) = cl_bcs=>create_persistent( ). " Create instance of BCS class
" create instance of eMail API, provide name of Mail template
DATA(lo_email_api) = cl_smtg_email_api=>get_instance( iv_template_id = 'ZMAIL_TEMPLATE1' ).
TRY.
" Here, we define the data table, which contains all dynamic data of eMail. There table gets used by API to
" replace placeholder with current values.
DATA: lt_comp TYPE cl_abap_structdescr=>component_table.
DATA: ls_comp LIKE LINE OF lt_comp.
DATA lr_data TYPE REF TO data.
ls_comp-name = 'PRUEFLOS'.
ls_comp-type ?= cl_abap_typedescr=>describe_by_name( 'QPLOS' ).
APPEND ls_comp TO lt_comp.
ls_comp-name = 'MATERIAL'.
ls_comp-type ?= cl_abap_typedescr=>describe_by_name( 'MATNR' ).
APPEND ls_comp TO lt_comp.
ls_comp-name = 'AUFNR'.
ls_comp-type ?= cl_abap_typedescr=>describe_by_name( 'AUFNR' ).
APPEND ls_comp TO lt_comp.
ls_comp-name = 'MAKTX'.
ls_comp-type ?= cl_abap_typedescr=>describe_by_name( 'KZTXT' ).
APPEND ls_comp TO lt_comp.
" Fill table with concrete data
DATA(lo_struct) = cl_abap_structdescr=>get( p_components = lt_comp ).
CREATE DATA lr_data TYPE HANDLE lo_struct.
ASSIGN lr_data->* TO FIELD-SYMBOL(<ls_data>).
ASSIGN COMPONENT 1 OF STRUCTURE <ls_data> TO FIELD-SYMBOL(<fs_value>).
<fs_value> = '777888999'. " No of inspection lot
ASSIGN COMPONENT 2 OF STRUCTURE <ls_data> TO <fs_value>.
<fs_value> = '123456'. " material no
ASSIGN COMPONENT 3 OF STRUCTURE <ls_data> TO <fs_value>.
<fs_value> = '111234'. " pp order no
ASSIGN COMPONENT 4 OF STRUCTURE <ls_data> TO <fs_value>.
<fs_value> = 'Screw M5x40'. " material text
" Render E-Mail for CL_BCS class. This replaces all placeholders with real data
lo_email_api->render_bcs_w_data(
EXPORTING
io_bcs = lo_bcs
iv_language = sy-langu
ir_data = lr_data
).
CATCH cx_smtg_email_common INTO DATA(ls_cx).
DATA(lv_message) = ls_cx->get_text( ).
MESSAGE s899(id) WITH 'Unable to send message:'(004) lv_message.
FREE lo_bcs.
gv_subrc_send_email = 1.
ENDTRY.
IF gv_subrc_send_email = 0.
TRY .
lo_email_document ?= lo_bcs->document( ).
CATCH cx_root.
ENDTRY.
TRY.
" Define recipient
CLEAR: lr_recipient.
lr_recipient =
cl_cam_address_bcs=>create_internet_address(
'XY@Z.com' ).
IF lr_recipient IS BOUND.
ls_recip-recipient = lr_recipient.
lo_bcs->add_recipient( EXPORTING i_recipient = lr_recipient ).
ENDIF.
CATCH cx_address_bcs INTO DATA(lr_bcs_exception).
ENDTRY.
" Define sender
DATA(lo_sender) = cl_sapuser_bcs=>create( sy-uname ).
lo_bcs->set_sender( i_sender = lo_sender ).
" Send Email
lo_bcs->send( ).
IF sy-subrc IS INITIAL.
COMMIT WORK. " Commit to really send the message
FREE lo_bcs.
ENDIF.
ELSEIF gv_subrc_send_email = 4.
MESSAGE s167(qm).
ENDIF.
CATCH cx_send_req_bcs INTO DATA(lr_send_req_bcs_excp).
* possible error types of CX_SEND_REQ_BCS
* (without those inherited from cx_bcs):
* ALLREADY_RELEASED RECIPIENT_EXISTS DOCUMENT_NOT_EXISTS
* DOCUMENT_NOT_SENT NOT_SUBMITED FOREIGN_LOCK
* TOO_MANY_RECEIVERS NO_INSTANCE CANCELLED
* NOT_RELEASED MIME_PROBLEMS NO_RECIPIENTS
* SENDER_PROBLEMS
DATA(lv_diagnosis) = lr_send_req_bcs_excp->get_text( ).
MESSAGE s899(id) WITH
'Unable to send message:'(004) lv_diagnosis.
FREE lo_bcs.
* possible bcs errors
CATCH cx_bcs INTO DATA(lr_bcs).
* possible error types of cx_bcs:
* INTERNAL_ERROR OS_EXCEPTION X_ERROR
* PARAMETER_ERROR INVALID_VALUE CREATION_FAILED
* NO_AUTHORIZATION LOCKED CAST_ERROR
lv_diagnosis = lr_bcs->get_text( ).
MESSAGE s899(id) WITH
'Unable to send message:'(004) lv_diagnosis.
FREE lo_bcs.
CATCH cx_smtg_email_common INTO DATA(lr_common).
lv_diagnosis = lr_common->get_text( ).
MESSAGE s899(id) WITH 'Unable to send message:'(004) lv_diagnosis .
CATCH cx_os_object_not_found INTO DATA(lr_object_not_found).
lv_diagnosis = lr_object_not_found->get_text( ).
ENDTRY.