Copyright 2022 - BV TallVision IT

For email purpose there is a larger setup available as well - the BCS or Business Communication Service which is accessible via classes. Compose an email with several attachments.

The BCS os Business Communication Service takes care of email sending, even when it is triggered from the SO_DOCUMENT_SEND_API1 function. This article shows how to set up such an email with attachments using classes for

  • CL_BCS - Business Communication Service, which will return a SEND_REQUEST
  • CL_DOCUMENT_BCS - Wrapper class for office documents (en email is such document). Method CREATE_FROM_TEXT will return a DOCUMENT

The logic below can be used to send an email, for which the body text had been composed before. The body is in fact an internal table gt_email_body with text lines of type BCSY_TEXT which consists of lines of type SOLI. The subject has also been prepared before calling this method, gv_subject. The receiver list has also been prepared on this example, as a list of email addresses in gt_receivers. The type of this internal table is a local type definition (ty_receiver), containing only email address (type ad_smtpadr) or the name as well.

  METHOD send_email.
* local objects - referencing classes
    DATA: lo_send_request TYPE REF TO cl_bcs,
          lo_document TYPE REF TO cl_document_bcs,
          lo_receiver TYPE REF TO cl_cam_address_bcs,
          lo_sender TYPE REF TO cl_sapuser_bcs,
* pool of help variables
          lv_status TYPE os_boolean,
          lw_receiver TYPE ty_receiver.

    TRY.
* Create a request handler
        lo_send_request = cl_bcs=>create_persistent( ).

* Link the body text to the email (document type RAW, importance 0 
* and sensitivity F, all defaults)
        cl_document_bcs=>create_from_text(
          EXPORTING
            i_text         = gt_email_body
            i_subject      = gv_subject
          RECEIVING
            result = lo_document ).

* Set the document on the request
        lo_send_request->set_document( 
          EXPORTING i_document = lo_document ).

* Set the receivers
        LOOP AT gt_receivers INTO lw_receiver.
          cl_cam_address_bcs=>create_internet_address(
            EXPORTING i_address_string = lw_receiver-email
                      i_address_name = lw_receiver-name
            RECEIVING result = lo_receiver ).
          lo_send_request->add_recipient( 
            EXPORTING i_recipient = lo_receiver ).
        ENDLOOP.

* Set the sender
        lo_sender = cl_sapuser_bcs=>create( sy-uname ).
        lo_send_request->set_sender( 
          EXPORTING i_sender = lo_sender ).

* Send the email
        lv_status = lo_send_request->send( ).

      CATCH cx_send_req_bcs.
      CATCH cx_document_bcs.
      CATCH cx_address_bcs.
    ENDTRY.
    IF lv_status = 'X'.
*------------------------------ 
      COMMIT WORK.
*------------------------------ 
    ENDIF.

  ENDMETHOD.                    "send_email

Do note the commit work at the end, for whithout it the email will show up in SOSTbut as a half-finished product.

An email with attachments

From the above example the email is enriched with binary attachments like word.doc or image.jpg. The actual source of these documents is not important here, but they need to become available in some form or another. The idea is that the gt_attachments listing contains a variabele of type XSTRING which holds the complete file (attachment). These could originate from anywhere, even from directly reading the file from a server location. In my example I picked it up from cl_hrrcf_attachments where it represented the CV of a job applicant. The other thing the attachment will have to have is a name, in the i_attachment_subject parameter. 

  METHOD send_email.
* local objects - referencing classes
    DATA: lo_send_request TYPE REF TO cl_bcs,
          lo_document TYPE REF TO cl_document_bcs,
          lo_receiver TYPE REF TO cl_cam_address_bcs,
          lo_sender TYPE REF TO cl_sapuser_bcs,
* pool of help variables
          lv_status TYPE os_boolean,
          lw_attachment TYPE ty_attachment,
          lv_subject_att TYPE sood-objdes,
          lv_length_hlp TYPE i,
          lv_length_att TYPE sood-objlen,
          lt_solix TYPE solix_tab,
          lw_receiver TYPE ty_receiver.

    TRY.
* Create a request handler
        lo_send_request = cl_bcs=>create_persistent( ).

* Link the body text to the email (document type RAW, importance 0  
* and sensitivity F, all defaults)
        cl_document_bcs=>create_from_text(
          EXPORTING
            i_text         = gt_email_body
            i_subject      = gv_subject
          RECEIVING
            result = lo_document ).

* Set the document on the request
        lo_send_request->set_document( 
          EXPORTING i_document = lo_document ).

* Add attachment(s)
        LOOP AT gt_attachments INTO lw_attachment.

* Make attachment content available as attachment
          CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
            EXPORTING
              buffer        = lw_attachment-contents "xstring
            IMPORTING
              output_length = lv_length_hlp
            TABLES
              binary_tab    = lt_solix.

          lv_length_att = lv_length_hlp.
          lv_subject_att = lw_attachment-description.
* Add attachment to the document
          lo_document->add_attachment( EXPORTING
             i_attachment_type     = 'BIN' "As binary
             i_attachment_subject  = lv_subject_att
             i_attachment_size     = lv_length_att
             i_att_content_hex     = lt_solix ).

        ENDLOOP.

* Set the receivers
        LOOP AT gt_receivers INTO lw_receiver.
          cl_cam_address_bcs=>create_internet_address(
            EXPORTING i_address_string = lw_receiver-email
                      i_address_name = lw_receiver-name
            RECEIVING result = lo_receiver ).
          lo_send_request->add_recipient( 
            EXPORTING i_recipient = lo_receiver ).
        ENDLOOP.

* Set the sender
        lo_sender = cl_sapuser_bcs=>create( sy-uname ).
        lo_send_request->set_sender( EXPORTING i_sender = lo_sender ).

* Send the email
        lv_status = lo_send_request->send( ).

      CATCH cx_send_req_bcs.
      CATCH cx_document_bcs.
      CATCH cx_address_bcs.
    ENDTRY.
    IF lv_status = 'X'.
*------------------------------
      COMMIT WORK.
*------------------------------
    ENDIF.

  ENDMETHOD.                    "send_email