Application Development and Automation Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
Faizan_khan1
Explorer
1,484

Introduction: 

Sending a single attachment via email in SAP ABAP is straightforward, thanks to built-in functionality. However, sending multiple attachments is more complex, involving challenges like proper encoding, and maintaining the email structure. In this blog, we’ll explore the steps to overcome these complexities and successfully send multiple attachments in a single email. By the end, you’ll have a clear understanding of how to handle multiple files and ensure they’re correctly delivered.

Data Declarations: 

 

DATA: lo_send_request TYPE REF TO cl_bcs. "VALUE IS INITIAL. 
 CLASS cl_bcs DEFINITION LOAD. 
 DATA: lo_document TYPE REF TO cl_document_bcs . "VALUE IS INITIAL. "document object 
 DATA : it_text TYPE bcsy_text. "Table for body 
 DATA : wa_text LIKE LINE OF it_text. "work area for message body 
 DATA: lo_sender TYPE REF TO if_sender_bcs. "VALUE IS INITIAL. "sender 
 DATA: lo_recipient TYPE REF TO if_recipient_bcs." VALUE IS INITIAL. "recipi

 

  • Data declarations are made for various objects that will be used to send emails  
  • it_text is an internal table used for storing the body content of the email. 
  • lo_sender and lo_recipient will store the sender and recipient details for the email. 
  • Data related to attachments (it_mara, it_sflight) is declared to hold material data and flight data, which will later be attached to the email as files.

 

 

PARAMETERS p_mtart TYPE mara-mtart. "material type input 
 PARAMETERS p_CARRID TYPE Sflight-carrid. " Airline code input 
 PARAMETERS : p_email TYPE UNAME. "Email input 
 PARAMETERS: p_sub TYPE char50. "email subject 

 

 

The selection screen gathers user input for: 

  • p_mtart: Material type to filter the MARA table. 
  • p_carrid: Airline code to filter the Sflight table. 
  • p_email: Recipient's email address. 
  • p_sub: Subject for the email. 

 

DATA : it_mara TYPE TABLE OF mara, 
        wa_mara TYPE mara. 
 DATA : it_sflight TYPE TABLE OF Sflight, 
        wa_sflight TYPE Sflight. 

 

 

  • it_mara: This is an internal table (TABLE OF mara) that will hold multiple rows of material data fetched from the MARA table. 
  • wa_mara: This is a work area (TYPE mara) used to temporarily store a single row of data from the MARA 
  • it_sflight: This is an internal table (TABLE OF Sflight) that will store multiple rows of flight data fetched from the Sflight table. 
  • wa_sflight: This is a work area (TYPE Sflight) used to temporarily hold a single row of flight 

 

DATA : lv_string             TYPE string, 
        lv_string_flight      TYPE string, 
        lv_data_string        TYPE string, 
        lv_data_string_flight TYPE string, 
        lv_xstring            TYPE xstring, 
        lv_xstring_flight     TYPE xstring. 

 

  • lv_string: A string variable used to store concatenated data related to material information during the loop over it_mara. 
  • lv_string_flight: A string variable used to store concatenated data related to flight details  during the loop over it_sflight. 
  • lv_data_string: A string variable that accumulates all concatenated material data (from lv_string). This data will be used to create the email attachment for material information. 
  • lv_data_string_flight: A string variable that accumulates all concatenated flight data (from lv_string_flight). This data will be used to create the email attachment for flight information.  
  • lv_xstring: This variable is used to store the material data in binary format (XSTRING). The data stored in lv_data_string will be converted into lv_xstring before it is used as an email attachment. 
  • lv_xstring_flight: Similar to lv_xstring, this variable stores the flight data in binary format (XSTRING). The data stored in lv_data_string_flight will be converted into lv_xstring_flight for the email attachment.

 

DATA: lit_binary_content        TYPE solix_tab, 
       lit_binary_content_flight TYPE solix_tab, 
       l_attsubject              TYPE sood-objdes. 

 

  • lit_binary_content: This is a table of type solix_tab, which will hold the binary content of the material data attachment after conversion from lv_xstring using SCMS_XSTRING_TO_BINARY. 
  • lit_binary_content_flight: Similar to lit_binary_content, this table holds the binary content of the flight data attachment after conversion from lv_xstring_flight to binary format. 
  • l_attsubject: This variable holds the subject or name for the email attachment. It is typically used to give a descriptive name to the file being attached to the email 

Creating Email Object (lo_send_request)

 

lo_send_request = cl_bcs=>create_persistent( ). 

 

This line creates a persistent email object using the class cl_bcs. The create_persistent method initializes the object that will be used to send the email. 

Message Body Creation :

 

wa_text-line = '<HTML><BODY>'. 
   APPEND wa_text TO it_text. 
   wa_text-line = 'Dear Recepient,'. 
   APPEND wa_text TO it_text. 
   wa_text-line = '<br></br>'. 
   APPEND wa_text TO it_text. 
   wa_text-line = 'Please find the Flight Details And Material Data  as requested in the attachment.'. 
   APPEND wa_text TO it_text. 
   wa_text-line = '<br></br>'. 
   APPEND wa_text TO it_text. 
   wa_text-line = 'Thanks & Regards , Sender'. 
   APPEND wa_text TO it_text. 
   wa_text-line = '</BODY></HTML>'. 
   APPEND wa_text TO it_text. 
   CLEAR wa_text. 

 

 

  • This section creates the body content for the email in HTML format. 
  • The body text includes a greeting, an explanation of the attachments, and a closing message. 
  • The content is stored in the it_text internal table, which will later be used as the email body. 

Create Document for Email: 

 

lo_document = cl_document_bcs=>create_document( 
   EXPORTING "create document 
   i_type = 'HTM' "Type of document HTM, TXT etc 
   i_text = it_text "email body internal table 
   i_subject = p_sub ). "email subject here p_sub input parameter 
 * Pass the document to send request 
   lo_send_request->set_document( lo_document ). 

 

This block creates a document object for the email using cl_document_bcs. It specifies that the document type is HTML (i_type = 'HTM'), assigns the email body (i_text = it_text), and sets the email subject (i_subject = p_sub). 

Attach Material Data (from MARA table): 

 

SELECT * FROM mara INTO TABLE it_mara UP TO 100 ROWS 
   WHERE mtart = p_mtart. 
  
   LOOP AT it_mara INTO wa_mara. 
     CONCATENATE wa_mara-matnr wa_mara-mtart wa_mara-meins wa_mara-mbrsh wa_mara-matkl INTO lv_string SEPARATED BY 
     cl_abap_char_utilities=>horizontal_tab. 
     CONCATENATE lv_data_string lv_string INTO lv_data_string SEPARATED BY cl_abap_char_utilities=>newline. 
   ENDLOOP. 

 

  • The SELECT query retrieves material data from the MARA table based on the material type (p_mtart). 
  • It then loops through the retrieved data and concatenates relevant fields (material number, type, unit, etc.) into a string lv_string. The string is then added to lv_data_string, which will be used as the attachment content. 

Convert String to XSTRING and Binary: 

 

CALL FUNCTION 'HR_KR_STRING_TO_XSTRING' 
     EXPORTING 
       unicode_string   = lv_data_string 
 *     OUT_LEN          = 
     IMPORTING 
       xstring_stream   = lv_xstring 
     EXCEPTIONS 
       invalid_codepage = 1 
       invalid_string   = 2 
       OTHERS           = 3. 
   IF sy-subrc <> 0. 
     IF sy-subrc = 1 . 
     ELSEIF sy-subrc = 2 . 
       WRITE:/ 'invalid string ' . 
     ENDIF. 
   ENDIF. 

 

  • The function HR_KR_STRING_TO_XSTRING is called to convert the string lv_data_string into an xstring (binary format). 
  • The result is stored in lv_xstring. 

 

CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' 
     EXPORTING 
       buffer     = lv_xstring 
     TABLES 
       binary_tab = lit_binary_content. 

 

The function SCMS_XSTRING_TO_BINARY is used to convert the xstring (lv_xstring) into binary content (lit_binary_content), which can be used as an attachment. 

Add Attachment to Email: 

 

add attachment 
   CLEAR l_attsubject . 
   CONCATENATE 'MaterialData_Excel' sy-datum INTO l_attsubject. 
 * Create Attachment 
   TRY. 
       lo_document->add_attachment( EXPORTING 
       i_attachment_type = 'XLS' 
       i_attachment_subject = l_attsubject 
       i_att_content_hex = lit_binary_content ). 
     CATCH cx_document_bcs INTO DATA(lx_document_bcs). 
   ENDTRY. 

 

  • A new subject for the attachment is created (l_attsubject). 
  • The add_attachment method is used to attach the material data (lit_binary_content) as an Excel file (i_attachment_type = 'XLS') to the email. 

Set Sender for the Email:

 

TRY. 
       lo_sender = cl_sapuser_bcs=>create( sy-uname ). "sender is the logged in user 
 * Set sender to send request 
       lo_send_request->set_sender( 
       EXPORTING 
       i_sender = lo_sender ). 
   ENDTRY. 

 

  • The cl_sapuser_bcs=>create method creates the sender object using the logged-in user (sy-uname). 
  • The set_sender method is used to associate the sender with the email. 

Attach Flight Data (from Sflight table): 

 

SELECT * FROM sflight INTO TABLE it_sflight UP TO 100 ROWS 
   WHERE carrid = p_carrid. 

   LOOP AT it_sflight INTO wa_sflight. 
     CONCATENATE wa_sflight-carrid wa_sflight-connid wa_sflight-currency wa_sflight-fldate wa_sflight-planetype INTO lv_string_flight SEPARATED BY 
     cl_abap_char_utilities=>horizontal_tab. 
     CONCATENATE lv_data_string_flight lv_string_flight INTO lv_data_string_flight SEPARATED BY cl_abap_char_utilities=>newline. 
   ENDLOOP. 

 

  • Similar to the material data section, this block retrieves flight data from the Sflight table based on the airline code (p_carrid). 
  • The relevant flight details are concatenated into a string and stored in lv_data_string_flight. 

Convert Flight Data to XSTRING and Binary: 

 

CALL FUNCTION 'HR_KR_STRING_TO_XSTRING' 
     EXPORTING 
 *     codepage_to      = '8300' 
       unicode_string   = lv_data_string_flight 
 *     OUT_LEN          = 
     IMPORTING 
       xstring_stream   = lv_xstring_flight 
     EXCEPTIONS 
       invalid_codepage = 1 
       invalid_string   = 2 
       OTHERS           = 3. 
   IF sy-subrc <> 0. 
     IF sy-subrc = 1 . 
     ELSEIF sy-subrc = 2 . 
       WRITE:/ 'invalid string ' . 
     ENDIF. 
   ENDIF. 
 ***Xstring to binary 
   CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' 
     EXPORTING 
       buffer     = lv_xstring_flight 
     TABLES 
       binary_tab = lit_binary_content_flight. 

 

This process is identical to the material data conversion. The same functions (HR_KR_STRING_TO_XSTRING and SCMS_XSTRING_TO_BINARY) are used to convert the flight data into binary format. 

Add Flight Data Attachment: 

 

*add attachment 
   CLEAR l_attsubject . 
   CONCATENATE 'Flight_data' sy-datum INTO l_attsubject. 
 * Create Attachment 
   TRY. 
       lo_document->add_attachment( EXPORTING 
       i_attachment_type = 'XLS' 
       i_attachment_subject = l_attsubject 
       i_att_content_hex = lit_binary_content_flight ). 
     CATCH cx_document_bcs INTO DATA(lx_document_bcs_flight). 
   ENDTRY. 

 

  • A new subject for the attachment is created (l_attsubject). 
  • The add_attachment method is used to attach the material data (lit_binary_content) as an Excel file (i_attachment_type = 'XLS') to the email

 

 TRY. 
       lo_sender = cl_sapuser_bcs=>create( sy-uname ). "sender is the logged in user 
       lo_send_request->set_sender( 
       EXPORTING 
       i_sender = lo_sender ). 
   ENDTRY.

 

Here are defining the sender name , using SY-UNAME we are defining that the user who has logged in he is sender . 

Set Recipient for the Email: 

 

DATA(lo_bcs) = cl_bcs=>create_persistent( ). 
   DATA(lo_user) =  cl_sapuser_bcs=>create( i_user = 'HANAUSER15'). 
   lo_bcs->add_recipient( EXPORTING i_recipient  =   lo_user ). 
TRY. 
       lo_send_request->add_recipient( 
       EXPORTING 
       i_recipient = lo_user 
       i_express = 'X' ). 
   ENDTRY. 

 

A recipient is added to the email using cl_sapuser_bcs. Here, the recipient is hardcoded as HANAUSER15, but it can be replaced with p_email (email parameter) for dynamic recipient selection. 

Send the Email: 

 

TRY. 
       CALL METHOD lo_send_request->set_send_immediately 
         EXPORTING 
           i_send_immediately = p_send. "here selection screen input p_send 
  
  ENDTRY. 
   TRY. 
 ** Send email 
       lo_send_request->send( 
       EXPORTING 
       i_with_error_screen = 'X' ). 
       COMMIT WORK. 
       IF sy-subrc = 0. "mail sent successfully 
         WRITE  'Mail sent successfully'. 
       ENDIF. 
   ENDTRY. 

 

  • The send method is called to send the email with all attachments and content. 
  • The COMMIT WORK ensures that the changes are committed to the database. 
  • A success message is displayed if the email is sent successfully. 

 

After activating and executing the code we can see the input screen

Faizan_khan1_0-1737354728921.png

After executing  

Faizan_khan1_1-1737354868500.png 

After executing this we can see the mail in T-CODE SBWP  

Once we open SBWP t-code () we will get a pop up notification

Faizan_khan1_2-1737354907422.png

In the inbox we can see the mails that we have received  

Faizan_khan1_3-1737354956518.png

When we open the Mail we can see that we have 2 attachments with the E-MAIL  

Faizan_khan1_0-1737355044006.png

1 Comment
Sandra_Rossi
Active Contributor

There are many existing blog posts about CL_DOCUMENT_BCS, that would be nice if you could tell what is different in your blog post?

There is no challenge in calling ADD_ATTACHMENT twice instead of existing blog posts which call it once.

A few remarks about the code:

  • I doubt this is needed: CLASS cl_bcs DEFINITION LOAD.
  • Your code is old fashioned (APPEND, CONCATENATE), I guess you're using a very old ABAP version (before 7.40 or even before 7.02)
  • I don't recommend formatting the HTML text with APPEND because you must pay attention to the maximum line length, instead build the text in a very long STRING variable and convert it to an internal table via CL_BCS_CONVERT=>STRING_TO_SOLI. NB: your variable IT_TEXT should be typed according to SOLI_TAB, as per the CREATE_DOCUMENT method signature.
  • HR_KR_STRING_TO_XSTRING is not released, instead use the released class CL_ABAP_CODEPAGE.
  • I don't recommend people using SCMS_XSTRING_TO_BINARY, it has traps, instead use CL_BCS_CONVERT=>XSTRING_TO_SOLIX, which is also much shorter.
  • Note that your "Excel" files are just text files with tab-delimited fields, inconsistent with the file extension .XLS. When Excel opens text files with the extension .XLS, it usually complains with a security warning.
Labels in this area