Skip to Content
Technical Articles

Sending Email from FINT



FINT is a handy transaction for calculating of interest on customer items ( for vendor items FINTAP should be used). It is the successor of the old transactions F.2A/ F.2B/ F.2C and F.24 which were using program RFDUZI00 for calculation.

FINT works, like most of periodically scheduled programs in SAP, using a 2-step approach: first a proposal is created and then the production run can be executed. It is also possible to directly start a production run without seeing the proposal run but this approach is rather not used.

Whereas the transactions based on RFDUZI00 program supported Sap Script only, FINT supports Smartforms and Adobe PDF and has a BADI where all actions performed by the calculation program can be influenced.

There are already well-documented examples how to steer with email sending of different correspondence in different SAP forums on the Internet and OSS notes:

  • Payment Advice: OSS 1033893
  • Dunning: 1042992
  • Balance Confirmation: 1377820
  • Other correspondence: 1360070

In terms of FINT SAP only delivered note 956981, which by standard supports only email sending for forms created using Adobe PDF but not Smartforms

This gap in documentation made me write the blog to show you how you can archive the interest email sending and what to consider during the programming.


FINT Enhancement Possibilities

FINT, in opposite to classic transactions based on RFDUZI00, has a BADI where many of the interest parameters, including the whole output and calculation, can be adjusted to customer needs. The BADI name is FI_INT_CUS01 – in fact in the coding 2 BADIs can be found, the other one is FI_INT_SAP01, which rather should be used by SAP only. It only seems to be a mistake that SAP didn’t mark it as ‘To-be-used by SAP only’.

Anyway the processing of each method available in these BADIs is always called in sequence – first FI_INT_SAP01 and immediately below it FI_INT_CUS01.

Besides that the selection screen as well as ALV output and Functions can be enhanced via program RFINTITUSEREXT.

FINT Email sending: Logic

The code presented in further sections of this blog is based on assumption that interest notes are to be send out to a customer who has a main E-mail address provided. If the email is marked as ‘standard’ then such is set as email recipient, otherwise it is set as secondary recipient (carbon copy).

FINT Email Sending: Enhance Screen

At first, to make email sending controllable, the selection screen will be enhanced by a new field using the screen enhancement program.

Program RFINTITUSEREXT provides function to:

  • Add / delete fields in calculation and display structure
  • Add / delete custom parameters
  • Add / delete custom select-options

The parameters and select-options have a predefined naming convention – they must begin with ‘A_’.  Using data elements created in a customer namespace, like /SAP/ should not be be used for any kind of abovementioned screen enhancement – it happened to me several times that system adds it (at least it says so) but it cannot be named and stays only as an untranslated parameter. Therefore it is advisable to use only Z/Y for data elements used as base of new fields (besides of course the standard standard ones that can also be used).

A newly created data element can be added using following option:

By adding a new parameter system will modify the include RFINTITARUSEREXT and FI_INT_USEREXT so you will be prompted to provide an object key for modification.

Note that the description of the data element is not taken automatically over in the selection screen, so you need to adjust it in SE38 of program RFINTITAR by choosing Text Elements -> Selection Text.

FINT Email Sending: Methods used

This implementation is called only when productive run of interest calculation is done.

In implementation of BADI FI_INT_CUS01 email can be archived by using 2 methods:

  1. INT_PRINT_OPTIONS – determination of email recipients and conversion to OTF
  2. INT_PRINT_SPOOL_CLOSED – actual sending of emails

In this example the content and subject of email are hardcoded – this is only for presentation purpose – in your system do not follow this approach!

FINT Email Sending: Class Attributes


Method INT_PRINT_OPTIONS contains all data about the interest calculated, business partners and output options. It is called when sample or final printout is selected in FINT.

In this method parameters for email recipients etc. already exists but filling them does not have any effect when using Smartforms-based output. This means that the recipients need to be saved in  a class attribute. We will use attribute ‘mt_email_recipients’ for that.

In addition the processing sequence of each output is only available in this method so it is advisable to save it in an attribute as well. In this example it will be saved in attribute ‘mt_ipf_proc_seq’.

To determine proper language of email text the output language will be stored in attribute ‘mt_output_language’. It won’t actually be used in the class for determining the language of email and is included here only for demonstration purposes.

Additionally, as newly-added selection parameter ‘A_EMAIL’ is not available in INT_PRINT_SPOOL_CLOSED it will be saved as ‘mv_email’ attribute.

In the method INT_PRINT_SPOOL_CLOSED no information about customer etc. is available. It is only called for each global output table GT_IPF_DISP of the report (stored in function group SAPLFI_INT) transferring the output content itself.

At the end following attributes and types are defined in the implementation class:

public section.

  interfaces IF_EX_FI_INT_CUS01 .

  constants GC_ACCOUNT_TYPE_CUSTOMER type KOART value 'D' ##NO_TEXT.

private section.

    " Key used to identity an interest package
    BEGIN OF tp_fint_key,
      bukrs TYPE bukrs,
      koart TYPE koart,
      konko TYPE konko,
    END OF tp_fint_key .
  "Language of printout info
    BEGIN OF tp_language_info.
          INCLUDE TYPE tp_fint_key.
    spras TYPE spras,
    name1 TYPE name1,
    END OF tp_language_info .
    tt_language_info TYPE STANDARD TABLE OF tp_language_info WITH NON-UNIQUE KEY bukrs koart konko .
  "Email recipient list
    BEGIN OF tp_email_recipients.
          INCLUDE TYPE tp_fint_key.
    receiver   TYPE ad_smtpadr,
    copy       TYPE so_snd_cp,
    blind_copy TYPE so_snd_bc,
    END OF tp_email_recipients .
    tt_email_recipients TYPE STANDARD TABLE OF tp_email_recipients WITH NON-UNIQUE KEY bukrs koart konko .
  "Processing sequence of output
    tt_ipf_sequence TYPE STANDARD TABLE OF intipf WITH DEFAULT KEY .

  "Contants for checks/ output info
  constants C_FINTSHOW type SY-TCODE value 'FINTSHOW' ##NO_TEXT.
  constants C_ATTACHMENT_TYPE_PDF type SO_OBJ_TP value 'PDF' ##NO_TEXT.
  "Data for email processing
  constants C_EMAIL type FIELDNAME value 'A_EMAIL' ##NO_TEXT.



This method is called in function module SF_PRINT_INTIT_NOTICE just before the SMARTFORM is called. The call happens in loop over T_IPF table storing each output line to be processed. T_IPF in the loop represents the same content as global table GT_IPF  of RFINTITAR.

Table GT_IPF contains all customers for which interest is to be created. Entries stored in the table show in which order the output is processed. Method INT_PRINT_OPTIONS is triggered for every single entry of GT_IPF.

As soon as the spool is closed these entries are not available any more in the method INT_PRINT_SPOOL_CLOSED that is why we’re storing it in class attribute to use it later on and send email.

  METHOD if_ex_fi_int_cus01~int_print_options.
    DATA ls_cus_addrres TYPE szadr_addr1_complete.
    "Email in FINT

        mv_email = it_frange[ fieldname = c_email ]-selopt_t[ 1 ]-low.

      CATCH cx_sy_itab_line_not_found.

    "no email sending from preview and print preview
    IF sy-tcode = c_fintshow OR control_parameters-preview IS NOT INITIAL OR mv_email IS INITIAL.

    mt_ipf_proc_seq = VALUE #( BASE mt_ipf_proc_seq ( is_ipf ) ).

    "read main email address of customer - can be changed to other type of read

    "read email address from Customer master data
        addrnumber              = is_kna1-adrnr
        addr1_complete          = ls_cus_addrres
        parameter_error         = 1
        address_not_exist       = 2
        internal_error          = 3
        wrong_access_to_archive = 4
        address_blocked         = 5
        OTHERS                  = 6.

    IF sy-subrc NE 0.

    LOOP AT ls_cus_addrres-adsmtp_tab ASSIGNING FIELD-SYMBOL(<fs_adsmtp>) WHERE adsmtp-flg_nouse IS INITIAL AND adsmtp-smtp_addr IS NOT INITIAL.

      IF <fs_adsmtp>-adsmtp-flgdefault EQ abap_true.

        "add recipients
        mt_email_recipients = VALUE #( BASE mt_email_recipients ( bukrs = is_ipf-bukrs
                                                                  koart = is_ipf-koart
                                                                  konko = is_ipf-account
                                                                  receiver = <fs_adsmtp>-adsmtp-smtp_addr
                                                                   ) ).

        mt_email_recipients = VALUE #( BASE mt_email_recipients ( bukrs = is_ipf-bukrs
                                                                  koart = is_ipf-koart
                                                                  konko = is_ipf-account
                                                                  receiver = <fs_adsmtp>-adsmtp-smtp_addr
                                                                  copy = abap_true
                                                                   ) ).


    IF line_exists( mt_email_recipients[ bukrs = is_ipf-bukrs
                                         koart = is_ipf-koart
                                         konko = is_ipf-account ] ).

      "prepare OTF data for PDF sending
      control_parameters-getotf = abap_true.
      output_options-tdnewid    = abap_true.

      IF line_exists( mt_output_language[ bukrs = is_ipf-bukrs
                                          koart = is_ipf-koart
                                          konko = is_ipf-account ] ).
        "prepare list of output languages
        mt_output_language = VALUE #( BASE mt_output_language ( bukrs = is_ipf-bukrs
                                                                koart = is_ipf-koart
                                                                konko = is_ipf-account
                                                                spras = control_parameters-langu
                                                                name1 = is_kna1-name1 ) ).





At the point of time when this method is called the spool is already closed, interest tables are updated with proper statuses and now the email creation can happen undisturbed.

The logic is processed when the ‘preview’ option was not set and the status is not in process as well as the interest document number was assigned.

This option contains also a check if the data is delivered in OTF form.

As not further actions are executed after his method email sending is done using CL_BCS class.

METHOD if_ex_fi_int_cus01~int_print_spool_closed.
* Local Variables  *
    DATA: lv_dirty_assign_preview TYPE string VALUE '(SAPLFI_INT)GB_PREVIEW'. "holding print preview indicator
    DATA: lv_doc_size     TYPE so_obj_len. " PDF document size
    DATA: lv_pdf_xstring TYPE xstring. "PDF conversion into xstring
    DATA: ls_email_subject TYPE itcpo-tdtitle. "email subject
* Local Structures *
    DATA: ls_ipf_global TYPE intipf.
*   Local Tables   *
    DATA: lt_pdf_lines    TYPE tline_tab. "converted lines to PDF
    DATA: lt_otf_lines    TYPE efg_tab_itcoo. "OTF lines delivered by smartforms
    DATA: lt_objbin   TYPE STANDARD TABLE OF solix. "PDF in HEX format

    "1.0 get global variables
    READ TABLE mt_ipf_proc_seq INTO ls_ipf_global INDEX 1. "processing one by one
    DELETE mt_ipf_proc_seq INDEX 1.
    ASSIGN (lv_dirty_assign_preview) TO FIELD-SYMBOL(<fs_preview>).
    IF sy-subrc NE 0.

    "1.1 first check
    IF ( ls_ipf_global-int_status = gc_interest_status_process AND ls_ipf_global-form_to IS INITIAL ) " form number not generated yet
    OR ( ls_ipf_global-int_belnr IS INITIAL AND ls_ipf_global-int_gjahr IS INITIAL AND ls_ipf_global-form_to IS INITIAL ) "document not posted yet
    OR ( <fs_preview> EQ abap_true )
    OR ( mv_email IS INITIAL ). "print preview only

    "1.2 - conditions for Email: no printout was generated
    IF job_output_info-otfdata IS NOT INITIAL.

      lt_otf_lines = job_output_info-otfdata.

      "2.0 Convert OTF data into PDF

          format                = c_attachment_type_pdf
          max_linewidth         = 132
          bin_filesize          = lv_doc_size
          bin_file              = lv_pdf_xstring   " This is NOT Binary. This is Hexa
          otf                   = lt_otf_lines
          lines                 = lt_pdf_lines
          err_max_linewidth     = 1
          err_format            = 2
          err_conv_not_possible = 3
          OTHERS                = 4.
      IF sy-subrc <> 0.
      REFRESH lt_otf_lines.

      "2.1 prepare HEX for PDF as attachment
          buffer     = lv_pdf_xstring
          binary_tab = lt_objbin[].

      READ TABLE mt_output_language WITH TABLE KEY bukrs = ls_ipf_global-bukrs
                                              koart = ls_ipf_global-koart
                                              konko = ls_ipf_global-account
                                              ASSIGNING FIELD-SYMBOL(<fs_customer>).
      IF sy-subrc EQ 0.

        "2.3 Get email subject
        "additional actions on subject - add Customer number + name

        ls_email_subject = |{ 'Interest Email' } { ls_ipf_global-account ALPHA = OUT } { <fs_customer>-name1 }|.

        ls_email_subject = |{ 'Interest Email' } { ls_ipf_global-account ALPHA = OUT }|.

      "2.4 Get email content
      DATA(lt_email_content) = VALUE soli_tab( ( |{ 'email text ' }| ) ).


          "3.0 Initiate object for email sending
          DATA(lo_send_email) = cl_bcs=>create_persistent( ).

          "3.1 Initialite attached document
          DATA(lo_email_attachment) = cl_document_bcs=>create_document( i_type    = 'RAW'
                                                                        i_text = lt_email_content
                                                                        i_subject = ls_email_subject ). "#EC NOTEXT

          "3.2 add the PDF as attachment to document object
          lo_email_attachment->add_attachment( i_attachment_type    = c_attachment_type_pdf
                                               i_attachment_subject = CONV so_obj_des( ls_email_subject )
                                               i_att_content_hex = lt_objbin

          "3.3 add document object to email
          lo_send_email->set_document( lo_email_attachment ).

          "3.4 add recipient
          LOOP AT mt_email_recipients ASSIGNING FIELD-SYMBOL(<fs_email_recipient>) WHERE koart = ls_ipf_global-koart
                                                                                     AND konko = ls_ipf_global-account.

            DATA(lo_email_recipient) = cl_cam_address_bcs=>create_internet_address( <fs_email_recipient>-receiver ).

            CASE abap_true.
              WHEN <fs_email_recipient>-copy.

                lo_send_email->add_recipient( i_recipient = lo_email_recipient
                                              i_copy = abap_true ).

              WHEN <fs_email_recipient>-blind_copy.

                lo_send_email->add_recipient( i_recipient = lo_email_recipient
                                              i_blind_copy = abap_true ).

              WHEN OTHERS.
                lo_send_email->add_recipient( lo_email_recipient ).


          "3.5 Set status
          lo_send_email->set_status_attributes( i_requested_status = CONV bcs_rqst('N')  ).

          "3.6 send email
          DATA(ls_result) = lo_send_email->send( ).

          COMMIT WORK.

          "check the result of sending
          IF ls_result IS INITIAL.
            MESSAGE i500(sbcoms) WITH <fs_email_recipient>-receiver.
            ROLLBACK WORK.
            MESSAGE s022(so).

        CATCH cx_bcs INTO DATA(lo_email_exception).
          MESSAGE i500(sbcoms) WITH <fs_email_recipient>-receiver.
      ENDTRY. " on email sending
    ENDIF. "on provided OTF data


This method ends the required implementation.


Example of use

To show how the solution works 3 customers were defined of which 2 only have email addresses updated.

Several invoices were posted and paid with some days in arrears:

Executing FINT shows the new field is available:

Executing FINT with ‚test run’ marked provides a list of selected and calculated interest. If this is not selected then the update of master data and printout will be triggered automatically.

For test purposes I run the report with test run enabled to see the proposal first.

Final processing is done with button


Items were processed successfully:

At the end 2 emails should be send out to customers – they can be visible in SOST:

With PDF attached to email:

Direct processing (without test run) is also supported:

At the end the result is the same – emails are generated and visible in SOST:


Thank you for reading – in next blog I will show how to enhance FINT output by custom fields like customer name.


You must be Logged on to comment or reply to a post.

    Hi Marek

    Thanks! I assume the three invoices in your example must trigger three different spools? How do you achieve that? If I set "new spool request" and "do not append print jobs" in the print pop-up I still get only one spool for all invoices. I guess that would then not work for your email solution?


    • Hi Magnus,


      actually the opening on new spool job is controlled in my solution in this part:

          "prepare OTF data for PDF sending
            control_parameters-getotf = abap_true.
            output_options-tdnewid    = abap_true.


      The parameter TDNEWID controls that a new spool job is opened each time for each customer. This is a prerequisite for sending the emails separately per customer in my solution. By this each output is handled separately and we can clearly steer email sending.

      The settings of "new spool request" and "do not append print jobs" actually mean a double negative and in result give = "append print jobs".

      This results in what you see - getting only one spool job - by this my solution will not really work because it sends the printouts at the end of spool job after database is updated with interest data (for consistency reasons). If you do not wish to keep this consistency but also use these 2 options together then you might go for using method INT_PRINT_RESULTS to send emails.

      This method is called after each loop over T_IPF table (function module SF_PRINT_INTIT_NOTICE) which contains all customers for which interests are to be printed. There you have also direct access to importing parameter JOB_OUTPUT_INFO from which you can read the OTF data and send the email and still get only one spool output.



  • Thank you Marek - I have implemented everyhting and it works really fine!

    Do you know how it is possible to send it via email and archived it at the same time? Archiving works only if the customer has no email adress and the form is printed. Any help is appreciated!




    • Hi Christine,


      I am glad to hear that it worked out flawlessly.

      Regarding the archiving issue - have you installed OSS Note 1552407 - FINT: No archiving when sending PDFs via mail or fax already?

      Have you passed the archivin parameters in BADI method INT_PRINT_OPTIONS?



  • Hi Marek,


    I have implemented as mentioned. Am facing one problem.

    When I run for multiple customer's, email is being sent only to the first customer with the one pdf having forms of multiple customer's.

    Can you please advise if there is any other setting that can impact this.


    • Hi Mohammed,


      please make sure you have put this part of code (method INT_PRINT_OPTIONS):

          "prepare OTF data for PDF sending
            control_parameters-getotf = abap_true.
            output_options-tdnewid    = abap_true.

      Additionally please check if in your spool parameters you do not have following options set:

      “new spool request”
      “do not append print jobs”

      If you have set both of them then system actually does append print jobs which is undesirable in this case.



  • Thanks for the quick response.

    I have already set the two parameters as below

    control_parametersgetotf abap_true.
    output_optionstdnewid    abap_true.

    And both the “new spool request” & “do not append print jobs” is set as No.

    Still I face the same issue.


    I also see that method “IF_EX_FI_INT_CUS01~INT_PRINT_SPOOL_CLOSED” is being called only once even if I run for multiple customer’s.

    in this case, the below picks the first customer and exits.

    READ TABLE mt_ipf_proc_seq INTO ls_ipf_global INDEX 1“processing one by one


    OTF data received is for multiple customer’s, therefore I think one mail is being sent with multiple interest invoice forms.



    Mohammed Zuber

    • Hi Mohammed,


      method “IF_EX_FI_INT_CUS01~INT_PRINT_SPOOL_CLOSED” should be called for each and every spool created - so for each and every customer processed.

      It seems that in your case only one spool is generated instead of many - did you include multiple customers in your selection or only one?

      Can you check if you do not have other fields populated in output_options which might influence the file creation?



  • Hi Marek,

    Yes, Am running for 2 customers.

    IF_EX_FI_INT_CUS01~INT_PRINT_SPOOL_CLOSED is called at the time of spool closing and therefore is triggered only once..

    Am not passing any other fields apart from the one's you mentioned.



    • Hi,

      it should be called for every spool created - in the solution from blog it is called every time spool is closed. In my example it is called 3 times therefore I can generate 3 separate emails.

      The call is trigerred from FM SF_PRINT_INTIT_NOTICE in this part of coding:

       If Gs_old_input <> Ls_input.                           "1310020
                  If not Gs_old_input is initial.                     "1310020
                     Perform Close_spool tables T_ipf T_ipf_processed "1136766
                     using A_pdf Id_badisap Id_badi.                  "1307368
                  Endif.                                              "1136766

      It is closing Smartforms spool job and opening new one for new parameters (new customer).

      Please check in debugger if this is triggered in your case in the same way.



  • Hi Marek,


    we have implemented your code and are facing the problem, that it is only working if all customers are printed or all customers get an email.

    In real life we have first customer should be printed, second should get an email and so on. Somehow the spoolfiles get mixed up and customer 2 gets letter from customer 1.

    Do you have any idea how we can solve this?


    Thank you!




    • Hi Christine,


      my coding was based on example that each time customer has email maintained then FINT should send an email.


      If your case I assume that there is some indicator if interest note should be printed or sent by email. In such case add an condifion before that part (in method INT_PRINT_OPTIONS):

        LOOP AT ls_cus_addrres-adsmtp_tab ASSIGNING FIELD-SYMBOL(<fs_adsmtp>) WHERE adsmtp-flg_nouse IS INITIAL AND adsmtp-smtp_addr IS NOT INITIAL.

      In the condition enter the expected value that should be fulfilled to mark the line as relevant for email. For such customer the table mt_email_recipients should be empty as no email should be determined. In such case also the conding:

            "prepare OTF data for PDF sending
            control_parameters-getotf = abap_true.
            output_options-tdnewid    = abap_true.

      should not be executed for such line.

      Important is only that the customer line is added in the processed customer line:

       mt_ipf_proc_seq = VALUE #( BASE mt_ipf_proc_seq ( is_ipf ) ).


      Then in method INT_PRINT_SPOOL_CLOSED that part of coding:

      "1.2 - conditions for Email: no printout was generated
          IF job_output_info-otfdata IS NOT INITIAL.
            lt_otf_lines = job_output_info-otfdata.


      should prevent the creation of email for such customer. It checks if the OTF data was created and it is only created if control_parameters-getotf is marked as abap_true in method INT_PRINT_OPTIONS.

      Please have a look if it helps and if not then provide the condition which you use as differentiation for generating emails or printout and I can help more with exact coding.



  • Hi Marek,

    thanks for sharing!

    One question: I also added a new parameter for the report. It appears on the selection screen, but I have no possibility to add a text.

    On your screen the selection text is changeble. Did you get an object key for RFINTITAR as well?

    Thanks in advance for your help.


    • Hi Nadine,

      yes, unfortunately I needed to also get the object key for  RFINTITAR  report as well. Without this the text of new field was not visible.


      Marek Turczyński