Skip to Content
SAP Marketing

How To Connect Your Own Email Service Provider to SAP Hybris Marketing (II) - Collecting Bounces

Tags:

Collecting Bounces

In the second part of our example on how to connect SAP Hybris Marketing to an own Email Service Provider, we describe how bounces can be processed. This is the most complex part of the overall example as it contains more business logic and demands at least a basic understanding of the SAP Hybris Marketing business object interaction and its data model. Therefore, we only focus here on the most important parts of the coding. Please refer to the appendix for the complete example implementation.

Bounce data has to be processed asynchronously after outbound emails have been sent. There are mainly two options how to realize the bounce processing described below by implementing the interface IF_CUAN_MKT_EXEC_BOUNCE in your adapter class.

The following methods are available here:

GET_BOUNCE_COLLECTION_MODE

Determines the mode how bounces are collected. Possible values are 'PULL' and 'PUSH'.

This setting is used to control the bounce collection logic implemented by the adapter class. The corresponding methods (see below) are called by the common bounce collection functionality at appropriate points in time to analyze the bounce information and create corresponding interactions if needed.

In our SendGrid example, we implement a pull approach:

METHOD if_cuan_mkt_exec_bounce~get_bounce_collection_mode.

    rv_mode = if_cuan_mkt_exec_bounce=>c_bounce_mode_pull.

ENDMETHOD.


BOUNCES_PULL


By implementing this method, bounces, complaints, other feedback can be collected from the service provider. This is the preferred mode as the control of when to process bounces remains within the responsibility of the SAP Hybris Marketing system.

The RFC destination maintained in the provider definition customizing and the provider ID are available as importing parameters to set up a connection to the service provider's API for getting bounces.

The service provider's bounce information needs to be analyzed and then appropriate interactions for hard and soft bounces shall be created (interaction types EMAIL_BOUNCE_HARD, EMAIL_BOUNCE_SOFT) with appropriate reason codes. Use internal table type CUAN_T_MKT_EXEC_MEMBER_STATUS for preparing the interactions. We recommend to use method UPDATE_INTERACTIONS_BOUNCES of class CL_CUAN_MKT_EXEC_BOUNCES for persisting the interactions. This ensures, that interactions are updated as expected by the campaign metrics functionality, i.e. corresponding successful outbounds (EMAIL_OUTBOUND) become replaced by the bounce interaction.

See our SendGrid example implementation that uses the SendGrid Bounces API:

The main steps implemented here are:

  1. Create the request to the SendGrid Bounces API:
    For the sake of the example we always query for the bounces of the last day.

  2. Identify the bounced email addresses in the HTTP response:
    Here for simplicity we use a regular expression to get the list of bounced email addresses and we ignore the error codes. In our example we simply treat all bounces as general hard bounces.

  3. Identification of Outbound IDs:
    SendGrid is to some extent a special case when it comes to identifying bounced messages. The SendGrid Bounce API only returns the bounced email addresses. Other ESPs typically provide the message ID of the bounced message that refers to the corresponding outbound message (x-message-id in the SendGrid case, see sending part of the example). This makes the example here a bit more complex, but for understanding the basic approach, it is not needed to understand in detail here the SendGrind specific outbound ID handling as described in the next few sentences.
    In the standard adapters form AMAZON and SAP Mobile Services you can see how this then works normally. We simply take the outbound ID returned from the bounce API and can identify in Hybris Marketing the corresponding EMAIL_OUTBOUND interaction. This taken care of for you by using the method cl_cuan_mkt_exec_bounces=>update_interactions_bounces.
    Here in this SendGrid example we identify all EMAIL_OUTBOUND interactions for the bounced email addresses of today and create EMAIL_BOUNCE_HARD interaction for all of them. In the EMAIL_OUTBOUND interaction we have a hash of the original outbound ID. Therefore, for using the standard functionality to update the interactions, we first need to identify the outbound IDs from table CUAND_EXEC_HASH.
  4. Delete processed bounces from SendGrid queue

METHOD if_cuan_mkt_exec_bounce~bounces_pull.

    …

    <coding removed here>

    …

* build GET request

  DATA(lv_start_time) = lv_end_time - 86400. " collect bounces of one day

    lo_client->request->set_method( lo_client->request->co_request_method_get ).

  DATA(lv_request_id) = |?start_time=| && lv_start_time

                        && |&end_time=| && lv_end_time.

    lo_client->request->set_header_field( name = '~request_uri' value = lv_request_id ).

  DATA lt_header TYPE tihttpnvp.

  DATA ls_header_field TYPE ihttpnvp.

    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.

    ls_header_field-name = 'Accept'.

    ls_header_field-value = 'application/json'.

  APPEND ls_header_field TO lt_header.

    lo_client->request->set_header_fields( lt_header ).

* send HTTP request

    lo_client->send( EXCEPTIONS OTHERS = 1 ).

   

    …

    <coding removed here>

    …

*   process bounce payload (find email outbound IAs, create bounce IAs etc.) and deleted from queue

*   get all bounced email adresses

    FIND ALL OCCURRENCES OF REGEX '\"email\":\"([A-Za-z0-9_\-@.]+)\"' IN lv_cdata RESULTS DATA(lt_results).

    DATA lt_bounces TYPE STANDARD TABLE OF string.

    LOOP AT lt_results ASSIGNING FIELD-SYMBOL(<fs_result_tab>).

      DATA(lv_offset) = <fs_result_tab>-offset + 9.

      DATA(lv_length) = <fs_result_tab>-length - 10.

      DATA(lv_message_part) = lv_cdata+lv_offset(lv_length).

      APPEND lv_message_part TO lt_bounces.

    ENDLOOP.

* retrieve outbound IDs for bounced emails (explanations see text and details in appendix)

   

    …

    <coding removed here>

    …

* prepare hard bounces for all bounced email adresses

  DATA: ls_bounce_interaction  TYPE cuan_s_mkt_exec_member_status.

  DATA: lt_bounce_interactions TYPE cuan_t_mkt_exec_member_status.

  LOOP AT lt_outbound_ids ASSIGNING FIELD-SYMBOL(<lv_outbound_id>).

    CLEAR ls_bounce_interaction.

       ls_bounce_interaction = VALUE #( ia_type     = if_cuan_mkt_exec_c=>c_ia_email_bounce_hard

                                                                    outbound_id = <lv_outbound_id> ).

    APPEND ls_bounce_interaction TO lt_bounce_interactions.

  ENDLOOP.

* update the interactions: remove EMAIL_OUTBOUND and create corresponding EMAIL_BOUNCE_HARD interactions

    cl_cuan_mkt_exec_bounces=>update_interactions_bounces(

                    EXPORTING it_bounce_interactions = lt_bounce_interactions

                    IMPORTING et_messages            = DATA(lt_messages)

                                                       ev_error               = DATA(lv_interactions_error) ).

    APPEND LINES OF lt_messages TO et_messages.

*   Delete bounces from SendGrid queue

    …

    <coding removed here>

    …

    lo_client->request->set_method( 'DELETE' ).

  CLEAR ls_header_field.

  REFRESH lt_header.

    ls_header_field-name = 'Authorization' ##NO_TEXT.

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

  APPEND ls_header_field TO lt_header.

    ls_header_field-name = 'Content-Type' ##NO_TEXT.

    ls_header_field-value = 'application/json'.

  APPEND ls_header_field TO lt_header.

    ls_header_field-name = 'Accept' ##NO_TEXT.

    ls_header_field-value = 'application/json'.

  APPEND ls_header_field TO lt_header.

    lo_client->request->set_header_field( name = '~request_uri' value = '' ).

    lo_client->request->set_cdata( data = '{ "delete_all": true }' ).

    lo_client->request->set_header_fields( lt_header ).

    lo_client->send( EXCEPTIONS OTHERS = 1 ).

    …

    <coding removed here>

    …

ENDMETHOD.


BOUNCES_PUSH


By implementing this method, bounces that are pushed via HTTP callback request from the provider to SAP Hybris Marketing can be processed. In order to implement this approach, you need to create an ICF service that is called by the service provider in case of bounces. This approach is more complex from a system integration point of view and the load introduced by the bounce processing in the SAP Hybris Marketing application servers cannot be controlled by the application. (Although load balancing and server groups for the bounce ICF node may be used.)

The HTTP request is accessible via the parameter IF_HTTP_SERVER for retrieving the requests payload representing the bounce data. In analogy to the PULL method interactions need to be created/updated. See the previous section.

Former Member

No comments