Skip to Content
Technical Articles
Author's profile photo Prabhjot Bhatia

E-Mail Templates in S/4 HANA

E-Mail communication is very common business requirements in day-to-day life. SAP understands that and comes up with very interesting feature in S/4 HANA (cloud and on premise both) – E-Mail Templates. In this article, I will provide a little overview and a demo of E-Mail templates.


What is E-Mail templates ?

With S/4 HANA Output Management, SAP provides E-mail templates to be configured which will be mapped to output types in BRF+. We can maintain HTML and Plain text in different languages in these  E-Mail templates and also, can map a CDS view for handling dynamic variables. This feature would save a lot of hardcoding or other custom ways to maintain E-mail content as done in past. Although in S/4 HANA, SAP uses E-Mail templates specifically in output management, still we can use this feature independent of output configurations and we will see in Demo section below for its usage.



  • Basic Knowledge of CDS views.
  • Good knowledge of ABAP.
  • Basic understanding of HTML.


How to create E-Mail Template?

There is no specific transaction to create email templates but we can create it as a repository object in SE80 transaction as follow:

  1. Select the package ( or Local objects ) and right click.
  2. Select “Create” -> “More” -> “Email Template”


However, we can always view/Edit the existing E-Mail templates from program SMTG_WB_START.

Different Component in E-Mail templates:

Header –

  • We need to maintain a name / description for the email template.
  • Also, we can maintain a CDS view which should be pre-delivered and can be used to provide dynamic variables in email content (body or subject).


  1. Languages             Maintain Email in different languages
  2. CDS Fields             Set of CDS view fields used in Email content
  3. Email Subject         Email subject description
  4. Body HTML            Email body content in HTML
  5. Body Plain Text      Email body content in plain text

Dynamic Variables in E-mail Content:

For maintaining dynamic variables, we would need to create a CDS view which would contain the required data. For each different email variables, we can pass CDS key with Name/Value pair to Email Template API classes and replace the variables with desired content very easily.

  • Create a CDS view ZRSCDS_INVOICE_DATA (for demo, I took reference of billing document header and Item tables).
@AbapCatalog.sqlViewName: 'ZRSCDS_INVDATA'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Invoice Data Line Item wise' 
as select from vbrk as zzrs_vbrk
join vbrp as zzrs_vbrp
    on zzrs_vbrk.vbeln = zzrs_vbrp.vbeln 
 key zzrs_vbrk.vbeln,
 key zzrs_vbrp.posnr,      
     @Semantics.currencyCode: true
     @Semantics.amount.currencyCode: 'waerk' 
     @DefaultAggregation: #SUM
     zzrs_vbrk.kunag as kunag,      
  • Add this CDS view in Email template Header.

  • Assign CDS view fields in E-Mail Body and Subject where ever required.


Email Preview-

We can always preview our email template how it will look once sent to customers by clicking on “preview” button as highlighted:


How to call E-Mail Templates ?

Till now, I have created E-mail templates in system. Now, I would like to integrate this in one of the calling programs which send email to customers and email content will be taken from templates. For the demo purpose, I created a simple program where I can pass receiver email address, E-Mail Template, Language and CDS Key ( Billing Document in our case ).

SAP has provided E-Mail template API class which can be instantiated and used to get email content. Steps are as follow:

  • Create instance of class CL_SMTG_EMAIL_API.
DATA(lo_email_api) = cl_smtg_email_api=>get_instance( iv_template_id = p_em_id  ).
  • Create instance of class CL_BCS.
DATA(lo_bcs) = cl_bcs=>create_persistent( ).
  • Prepare CDS view Key table with Key Field name and value.
DATA(lt_cds_key) = VALUE ty_gt_data_key( ( name = 'vbeln' value = p_vbeln ) ).
  • Integrate E-Mail subject and body with email instance
lo_email_api->render_bcs( io_bcs = lo_bcs iv_language = p_spras it_data_key = lt_cds_key ). 
  • Set Sender, receiver and send the email.
  " Set Email Sender
  DATA(lo_sender) = cl_sapuser_bcs=>create( sy-uname ).

  lo_bcs->set_sender( i_sender = lo_sender ).

  " Set Email Receiver(s)
  DATA(lo_recipient) = cl_cam_address_bcs=>create_internet_address( p_rec ).
  lo_bcs->add_recipient( EXPORTING i_recipient = lo_recipient ).

  " Send Email
  lo_bcs->send( ).


Selection-Screen of Demo Program :


Result Email with replacement of dynamic variables :



Assigned Tags

      You must be Logged on to comment or reply to a post.
      Author's profile photo Ibrahim Khan
      Ibrahim Khan

      Hi prabhjot,

      Excellent blog, can you please let me know how to embed images to the email template?




      Author's profile photo Sandra Rossi
      Sandra Rossi

      I guess you can do it in two steps:


      1. Position the image where you want in the body HTML, and assign it any CID name you want (Content-ID):

      <img src="cid:any-name-you-want">


      2. in the ABAP code, get the email HTML by using the method RENDER instead of RENDER_BCS, and create the document from scratch via BCS by using multipart, one part being the image to which you assign the Content-ID chosen in the first step.


      lo_email_api->render( IMPORTING ev_body_html = DATA(body_html) ).
      DATA(body_html_soli) = cl_bcs_convert=>string_to_soli( body_html ).
      DATA(multipart) = NEW cl_gbt_multirelated_service( ).
            content     = body_html_soli
            description = 'descriptionhtml'.
            content      = image_png_solix " BYTES OF IMAGE (PNG or other type)
            filename     = 'filename.png'
            extension    = 'PNG'
            description  = 'descriptionpng'
            content_type = 'image/png'
            length       = l_len
            content_id   = 'any-name-you-want'.
      DATA(doc_bcs) = cl_document_bcs=>create_from_multirelated(
                i_subject          = 'email subject'
                i_multirel_service = multipart ).
      lo_bcs->set_document( doc_bcs ).


      Addendum October 15, 2019:

      There's a second option:

      You may also hardcode the image inside the body HTML with <img src="data:image/png;base64,HERE-BASE64-OF-IMAGE">. The advantage is that there's no ABAP code and the image is displayed if you preview the email, but the body HTML is difficult to maintain because it's full of base64 characters.


      <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
        <meta name="generator" content="HTML Tidy for SAP R/3 (vers 25 March 2009), see">
      Text before icon. Icon "LEFT ARROW": <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAIAAADUsmlHAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAVklEQVR42mN88/IGA7mAiYECMAg1uza+JVMzMTqxayZSJwMDAyNaVBGjc3e9MBabibcTXTOpOlE0wx1DZlSRqp8RM23D3U/QLCY8gUlmIiFSP+PQzJIA5rYeiLeQLUYAAAAASUVORK5CYII=">. Text after icon.
      Author's profile photo Prabhjot Bhatia
      Prabhjot Bhatia
      Blog Post Author

      Thanks Sandra.

      I already used option1 in the demo example. and It’s really helpful and good to know about option 2. I will try to integrate it in my applications now.

      But in this case, we can't use email templates.


      Author's profile photo Sandra Rossi
      Sandra Rossi

      I'm confused about "option 1" and "option 2": are you talking about RENDER_BCS versus RENDER, or are you talking about the two steps of the solution I proposed (which are not options 1 and 2, it's steps 1 and 2)?

      In which case can't we use email templates?

      Author's profile photo Prabhjot Bhatia
      Prabhjot Bhatia
      Blog Post Author

      I misunderstood that .

      I meant I used the step 1 in the demo example. I generated the image URL separately and added the url in HTML directly as <img src = imageURL> .

      In that case, I didnt need to use step 2 and that's the real use of E-Mail templates -to customize email body content( plain or HTML ) and call that in applications.

      I hope it clarify the confusion.

      Author's profile photo Julio Ferrero Flores
      Julio Ferrero Flores


      Could you, please, tell me how it does what you indicate above? (I meant I used the step 1 in the demo example. I generated the image URL separately and added the url in HTML directly as <img src = imageURL> )

      I upload the image to MIME repository but i don´t know how to create the url of the image.


      Author's profile photo Neelesh Jain
      Neelesh Jain

      Thanks Prabhjot for very useful and self-explanatory blog.

      can you confirm whether CSS can also be attached?




      Author's profile photo Prabhjot Bhatia
      Prabhjot Bhatia
      Blog Post Author

      Thanks Neelesh.

      I have used CSS stsylehseet in the HTML in the example in this blog.

            <style type="text/css">
      /* Client-specific Styles */
               #outlook a {padding:0;} /* Force Outlook to provide a "view in browser" menu link. */
               body{width:100% !important; -webkit-text-size-adjust:100%; -ms-text-size-adjust:100%; margin:0; padding:0;}
               /* Prevent Webkit and Windows Mobile platforms from changing default font sizes, while not breaking desktop design. */        
               #backgroundTable {margin:0; padding:0; width:100% !important; line-height: 100% !important;}
               img {outline:none; text-decoration:none;border:none; -ms-interpolation-mode: bicubic;}
               a img {border:none;}       
               /*p {margin: 0px 0px !important;}*/
               table td {border-collapse: collapse;}
               table {border-collapse:collapse; mso-table-lspace:0pt; mso-table-rspace:0pt;  }
               a {color: #193c6b;text-decoration:none;} 
               /* Our Styles */
               body {font-family: Calibri, Arial, sans-serif;}
      		 .csLink a {color:#666666!important;text-decoration:none!important;}
      		 .csNr a {color:#193c6b!important;text-decoration:none!important;}
      		 .csNr2 a {color:#333333!important;text-decoration:none!important;}
               a[x-apple-data-detectors] {
                  color: inherit !important;
                  text-decoration: none !important;
                  font-size: inherit !important;
                  font-family: inherit !important;
                  font-weight: inherit !important;
                  line-height: inherit !important;
                /*IPAD STYLES*/
                @media only screen and (max-width: 640px) {             
                  table.devicewidth, img.gradientbottom  {width: 440px!important;}
                  table.devicewidthinner, table.prow {width: 400px!important;} 
      			img.imggradient {width:212px!important;}
      			img.bannerimg {width:440px!important;height:73px!important;}
      			td.padleft {padding-left:0px!important;}
               /*IPHONE STYLES*/
               @media only screen and (max-width: 480px) {
                   table.devicewidth, img.gradientbottom  {width: 320px!important;}
      			 table.devicewidthinner{width: 280px!important;}
                   img.imggradient {width:92px!important;}
      			 img.bannerimg {width:320px!important;height:53px!important;}

      I am not sure whether you want to use CSS explicitly as SAP has given option to add HTML files in the body HTML. But we can always integrate CSS in HTML and use here.


      Author's profile photo Michael Keller
      Michael Keller

      When I used class CL_BCS to create HTML mail there was some strange situation: Only inline CSS was ok to use in the body. It wasn't a problem of CL_BCS but of the mail clients like Outlook. Don't know if this is important in this context.

      Author's profile photo Raza Hassan
      Raza Hassan

      Hi Prabhjot,


      Very nice and informative article. Please let me know if there is a way to add CC and BCC recipients in email?

      Also, how to add system attachments via this class?

      Thanks in advance.

      Author's profile photo Prabhjot Bhatia
      Prabhjot Bhatia
      Blog Post Author

      Thanks Raza.

      E-Mail templates are only used to configure E-Mail content which is Email Body and Subject.

      Sender information with different roles TO,CC,BCC are not covered in this. You need to define or configure these information on your application where you will call email templates.

      Same for attachments 🙂


      Author's profile photo Former Member
      Former Member

      That should be same way as we do with the BCS class, this is only to handle the e-mail body template. Right?

      Author's profile photo Timo Sandlass
      Timo Sandlass

      Hi Prabhjot Bhatia,

      in the last few Weeks i am developing a Fiori App which uses the new E-Mail Templates, but for certain time i have problems with the text Replacement.

      If you do a little research, you will quickly find, that the Replacement of the dynamic variables will happen in the APPLY( )-method of CL_SMTG_EMAIL_RENDERER. In my opinion it doesn't matter whether you call APPLY( ) directly or indirectly via BCS as long as you supply the method correctly.
      But i have a big Problem with the Replacement of some Fields.

      Most of the Fields are replaced without any problem, except two types: dates and currency amounts. Both have one in common: they have a differen internal format and an external format. Dates can be displayed in different shapes, depending on your systems customizing in table T005X . But every time i want to replace a date, e.g. a date of DDIC-type BLDAT it only displays the internal format like 20191015 instead of 15.10.2019 or 10/15/2019 etc.
      Even by debugging and modifying some things i was unable to get the system to replace the variable with the external format.

      In the coding at CL_SMTG_EMAIL_RENDERER in his private Method FORMAT_FIELD_VALUE i found following comment: "DATS field is not converted currently as the date format of the *receiver* of the mail template is not knwown... Using the format of the currently logged in user may not be appropriate." But this is exactly what i want to happen.

      Is there any possibility to do so or do i have to implement the replacement in my application by myself?

      Thanks in advance

      Author's profile photo Arun Reddy
      Arun Reddy

      Hi Prabhjot,

      Thanks for the nice blog.

      Can we add table in the template with dynamic variables in the table?

      Thanks in advance.


      Author's profile photo Prabhjot Bhatia
      Prabhjot Bhatia
      Blog Post Author

      Hi Arun,

      Thanks for reading.

      Since dynamic values are filled from CDS views, I don't think you can add tables in dynamic variables. 

      Do you have any real time example where tables are required as dynamic variables?

      Thanks and regards,


      Author's profile photo Gurpreet Singh Jaspal
      Gurpreet Singh Jaspal

      Hi Prabhjot Bhatia,

      I have a similar query. CDS can also return multiple records therefore can that be added as part of a tabular section in the email. For example, consider that there is a requirement to send the open invoices at end of every month to all customers. Is there any way this can be achieved to get an output like below?

      example CDS Structure with association to customer master as _customer


      key inv_no,

      key payer,







      Dear {_customer.customer_first_name},

      Please find your open inoices for period {period}.

      Invoice Number                             Date                 Amount

      {inv_no}                                          {date}                {amount}


      Finance Team





      Author's profile photo shrikant more
      shrikant more

      Hi Prabhjot Bhatia,


      Thanks for your article.its really helpful.

      is it possible to display a table in the Email Template?

      as I tried but unable to get the option for that.



      Shrikant More.

      Author's profile photo Timo Sandlass
      Timo Sandlass

      Hey Shrikant,

      as far as i know E-Mail-Templates fully support HTML. Did you already tried to use HTML for creating a Table? If you don't know how this works out in HTML there are plenty of good Tutorials out there, i.e.W3Schools where i always look up stuff like that.

      And in these tables you are free to use any given data from your CDS View.

      I did't tried out but for tables of variable length you could modify the mails HTML-Body with your ABAP-Code and insert another row for each row of your datatable (e.g. internal table).



      Author's profile photo Varun Jain
      Varun Jain

      HI Prabhjot Bhatia ,

      by any change can it be integrated with classes or dynamic tables . Use case I am working on SAP MDG and here tables are dynamic so we want to read table we need to class method to get data no other possible way to read .

      If that is possible then that will be big assets as email is frequent requirement we have  at any project we do.



      Author's profile photo Prabhjot Bhatia
      Prabhjot Bhatia
      Blog Post Author

      Hi Varun,

      If I understand correctly, you want email data dynamically instead of depending on data driven cds fields. If yes, it's possible to integrate those fields and populate the data independent of cds view data.



      Author's profile photo Sathya Prabhu Narayanasamy
      Sathya Prabhu Narayanasamy

      Hello Prabhjot,


      Thanks for the blog.

      How can pass the data to the E-Mail template independent of the CDS. I am calling the template from report program where I need to generate an FIORI URL and append it to a table. Generation of URL is not possible in AMDP, so I have to do it via ABAP.

      Essentially E-Mail with table consists of data and URL in a cell on every row.



      Author's profile photo Varun Jain
      Varun Jain

      HI Prabhjot Bhatia ,

      Correct , so I take example of Material , I would like to send Materiel related field data at email body , but during MDG process this data wont be available at MARA table it would at some temp table which generates dynamically at each system and only way to read is via MDG APIs.

      I am sure CDS view , but can CDS view call an standard API and get data or I create rapper api and which can feed to CDS view ?



      Author's profile photo Former Member
      Former Member

      CDS is a data modelling technique no it can not call any API.

      Author's profile photo Martin Maida
      Martin Maida

      Hello all (  Prabhjot Bhatia )


      Someone can help me?


      I need to create a Email template and into the body include a list of documents.


      So, i should include in the template a TABLE.


      I was debugging the std class but, when recover the information from CDS, always is with ONE RECORD ( not getting the list of documents)


      Is it possible to send an email with a table with severals records?


      thanks in advance 



      Author's profile photo Former Member
      Former Member

      table with several records should ideally be in an attachment not the email body though it is possible using <table> of html. thanks

      Author's profile photo Sushnata Satpathy
      Sushnata Satpathy

      Hello @Prabhjot Bhatia

      Thank you for this helpful blog .

      Is this possible in  ECC 702 version.


      Thank you  in advance

      Author's profile photo Prabhjot Bhatia
      Prabhjot Bhatia
      Blog Post Author

      No.. It's only available from 7.5 version specifically to be used by SAP in new Output Management in S/4 HANA.

      Author's profile photo Ratul Chakraborty2
      Ratul Chakraborty2

      Nice one

      Author's profile photo fabrizio comuzzi
      fabrizio comuzzi

      Hi Prabhjot,

      Excellent blog!

      Is it possible to pass data to template variables directly from the invoking code instead of using a CDS view?

      Class CL_SMTG_EMAIL_API has a method RENDER_BCS_W_DATA. It looks as this is what I need but there is no documentation about how to use the method.

      Do you have any idea?

      Thanks in advance



      Author's profile photo Prabhjot Bhatia
      Prabhjot Bhatia
      Blog Post Author


      I have used method RENDER_BCS_W_DATA and I will post a new blog to cover a business scenario. I agree with you regarding documentation for these topics but we also need to understand that these things are quite new and SAP is still doing/releasing OSS notes based on customer's requirements.So these blogposts would be better place for any documentation.


      Author's profile photo Thorsten Wöhrle
      Thorsten Wöhrle

      Hello Fabrizio,

      I tried to use method RENDER_BCS_W_DATA. My idea was to user these fields also in the email template.

        ls_comp-name = 'FIELD1'.
        ls_comp-type ?= cl_abap_typedescr=>describe_by_name( 'CHAR10' ).
        APPEND ls_comp TO lt_comp.
        ls_comp-name = 'FIELD2'.
        ls_comp-type ?= cl_abap_typedescr=>describe_by_name( 'CHAR12' ).
        APPEND ls_comp TO lt_comp.
        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> = 'Value 1'.
        ASSIGN COMPONENT 2 OF STRUCTURE <ls_data> TO <fs_value>.
        <fs_value> = 'Value 1'.
              io_bcs      = lo_bcs
              iv_language = 'D'
              ir_data     = lr_data  ).

      But if the fields are not part of the CDS view, the matches are deleted.
      This method can only be used, to fill the values which are part of the CDS view.

      Author's profile photo Patrick Weber
      Patrick Weber

      Hello Thorsten,

      may I ask you to show some more code? I also want to use some data from CDS View, but others should be set by code. To my understanding, this is what you've solved here.

      The code you've shown above doesn't have any relation to CDS view anymore.

      It would be really great, if you can provide a sample code of how to achieve this.


      Author's profile photo Thorsten Wöhrle
      Thorsten Wöhrle

      Hello Patrick.

      In my exmaple only varialbes are used, which are filled from code. Field CDS view is not filled.


      subject mail template


      Variables and their values are maintained with an internal table.

      *+++ Fill table to replace variables in Emmail template
        it_email_tpl_vars_cdskey = VALUE #( ( name = 'MATNR' value = ycl_me6_material_helper=>set_matnr_output_format( iv_matnr_in = p_matnr ) ) 


      This is a central method to replace the variables with the corresponding content from IT_EMAIL_TPL_VARS_CDSKEY:

      *== Email text: subject and body
          CLEAR: ev_subject, ev_subject_long, et_html_text, et_plain_text.
      *== Für Referenzierung noch ohne SprachBezug
              DATA(lo_email_api) = cl_smtg_email_api=>get_instance( iv_template_id = iv_email_template  ).
              DATA(ls_email_template) = lo_email_api->get_detail( ).
              DATA(lo_email_template) = cl_smtg_email_template=>get( iv_email_template  ) .
              DATA(lo_email_renderer) = cl_smtg_email_renderer=>get_instance( io_template = lo_email_template ).
      *== IF field CDS View is maintainded, the key fields are maintainend in import table IT_VARIABLEN to to replace the variable         lo_email_renderer->apply(
                  it_data_key   = COND #( WHEN ls_email_template-header-cds_view IS NOT INITIAL THEN it_email_tpl_key_vars )
                  iv_language   = iv_email_tpl_langu
                  ev_subject    = DATA(lv_subject)
                  ev_body_html  = DATA(lv_body_html)
                  ev_body_text  = DATA(lv_body_text)
                  et_attachment = DATA(lt_attachment) ).
            CATCH cx_smtg_email_common INTO DATA(lx_email).
              RAISE EXCEPTION TYPE ycx_so5_general USING MESSAGE.
      *== If field CDS View is empty, variables of table it_email_tpl_key_vars replaced
          IF ls_email_template-header-cds_view IS INITIAL.
            LOOP AT it_email_tpl_key_vars INTO DATA(ls_data_key).
              REPLACE ALL OCCURRENCES OF |{ mc_sqbracket_start && ls_data_key-name && mc_sqbracket_end }|:
                                          IN lv_subject WITH ls_data_key-value,
                                          IN lv_body_html WITH ls_data_key-value,
                                          IN lv_body_text WITH ls_data_key-value.

      Maybe this can be adjusted to use CDS views and own variables.




      Author's profile photo Patrick Weber
      Patrick Weber

      Thank you Thorsten for this great example.

      I was able to get RENDER_BCS_W_DATA running but it's like you said, if a field is not part of CDS view, it gets ignored. To use it, we have to define these code-filled fields as empty fields in CDS View.

      Your code looks more clean as you don't need to define dynamic table anymore.

      Author's profile photo Former Member
      Former Member

      Thank you Prabhjot Bhatia , I was looking for something like this. Great work!!!



      Author's profile photo Mayank Sharma
      Mayank Sharma

      Hi Prabhjot,

      Nice blog on Email Templates!!

      i had one question is it a clean core approach since in S/4HANA cloud you dont have option to create custom e-mail template ?



      Author's profile photo Jelena Perfiljeva
      Jelena Perfiljeva

      I'm not an expert but watching this openSAP video on email templates for Flexible Workflow in S/4 Cloud and it does talk about custom templates:

      So I'm curious where you got the information that there is no such option.

      Author's profile photo Ashok Kumar
      Ashok Kumar

      Hello Prabhjot Bhatia,

      Excellent Blog.


      Could you Please Tell how to add images in the Email Template,

      I checked the Solution that you provided in this Blog But Unfortunately I am not able to add Image in the Email Template.

      So could you please Explain how to add Image in the Email Template



      Ashok Kumar

      Author's profile photo Aditya Waghmare
      Aditya Waghmare

      Just follow the second option in this comment by Sandra Rossi

      Convert your desired image into Base64 (you can use this site or google for any other). Copy the base64 code and use it as sandra used it here:


      Just replace the part after 'base64 ,' with your actual base64 code of image

      Author's profile photo ana osako
      ana osako



      someone could post an example with multiple lines in cds wich can use in htlm template?

      Author's profile photo B. Blei
      B. Blei

      Hello Prabhjot Bhatia, nice blog!


      I have a question regarding adding (multiple) attachments.

      How would you do this when working with OPM en Adobe?

      Is this also possible in the email template?

      Were would I create the code to add additional attachments to the emai?

      Kind regards,

      Berry Blei