Skip to content

How to send an email from ABAP

Send plain-text and HTML emails with attachments using CL_BCS — step by step.

Introduction

Sending emails from ABAP comes up in many scenarios:

  • Workflow notifications — alert approvers, requesters, or administrators when a business document changes state.
  • Error reports — a batch job emails a summary of processed records and failures instead of writing to a spool.
  • Scheduled exports — a background program emails a CSV or text file attachment to a distribution list every morning.

The standard approach uses the Business Communication Services (BCS) class family: CL_BCS for the send request, CL_DOCUMENT_BCS for the mail body, and CL_CAM_ADDRESS_BCS for internet addresses. These classes are available from SAP Basis 6.40 onwards and work identically in ECC and S/4HANA.

This tutorial sends via SAPconnect (SCOT)

Emails leave the system through the SAPconnect gateway. The basis team must configure an SMTP node in transaction SCOT before any email can be delivered. Use SOST to monitor the outbound queue and check delivery status.


Prerequisites

  • SAPconnect (SCOT) configured with a valid SMTP node — ask your basis team.
  • Authorization object S_TCODE for transaction SBWP (optional, for manual send queue trigger).
  • Basic knowledge of ABAP OO — all BCS objects are class instances.

Step 1 — Create the send request

The send request (CL_BCS) is the container that holds the document, recipients, and sending options. Create it first; everything else is attached to it.

DATA lo_request TYPE REF TO cl_bcs.

TRY.
    lo_request = cl_bcs=>create_persistent( ).
  CATCH cx_send_req_bcs INTO DATA(lx_bcs).
    MESSAGE lx_bcs->get_text( ) TYPE 'E'.
ENDTRY.

CREATE_PERSISTENT creates a BCS request that is stored in the database (table SOUD). This means it survives until COMMIT WORK is called and the background send job picks it up.

Always use TRY/CATCH with BCS

Every BCS method can raise CX_SEND_REQ_BCS. Wrap all BCS calls in a single TRY block (shown in the full example) rather than checking sy-subrc — BCS uses class-based exceptions exclusively.


Step 2 — Create the document / body

The mail body is a table of SODOCCHGI1 lines — each line holds up to 255 characters. Build the table, then call CL_DOCUMENT_BCS=>CREATE_DOCUMENT.

DATA: lt_body  TYPE STANDARD TABLE OF sodocchgi1,
      ls_line  TYPE sodocchgi1,
      lo_doc   TYPE REF TO cl_document_bcs.

ls_line-line = 'Hello,'.          APPEND ls_line TO lt_body.
ls_line-line = ''.                APPEND ls_line TO lt_body.
ls_line-line = 'This is an automated notification from SAP.'.
APPEND ls_line TO lt_body.

lo_doc = cl_document_bcs=>create_document(
           i_type    = 'RAW'
           i_text    = lt_body
           i_subject = 'SAP Notification' ).

lo_request->set_document( lo_doc ).

Key parameters:

Parameter Value Notes
i_type 'RAW' Plain text. Use 'HTM' for HTML.
i_text lt_body Table of SODOCCHGI1; max 255 chars per line.
i_subject String The email subject line.

HTML emails use i_type = 'HTM'

Set i_type = 'HTM' and populate lt_body with valid HTML. Keep the HTML simple — many email clients strip complex CSS.


Step 3 — Add a TO recipient

Create an internet address object and add it to the request. You can call ADD_RECIPIENT multiple times to add CC/BCC recipients.

DATA: lv_email    TYPE adr6-smtp_addr,
      lo_recipient TYPE REF TO if_recipient_bcs.

lv_email = 'user@example.com'.

lo_recipient = cl_cam_address_bcs=>create_internet_address( lv_email ).

lo_request->add_recipient(
  i_recipient = lo_recipient
  i_express   = abap_true ).

i_express = abap_true flags the message for immediate delivery rather than batched processing, which works in combination with set_send_immediately (Step 5).


Step 4 — Set the sender (optional)

By default, SAP uses the system address as the sender. To send as a specific SAP user or as a named internet address, set the sender explicitly.

" Option A: send as the current SAP user
DATA lo_sender TYPE REF TO if_sender_bcs.
lo_sender = cl_sapuser_bcs=>create( sy-uname ).
lo_request->set_sender( lo_sender ).

" Option B: send as a specific internet address
lo_sender = cl_cam_address_bcs=>create_internet_address(
              i_address_string = 'noreply@example.com'
              i_address_name   = 'SAP System' ).
lo_request->set_sender( lo_sender ).

CL_SAPUSER_BCS requires a valid SAPconnect user mapping

If the SAP user has no email address maintained in SU01, the send will fail with a BCS exception. Use CL_CAM_ADDRESS_BCS with an explicit address to avoid this dependency.


Step 5 — Send and commit

Set the send-immediately flag so the email is dispatched by the next SAPconnect job, then call SEND and commit.

lo_request->set_send_immediately( abap_true ).

lo_request->send( i_with_error_screen = abap_false ).

COMMIT WORK.

COMMIT WORK is mandatory

Without COMMIT WORK the BCS request stays in a temporary state and is never picked up by the send job. This is the single most common reason emails appear to send without error but never arrive. Do not call COMMIT WORK inside a LOOP AT or a function module that may itself be part of a larger LUW.


Full working example

REPORT z_send_email_demo.

"--------------------------------------------------------------------
" Parameters
"--------------------------------------------------------------------
PARAMETERS: p_email   TYPE adr6-smtp_addr OBLIGATORY
                        DEFAULT 'user@example.com',
            p_subject TYPE so_obj_des     OBLIGATORY
                        DEFAULT 'Test email from SAP'.

"--------------------------------------------------------------------
" Main processing
"--------------------------------------------------------------------
START-OF-SELECTION.

  DATA: lo_request   TYPE REF TO cl_bcs,
        lo_doc       TYPE REF TO cl_document_bcs,
        lo_recipient TYPE REF TO if_recipient_bcs,
        lt_body      TYPE STANDARD TABLE OF sodocchgi1,
        ls_line      TYPE sodocchgi1.

  " Build body
  ls_line-line = 'Hello,'.             APPEND ls_line TO lt_body.
  ls_line-line = ''.                   APPEND ls_line TO lt_body.
  ls_line-line = 'This is a test email sent from ABAP using CL_BCS.'.
  APPEND ls_line TO lt_body.
  ls_line-line = ''.                   APPEND ls_line TO lt_body.
  ls_line-line = |Sent by: { sy-uname } on { sy-datum DATE = USER }.|.
  APPEND ls_line TO lt_body.

  TRY.
      " Step 1: create send request
      lo_request = cl_bcs=>create_persistent( ).

      " Step 2: create document
      lo_doc = cl_document_bcs=>create_document(
                 i_type    = 'RAW'
                 i_text    = lt_body
                 i_subject = p_subject ).
      lo_request->set_document( lo_doc ).

      " Step 3: add recipient
      lo_recipient = cl_cam_address_bcs=>create_internet_address( p_email ).
      lo_request->add_recipient(
        i_recipient = lo_recipient
        i_express   = abap_true ).

      " Step 5: send
      lo_request->set_send_immediately( abap_true ).
      lo_request->send( i_with_error_screen = abap_false ).
      COMMIT WORK.

      WRITE: / |Email queued for: { p_email }|.
      WRITE: / 'Check SOST to monitor delivery.'.

    CATCH cx_send_req_bcs INTO DATA(lx_bcs).
      ROLLBACK WORK.
      WRITE: / 'BCS error:', lx_bcs->get_text( ).
  ENDTRY.
REPORT z_send_email_attachment.

PARAMETERS: p_email TYPE adr6-smtp_addr OBLIGATORY
                      DEFAULT 'user@example.com'.

START-OF-SELECTION.

  DATA: lo_request   TYPE REF TO cl_bcs,
        lo_doc       TYPE REF TO cl_document_bcs,
        lo_recipient TYPE REF TO if_recipient_bcs,
        lt_body      TYPE STANDARD TABLE OF sodocchgi1,
        ls_line      TYPE sodocchgi1,
        lt_att_hex   TYPE STANDARD TABLE OF solix,
        lv_att_len   TYPE i,
        lv_content   TYPE string.

  " Build plain-text body
  ls_line-line = 'Please find the attached report.'.
  APPEND ls_line TO lt_body.

  " Build attachment content as a string, then convert to SOLIX
  lv_content = 'ID;Name;Status' && cl_abap_char_utilities=>cr_lf
           && '001;Alpha;Active' && cl_abap_char_utilities=>cr_lf
           && '002;Beta;Inactive' && cl_abap_char_utilities=>cr_lf.

  CALL FUNCTION 'SCMS_STRING_TO_FTEXT'
    EXPORTING
      text = lv_content
    IMPORTING
      ftext_length = lv_att_len
    TABLES
      ftext_tab = lt_att_hex.

  TRY.
      lo_request = cl_bcs=>create_persistent( ).

      lo_doc = cl_document_bcs=>create_document(
                 i_type    = 'RAW'
                 i_text    = lt_body
                 i_subject = 'Report attached' ).

      " Add the attachment to the document
      lo_doc->add_attachment(
        i_attachment_type    = 'CSV'
        i_attachment_subject = 'report.csv'
        i_attachment_size    = lv_att_len
        i_att_content_hex    = lt_att_hex ).

      lo_request->set_document( lo_doc ).

      lo_recipient = cl_cam_address_bcs=>create_internet_address( p_email ).
      lo_request->add_recipient( i_recipient = lo_recipient ).

      lo_request->set_send_immediately( abap_true ).
      lo_request->send( i_with_error_screen = abap_false ).
      COMMIT WORK.

      WRITE: / 'Email with attachment queued.'.

    CATCH cx_send_req_bcs INTO DATA(lx_bcs).
      ROLLBACK WORK.
      WRITE: / 'BCS error:', lx_bcs->get_text( ).
  ENDTRY.

Troubleshooting

Symptom Likely cause Fix
Email visible in SOST but never delivered COMMIT WORK missing, or SAPconnect job not running Add COMMIT WORK after send( ); check SCOT/SOST send job is scheduled
send_immediately has no effect set_send_immediately not called before send( ) Call lo_request->set_send_immediately( abap_true ) before send( )
CX_SEND_REQ_BCS raised Invalid recipient, bad subject, or BCS internal error Wrap all BCS calls in TRY/CATCH; call lx_bcs->get_text( ) for the exact message
Email arrives with wrong sender / bounce SAP user has no email in SU01, or CL_SAPUSER_BCS used with unmapped user Use CL_CAM_ADDRESS_BCS=>CREATE_INTERNET_ADDRESS with an explicit address string
Attachment empty or corrupt SCMS_STRING_TO_FTEXT not called, or wrong length passed Verify lv_att_len returned by SCMS_STRING_TO_FTEXT is > 0 before attaching
Email in SOST shows status "Error" SMTP relay not reachable, TLS mismatch, or wrong port in SCOT Check SCOT SMTP node settings; ask basis to test with SBWP

See also

  • CL_BCS — full class reference, constructor options, and advanced usage
  • Transaction SCOT — configure the SAPconnect SMTP node
  • Transaction SOST — monitor the outbound email queue and resend failed messages
  • Transaction SBWP — SAP Business Workplace; useful for manual send tests

Comments