Skip to Content

How To Connect Your Own Email Service Provider to SAP Hybris Marketing (I) - Sending Emails



From SAP Hybris Marketing On Premise release 1508 onwards, it is technically possible to connect custom service providers (e.g. for email, text messages, messengers etc.) by implementing a custom provider adapter.

This document describes how this can be achieved in detail using a concrete example for developers. We use SendGrid as an example as it offers the possibility to request a test account for free. Thus, everyone can repeat the described steps here and learn by doing.

(Note that the described example is only a didactic example in order to explain the approach and basic concepts, it is in no way intended/recommended for a productive usage)

Essentially, connecting SAP Hybris Marketing to a custom Email Service Provider (ESP) comes down to implementing several methods in an ABAP adapter class. In the standard delivery--depending on the actual release you are using--adapter classes for AMAZON SES and SAP Mobile Services for Email and SAP Mobile Services / SMS 365 for text messages are included and can be used as examples to learn how to implement a custom adapter class.

The described adapter concept is valid for service providers that offer an HTTP based API (not SMTP based!!) and it is only possible in the on premise deployment of SAP Hybris Marketing, i.e. NOT POSSIBLE in S/4HANA Marketing Cloud.

You will find the documentation of the SendGrid HTTP API that we will use throughout our example here. Please have a look into it to familiarize yourself with the API.

We will split this example into three different documents that deal with different aspects of the connection and an appendix that contains the complete coding:

  1. Sending Emails
  2. Collecting Bounces/Feedback
  3. Specific Integration related topics
  4. Appendix: Complete Example Adapter Implementation

Sending Emails

Provider Configuration

The first step in case a new provider shall be connected to your SAP Hybris Marketing system consists in creating new provider configuration in transaction SPRO:

Use transaction SM59 to create an RFC destination representing the service provider's sending API URL endpoint and enter the RFC destination in field 'HTTP Destination'.

Ensure that the needed certificates for the API endpoint are installed in the PSE using transaction STRUST. Otherwise, you will get SSL handshake errors during the connection test.

Likewise if needed create a destination for the bounce API and enter it in field 'HTTP Dest. Bounce'. This is also described in the SendGrid example when dealing with bounce collection process.

For a documentation of the remaining fields of the provider configuration see the F1 help in IMG.

Enter your custom adapter class ZCL_CUAN_MKT_EXEC_EMAIL_SG (we will discuss in detail how this adapter class will be implemented in the remainder of this document) in the field 'Adapter'. This ensures that your class is used during the campaign execution for campaign content that is created for this provider.

This provider can then be used for creating sender profiles for your campaign content. For testing the adapter class you can then use the send test functionality of the campaign content.

Adapter Class

The adapter class captures all provider specific coding that is needed to connect to a particular ESP.

To get the overall understanding the following picture shows how this class is called at various points in the email execution process:

The swim-lane on the right part represents the adapter class. For sending, two activities (corresponding to two class methods) need to be realized:

  • Build an HTTP request as demanded by the ESP's API
    This includes the metadata of the outbound messages, e.g. recipient, sender information as well as the personalized content of the outbound message, such as subject, text body etc. Additional provider specific logic may be needed here, for example Amazon SES requires signing of the HTTP request using security credentials.

  • Process the synchronous HTTP response
    This includes analyzing HTTP response codes (e.g. 200 for OK) and in particular the handling of error situations and what follow-up steps to take as part of the execution (stop the execution completely, mark the outbound as erroneous but proceed with the remaining outbound messages)

How does an adapter class implementation look in detail?

The adapter class ZCL_CUAN_MKT_EXEC_EMAIL_SG inherits from superclass CL_CUAN_MKT_EXEC_EMAIL (in case of an email service provider). By this it is ensured that the personalized data that is needed to build the outbound request (e.g. recipient, sender, body etc.) is available in class member attributes. By implementing the methods of interfaces IF_CUAN_MKT_EXEC_HTTP_OUTBOUND and IF_CUAN_MKT_EXEC_BOUNCE, the adapter class connects to the custom service provider.

The following class diagram includes the relevant interfaces and classes with the methods that we will describe in detail when implementing the example adapter:

Basic Methods


In case parameters for the sending process are needed (like API access keys), they can be determined using this method. These parameters are read during the campaign automation's pre-processing phase and passed through to the following execution phases and are available again when the constructor of the adapter class is called for actually sending out an email.

A parameter that is needed in the SendGrid example is the API key.

METHOD if_cuan_mkt_exec_http_outbound~get_parameters.

    APPEND VALUE #( param_name  = 'API_KEY'

                                    param_value = '<your sendgrid API key>')

              TO rt_parameters.



Process parameters that are determined using the GET_PARAMETERS methods are available at runtime when the class' constructor is called. The can be put into member variables of the adapter objects for using during the sending/bounce collection phases, respectively.

METHOD constructor.

    super->constructor( it_parameters = it_parameters ).

  DATA(lt_parameters) = it_parameters.

  IF lt_parameters IS INITIAL.

      lt_parameters = me->if_cuan_mkt_exec_http_outbound~get_parameters( ).


  READ TABLE lt_parameters ASSIGNING FIELD-SYMBOL(<ls_api_key>)

      WITH KEY param_name = 'API_KEY'.

  IF sy-subrc = 0.

      me->mv_api_key = <ls_api_key>-param_value.



Sending Outbound Messages (Interface IF_CUAN_MKT_EXEC_HTTP_OUTBOUND)

Sending outbounds consists in (1) preparing the HTTP request to the service provider's API, and (2) processing the HTTP response returned by the service provider's API.


The HTTP request is prepared in this method using the interface IF_HTTP_REQUEST. A reference to an object implementing this interface is imported into this method. It will be used for sending by the execution HTTP outbound functionality after returning from this callback method. See official documentation on how to use this interface in detail.

  METHOD if_cuan_mkt_exec_http_outbound~build_request.

*   Set HTTP verb to POST

       io_request->set_method( io_request->co_request_method_post ).

    DATA lt_header TYPE tihttpnvp.

    DATA ls_header_field TYPE ihttpnvp.

*   Specify the HTTP header fields

       ls_header_field-name = 'Authorization'.

       ls_header_field-value = |Bearer | && me->mv_api_key.

    APPEND ls_header_field TO lt_header.

       ls_header_field-name = 'Content-Type'.

       ls_header_field-value = 'application/json'.

    APPEND ls_header_field TO lt_header.

       io_request->set_header_fields( lt_header ).

*   encode hyphens

    REPLACE ALL OCCURRENCES OF '"' IN me->mv_body_html WITH '\"'.

*   build the HTTP payload

    DATA(lv_body)  = '{"personalizations": [{"to": [{"email": "' && me->mv_recipient && '" } ] } ] ,' &&

                                      '"from": {"email": "' && me->mv_sender && '"},' &&

                                      '"subject": "' && me->mv_subject && '",' &&

                                      '"content": [' &&                     

                                      '{"type": "text/html", "value": "' && me->mv_body_html && '"}],' &&

                                      '"tracking_settings": { "open_tracking": { "enable": false } } }'.

       io_request->set_cdata( EXPORTING data   =  lv_body ).


The first part fills the HTTP request header and the second part creates the request’s body.


After sending the request to the service provider's API and receiving the synchronous response, this callback method is called by the campaign execution HTTP outbound functionality. An IF_HTTP_RESPONSE object is passed into this method.

Based on the HTTP response code and the service provider specific response data, there shall appropriate SAP Hybris Marketing interactions be prepared or error handling done.

In case of success (HTTP code 200 or 202), you should create interactions of type EMAIL_OUTBOUND. Typically, you receive a unique identifier for each outbound message back. Fill this into field OUTBOUND_ID of structure ES_ MEMBER_STATUS. It is needed in the bounce collection process to identify the outbound messages that bounced back. We will describe this in more detail in a later part of the example.

In case of an error, it depends on whether the error is classified as a general (technical) error that is expected to persist for some time. Then, you should abort the execution process by setting EV_STOP_SENDING to 'X'. Otherwise you can prepare an interaction in the method’s exporting structure ES_MEMBER_STATUS that reflects the business error for the individual target group member and proceed executing the remaining TG members.

METHOD if_cuan_mkt_exec_http_outbound~process_response.

    DATA: lv_http_code TYPE i.

    DATA: lv_reason TYPE string.

    DATA: lv_type TYPE string.

    DATA: lv_code TYPE string.

    DATA: lv_message TYPE string.

    DATA: lv_cdata TYPE string.

    DATA: lt_headers TYPE tihttpnvp.

    CLEAR es_member_status.

       io_response->get_status( IMPORTING  code   = lv_http_code

                                        reason = lv_reason ).

       lv_cdata = io_response->get_cdata( ).

       io_response->get_header_fields( CHANGING fields = lt_headers ).

    CASE lv_http_code.

      WHEN 202. "Successful request -> prepare EMAIL_OUTBOUND interaction

               es_member_status-ia_type = if_cuan_mkt_exec_c=>c_ia_email_outbound.

        READ TABLE lt_headers ASSIGNING FIELD-SYMBOL(<ls_header>) WITH KEY name = 'x-message-id'.

        IF sy-subrc <> 0.

*         no outbound id in success case -> fatal error: STOP sending

          MESSAGE e005(cuan_mkt_exec_frw) INTO lv_message.

               cl_cuan_mkt_exec_messages=>add_message( CHANGING ct_messages = et_messages ).

               ev_stop_sending = abap_true.


              es_member_status-outbound_id = <ls_header>-value.

      WHEN OTHERS. "Error -> Stop sending

        MESSAGE e004(cuan_mkt_exec_frw) INTO lv_message WITH lv_http_code lv_reason lv_cdata.

              cl_cuan_mkt_exec_messages=>add_message( CHANGING ct_messages = et_messages ).

              ev_stop_sending = abap_true.



Process integration methods

The following two method need to be implemented too to have an adapter class that works in the whole process. We will come back to the details later here in a dedicated document.

METHOD if_cuan_mkt_exec_http_outbound~check_connection.

    ev_success = abap_false.


METHOD if_cuan_mkt_exec_email~retrieve_verified_senders.

    APPEND '<your email sending domain>' TO et_domains.


Now create a sender profile for your provider and send a test message from the campaign content / content studio. You have sent your first message via SendGrid! Congratulations

Former Member

No comments