Showing posts with label EMAIL. Show all posts
Showing posts with label EMAIL. Show all posts

Wednesday, July 19, 2017

Send email with high importance from ABAP

There is an easy to grasp function module EFG_GEN_SEND_EMAIL, which is a kind of wrapper over CL_BCS class. Unfortunately EFG_GEN_SEND_EMAIL does not support email high priority sign (nice red exclamation mark within Outlook) in any input parameter.

I have a made a custom clone of this FM supporting high importance sign. I converted the coding into static method of a custom repository class. Please, no flame war for usage of static method ;-), there is no need to have an instance.


Original call of FM:


    CALL FUNCTION 'EFG_GEN_SEND_EMAIL'
      EXPORTING
        i_title                iv_title
        i_sender               iv_sender
        i_recipient            ''
        i_flg_send_immediately 'X'
      TABLES
        i_tab_lines            t_mail_text
        i_tab_recipients       t_recipients
      EXCEPTIONS
        not_qualified          1
        failed                 2
        OTHERS                 3.
    IF sy-subrc NE 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.


Call of custom method (almost the same):


    TRY.
        CALL METHOD /yournamespace/cl_email=>send_email
          EXPORTING
            iv_title          iv_title
            iv_sender         iv_sender
            iv_high_priority  abap_true
            iv_recipient      ''
          CHANGING
            ct_tab_lines      t_mail_text
            ct_tab_recipients t_recipients.
      CATCH cx_root.
        MESSAGE ID sy-msgid TYPE 'E' NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDTRY.



Description of the custom repository class 


There is one static method with following input parameters:



The complete method source code:


METHOD send_email.

  DATAlt_recipients     TYPE STANDARD TABLE OF string,
        lv_string         TYPE string,
        lo_ref_send_req   TYPE REF TO cl_bcs,
        lt_text           TYPE bcsy_text,
        lo_ref_doc        TYPE REF TO cl_document_bcs,
        lo_ref_recipient  TYPE REF TO if_recipient_bcs,
        lo_ref_sender     TYPE REF TO if_sender_bcs,
        lx_rex_bcs        TYPE REF TO cx_bcs,
        lx_rex_addr       TYPE REF TO cx_address_bcs,
        lv_smtp_addr      TYPE adr6-smtp_addr,
        lv_subject        TYPE so_obj_des,
        lt_soli           TYPE soli_tab,
        ls_soli           TYPE soli,
        lv_uname          TYPE uname,
        lv_importance     TYPE bcs_docimp.

  IF iv_sender IS INITIAL.
    RAISE EXCEPTION TYPE cx_bcs
      EXPORTING
        msgty 'E'
        msgid '00'
        msgno 007
        msgv1 'Sender'.
  ENDIF.

  IF iv_title IS INITIAL.
    RAISE EXCEPTION TYPE cx_bcs
      EXPORTING
        msgty 'E'
        msgid '00'
        msgno 007
        msgv1 'Title'.
  ENDIF.

  IF ct_tab_lines IS INITIAL.
    RAISE EXCEPTION TYPE cx_bcs
      EXPORTING
        msgty 'E'
        msgid '00'
        msgno 007
        msgv1 'Content'.
  ENDIF.

  IF ct_tab_recipients[] IS INITIAL AND iv_recipient IS INITIAL ).
    RAISE EXCEPTION TYPE cx_bcs
      EXPORTING
        msgty 'E'
        msgid '00'
        msgno 007
        msgv1 'Recipient'.
  ENDIF.

  IF NOT iv_sender CS '@'.
    cv_flg_sender_is_uname 'X'.
  ENDIF.

  lt_recipients ct_tab_recipients[].
  APPEND iv_recipient TO lt_recipients.

  DELETE lt_recipients
    WHERE table_line IS INITIAL.

  SORT lt_recipients BY table_line.
  DELETE ADJACENT DUPLICATES FROM lt_recipients.

  TRY.
      lo_ref_send_req cl_bcs=>create_persistent).

*     sender
      TRY.
          IF cv_flg_sender_is_uname IS INITIAL.

            lv_smtp_addr       iv_sender.
            lo_ref_sender      cl_cam_address_bcs=>create_internet_address(
              i_address_string lv_smtp_addr
              i_address_name   lv_smtp_addr
            ).
          ELSE.
            lv_uname iv_sender.
            lo_ref_sender cl_sapuser_bcs=>createi_user =  lv_uname ).
          ENDIF.

        CATCH cx_address_bcs INTO lx_rex_addr.
          RAISE EXCEPTION lx_rex_addr.
      ENDTRY.

      lo_ref_send_req->set_senderlo_ref_sender ).

*      recipient (e-mail address)
      LOOP AT lt_recipients INTO lv_smtp_addr.
        lo_ref_recipient cl_cam_address_bcs=>create_internet_addresslv_smtp_addr ).
*       add recipient with its respective attributes to send request
        lo_ref_send_req->add_recipientlo_ref_recipient ).
      ENDLOOP.

*     document
      APPEND LINES OF ct_tab_lines TO lt_soli.
      lv_subject  iv_title.

      IF iv_high_priority EQ abap_true.
        lv_importance '1'.
      ENDIF.

      lo_ref_doc cl_document_bcs=>create_document(
        i_type       'RAW'
        i_text       lt_soli
        i_length     '100'
        i_subject    lv_subject
        i_importance lv_importance
      ).

*     add document to send request
      lo_ref_send_req->set_documentlo_ref_doc ).

      IF NOT iv_flg_send_immediately IS INITIAL.
        lo_ref_send_req->set_send_immediately'X' ).
      ENDIF.

      lo_ref_send_req->set_status_attributes'N' ).
      lv_string iv_title.
      lo_ref_send_req->set_message_subjectlv_string ).
      lo_ref_send_req->send).

      IF NOT iv_flg_commit IS INITIAL.
        TRY.
            COMMIT WORK.
          CATCH cx_root.
        ENDTRY.
      ENDIF.

    CATCH cx_bcs INTO lx_rex_bcs.
      RAISE EXCEPTION lx_rex_bcs.
    CATCH cx_root.
  ENDTRY.

ENDMETHOD.



The usage is very easy, you have to always provide some email body, title - subject, sender and recipient. You can do that as follows within some arbitrary class. Play with it a you want..



CLASS lcl_ctrl_email DEFINITION.

  PUBLIC SECTION.
    METHODS:
      send_email
        IMPORTING
          iv_title           TYPE clike
          iv_sender          TYPE clike.

  PRIVATE SECTION.
    DATAt_mail_text        TYPE soli_tab,
          t_recipients       TYPE STANDARD TABLE OF ad_smtpadr.

    METHODS:

      generate_content,
      get_recipients.

ENDCLASS.                    "lcl_ctrl_email DEFINITION


CLASS lcl_ctrl_email IMPLEMENTATION.
  METHOD generate_content.

    DATAls_mail_text TYPE soli.

    ls_mail_text 'Hello,'.
    APPEND ls_mail_text TO t_mail_text.

    ls_mail_text ''.
    APPEND ls_mail_text TO t_mail_text.

    ls_mail_text 'this is an email content example...'.
    APPEND ls_mail_text TO t_mail_text.

    ls_mail_text ''.
    APPEND ls_mail_text TO t_mail_text.

    ls_mail_text 'Regards,'.
    APPEND ls_mail_text TO t_mail_text.

    ls_mail_text 'Your team'.
    APPEND ls_mail_text TO t_mail_text.

  ENDMETHOD.                    "generate_content.

  METHOD get_recipients.

    SELECT email FROM /yournamespace/email_addr
      INTO TABLE t_recipients.

  ENDMETHOD.                    "get_recipients

  METHOD send_email.

    generate_content).
    get_recipients).

    TRY.
        CALL METHOD /yournamespace/cl_email=>send_email
          EXPORTING
            iv_title          iv_title
            iv_sender         iv_sender
            iv_high_priority  abap_true
            iv_recipient      ''
          CHANGING
            ct_tab_lines      t_mail_text
            ct_tab_recipients t_recipients.
      CATCH cx_root.
        MESSAGE ID sy-msgid TYPE 'E' NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDTRY.

  ENDMETHOD.                    "send_email

ENDCLASS.                    "lcl_ctrl_email IMPLEMENTATION



Source:  https://archive.sap.com/discussions/thread/1953259

Friday, August 29, 2014

HTML Email with tables generated by SmartForm

Intro

There are various possibilities how to work with emails in SAP. Previously I used some function module. When I obtained a task to prepare an email message with some log info content e.g. this job passed the other failed. I decided to create a HTML email message with nice colors, green for passed, red for failed tasks.

At first I decided to use Nguyen Van Thao's pattern. It uses CL_BCS class and SF. I used it by a bit by my own way. So let me introduce a clone with tables inside the smart form + some my experience notes.

Content generator Class

There is class responsible for the filling out needed tables which should be displayed inside the email. I just took a real example from my work.

*----------------------------------------------------------------------*
*       CLASS lcl_manager_email DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_manager_email DEFINITION.
  PUBLIC SECTION.
    METHODSconstructor
              IMPORTING
                io_data_sel  TYPE REF TO lcl_data_sel
                io_data_user TYPE REF TO lcl_data_user,
             send_email_log
              IMPORTING iv_subject TYPE so_obj_des
              RAISING lcx_msg_exception.

  PRIVATE SECTION.
    DATAo_data_sel  TYPE REF TO lcl_data_sel,
          o_data_user TYPE REF TO lcl_data_user.

    METHODSget_mail_body
                RETURNING value(rt_soliTYPE soli_tab
                RAISING lcx_msg_exception" get mail body from Smart form

ENDCLASS.                    "lcl_manager_email DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_manager_email IMPLEMENTATION
*----------------------------------------------------------------------*
* Any email stuff
*----------------------------------------------------------------------*
CLASS lcl_manager_email IMPLEMENTATION.

  METHOD constructor.
    o_data_sel  io_data_sel.
    o_data_user io_data_user.
  ENDMETHOD.                    "constructor

  METHOD send_email_log.
    " Send message only in case of real action
    IF o_data_sel->v_locka IS NOT INITIAL )    " do admin lock
        OR o_data_sel->v_lockl IS NOT INITIAL )  " do local lock
        OR o_data_sel->v_vali  IS NOT INITIAL )" set validation

      DATAlo_send_request TYPE REF TO cl_bcs,
            lo_document     TYPE REF TO cl_document_bcs,
            lo_recipient    TYPE REF TO if_recipient_bcs,
            lo_sender       TYPE REF TO cl_sapuser_bcs,
            lt_soli         TYPE soli_tab,
            lv_sent_flag    TYPE abap_bool,
            lx_oref         TYPE REF TO lcx_msg_exception,
            lx_bcf          TYPE REF TO cx_bcs,
            lv_msg          TYPE string.

      lt_soli me->get_mail_body).

      " Instantinate CL_BCS and specify options
      TRY .
          " Create persistent
          lo_send_request cl_bcs=>create_persistent).

          " Email FROM
          lo_sender cl_sapuser_bcs=>createsy-uname ).
          " Add sender to send request
          CALL METHOD lo_send_request->set_sender
            EXPORTING
              i_sender lo_sender.

          " Email TO
          lo_recipient cl_cam_address_bcs=>create_internet_addresso_data_sel->v_email ).
          " Add recipient to send request
          CALL METHOD lo_send_request->add_recipient
            EXPORTING
              i_recipient lo_recipient
              i_express   'X'.

          " Email BODY from SmartForm
          lo_document cl_document_bcs=>create_document(
              i_type        'HTM'
              i_subject     iv_subject
              i_text        lt_soli ).
          " Add document to send request
          CALL METHOD lo_send_request->set_documentlo_document ).

          " Send email
          lo_send_request->set_send_immediatelyi_send_immediately abap_true ).

          lv_sent_flag lo_send_request->sendi_with_error_screen 'X' ).
          IF lv_sent_flag EQ abap_false.
            RAISE EXCEPTION TYPE lcx_msg_exception
              EXPORTING iv_text =  'Error Sending Email!'.
          ENDIF.

          "Commit to send email
          COMMIT WORK.

        CATCH cx_bcs INTO lx_bcf.
          RAISE EXCEPTION lx_bcf.
      ENDTRY.
    ENDIF.
  ENDMETHOD.                    "send_email_log

  METHOD get_mail_body.

*---Data declaration
    DATAlt_lines TYPE TABLE OF tline,
          ls_line  TYPE tline,
          ls_soli  TYPE soli.
    DATAlv_fname      TYPE rs38l_fnam,
          ls_job_output TYPE ssfcrescl"Structure to return value at the end of form printing
    DATAls_ctrl_form  TYPE ssfctrlop"Smart Form Control Structure
          ls_output_opt TYPE ssfcompop"Smart Form Transfer Options

*---Pass data to Smartforms to receive itab of HTML Email

    "Get Smart Form Function Module Name
    CALL FUNCTION 'SSF_FUNCTION_MODULE_NAME'
      EXPORTING
        formname           cv_sf_htm_mail
      IMPORTING
        fm_name            lv_fname
      EXCEPTIONS
        no_form            1
        no_function_module 2
        OTHERS             3.
    IF sy-subrc <> 0.
      RAISE EXCEPTION TYPE lcx_msg_exception
        EXPORTING is_syst sy.
    ENDIF.

    "Spool parameters
    ls_output_opt-tdimmed 'X'.      "Print Immediately (Print Parameters)
    ls_output_opt-tddelete 'X'.     "Delete After Printing (Print Parameters)
    ls_output_opt-tdlifetime 'X'.   "Spool Retention Period (Print Parameters)
    ls_output_opt-tddest 'LOCL'.    "Spool: Output device
    ls_output_opt-tdprinter 'SWIN'"Spool: Device type name
    ls_ctrl_form-no_dialog 'X'.     "SAP Smart Forms: General Indicator
    ls_ctrl_form-preview 'X'.       "Print preview
    ls_ctrl_form-getotf 'X'.        "Return of OTF table. No printing, display, or faxing
    ls_ctrl_form-langu 'EN'.        "Language key
    ls_ctrl_form-device 'PRINTER'.  "Output device

    "Call Smart Form Function Module
    CALL FUNCTION lv_fname
      EXPORTING
        control_parameters ls_ctrl_form
        output_options     ls_output_opt
      IMPORTING
        job_output_info    ls_job_output
      TABLES
        it_users1          o_data_user->t_users1
        it_users2          o_data_user->t_users2
        it_users3          o_data_user->t_users3
        it_users4          o_data_user->t_users4
        it_result_statuses o_data_user->t_result_statuses
        it_result_errors   o_data_user->t_result_errors

      EXCEPTIONS
        formatting_error   1
        internal_error     2
        send_error         3
        user_canceled      4
        OTHERS             5.
    IF ls_job_output-otfdata IS INITIAL.
      RAISE EXCEPTION TYPE lcx_msg_exception
        EXPORTING is_syst sy.
    ENDIF.

    "Convert OTF to TLINE
    CALL FUNCTION 'CONVERT_OTF'
      EXPORTING
        format                'ASCII'
        max_linewidth         132
      TABLES
        otf                   ls_job_output-otfdata
        lines                 lt_lines
      EXCEPTIONS
        err_max_linewidth     1
        err_format            2
        err_conv_not_possible 3
        err_bad_otf           4
        OTHERS                5.
    IF sy-subrc <> 0.
      RAISE EXCEPTION TYPE lcx_msg_exception
        EXPORTING is_syst sy.
    ENDIF.

    "Remove empty lines
    DELETE lt_lines WHERE tdline EQ space.
    "Convert itab of HTML Email to itab of sending format in class CL_BCS
    LOOP AT lt_lines INTO ls_line.
      ls_soli ls_line-tdline.
      APPEND ls_soli TO rt_soli.
      CLEAR ls_soli.
    ENDLOOP.

  ENDMETHOD.                    "get_mail_body

ENDCLASS.                    "lcl_manager_email IMPLEMENTATION



Smart form

By above class we have some prepared data/tables which should be placed into email. Please acknowledge the data types transferred into SmartForm must be data dictionary based. Here I used also some our custom types. 



Tables

I had a bit bad experience with SmartForm's TABLE elements. The text inside the SOLI table was truncated and useless for HTML content. So I decided to use simple LOOP instead of table. Inside the loop you can achieve the same functionality. In connection with IF conditions inside the loop it gives you quite powerful tool for email generation.



In text element you can place your HTML code with inside CSS style. Inside text element you may work normally with variables as usual e.g. &GS_RESULT_STATUS-STATUS_LOCKED&.




Together it produces following tables within email. Now email dynamically shows the result of the last taken action according to the conditions within table loops inside the SmartForm.



As you see, it's some mix up of SmartForm's elements and HTML/CSS styles inside texts elements and that's all. So now is your turn...