Skip to Content
Technical Articles
Author's profile photo Vipin Saraika

Send password protected ZIP file (PDF file inside ZIP folder) from SAP via email

This blog describes the procedure to email a ZIP file (PDF file inside ZIP folder) with password protection, as an attachment. Normally, we have a scenario where we convert the OTF output of a Smartform, or a spool request to PDF.
Without using any third-party tool, we can password protect the ZIP file (pdf file inside the ZIP folder) and send it via email using SAP.
Business Scenario:
Generate a payslip using smartform, encrypt it with a password and send it to the employee via email.

Prerequisites

  • You are able to generate a smartform with OTF data

 

STEP 1

Convert OTF of a smartform to PDF file

DATA: i_otf         TYPE itcoo OCCURS 0 WITH HEADER LINE,
      i_tline       TYPE TABLE OF tline WITH HEADER LINE,
      v_len_in      LIKE sood-objlen.  

CALL FUNCTION 'CONVERT_OTF'
    EXPORTING
      format                = 'PDF'
      max_linewidth         = 132
    IMPORTING
      bin_filesize          = v_len_in
    TABLES
      otf                   = i_otf
      lines                 = i_tline
    EXCEPTIONS
      err_max_linewidth     = 1
      err_format            = 2
      err_conv_not_possible = 3
      OTHERS                = 4.

STEP 2

Move the PDF file to the Application server. In the below scenario we are moving the file to /tmp/ directory in AL11 Transaction, One in .PDF format and the other in .ZIP format.

 DATA: l_file       TYPE string,
        l_file_zip   TYPE string,
        itab_attach  TYPE xstring,
        t_attachment TYPE solix_tab.

  CLEAR:l_file,l_file_zip,itab_attach.
  REFRESH:t_attachment[].

  CONCATENATE '/tmp/' wa_final-pernr '''.PDF'  INTO l_file.
  CONCATENATE '/tmp/' wa_final-pernr '''.zip'  INTO l_file_zip.
  REPLACE ALL OCCURRENCES OF '''' IN l_file WITH space.
  REPLACE ALL OCCURRENCES OF '''' IN l_file_zip WITH space.

****code move PDF to server location***
  OPEN DATASET l_file FOR OUTPUT IN BINARY MODE  .
  IF  sy-subrc = 0 .
    LOOP AT i_tline.
      TRANSFER i_tline TO l_file .
    ENDLOOP.
    CLOSE DATASET l_file  .
  ELSE.
    WRITE : / 'operating system could not open file' .
  ENDIF.

***end server code***

STEP 3

Configure the external command using the transaction SM69. Refer to the below screenshot for information to be maintained as part of the configuration.

SM69-External%20Command

SM69-External Command

STEP 4

Use the below source code and get external commands from Transaction SM69, and encrypt the file with a password using SXPG_COMMAND_EXECUTE Function module.

  DATA: BEGIN OF command_list OCCURS 0.
          INCLUDE STRUCTURE sxpgcolist.
  DATA: END OF command_list .

  DATA: BEGIN OF exec_protocol OCCURS 0.
          INCLUDE STRUCTURE btcxpm.
  DATA: END OF exec_protocol.

  DATA: status      LIKE btcxp3-exitstat,
        commandname LIKE sxpgcolist-name VALUE 'ZDJ_ENCRYPTPDF',
        sel_no      LIKE sy-tabix.

* GET LIST OF EXTERNAL COMMANDS

  CALL FUNCTION 'SXPG_COMMAND_LIST_GET'
    EXPORTING
      commandname     = commandname
      operatingsystem = sy-opsys
    TABLES
      command_list    = command_list
    EXCEPTIONS
      OTHERS          = 1.

  CALL FUNCTION 'SXPG_COMMAND_CHECK'
    EXPORTING
      commandname                = command_list-name
      operatingsystem            = sy-opsys
    EXCEPTIONS
      no_permission              = 1
      command_not_found          = 2
      parameters_too_long        = 3
      security_risk              = 4
      wrong_check_call_interface = 5
      x_error                    = 6
      too_many_parameters        = 7
      parameter_expected         = 8
      illegal_command            = 9
      communication_failure      = 10
      system_failure             = 11
      OTHERS                     = 12.


  CLEAR command_list.
  REFRESH command_list.

  DATA: v_dir_input      TYPE sxpgcolist-parameters.
  DATA:l_orln     LIKE drao-orln,
       l_data_tab LIKE rcgrepfile OCCURS 10 WITH HEADER LINE,
       l_lines    TYPE i.

  CLEAR: v_dir_input,l_orln,l_lines.
  REFRESH:l_data_tab[].

  command_list-name = 'ZDJ_ENCRYPTPDF'.  " External command u have created
  command_list-opsystem = 'Linux'.


  CONSTANTS: c_extcom TYPE sxpgcolist-name VALUE 'ZDJ_ENCRYPTPDF',
             c_oper   TYPE syopsys VALUE 'Linux'.

*encrypting the file using some number- Civil ID here is social security ID, AAdhar ID country specific 
  IF wa_final-civil_id IS NOT INITIAL. 
    CONCATENATE '-P' wa_final-civil_id l_file_zip l_file INTO v_dir_input SEPARATED BY space.
  ENDIF.
*encrypting the file using passport number if no ID available
  IF wa_final-civil_id IS INITIAL.
    CONCATENATE '-P' wa_final-passport_no l_file_zip l_file INTO v_dir_input SEPARATED BY space.
  ENDIF.


  DATA: t_result         TYPE STANDARD TABLE OF btcxpm.
  REFRESH:t_result[].

  CALL FUNCTION 'SXPG_COMMAND_EXECUTE'
    EXPORTING
      commandname                   = c_extcom
      additional_parameters         = v_dir_input
      operatingsystem               = c_oper
    TABLES
      exec_protocol                 = t_result
    EXCEPTIONS
      no_permission                 = 1
      command_not_found             = 2
      parameters_too_long           = 3
      security_risk                 = 4
      wrong_check_call_interface    = 5
      program_start_error           = 6
      program_termination_error     = 7
      x_error                       = 8
      parameter_expected            = 9
      too_many_parameters           = 10
      illegal_command               = 11
      wrong_asynchronous_parameters = 12
      cant_enq_tbtco_entry          = 13
      jobcount_generation_error     = 14
      OTHERS                        = 15.

STEP 5

Now we need to send the above-encrypted PDF file to an email ID

Convert the file to BINARY data using the below function module:

sy-cprog = 'RC1TCG3Y'.
  CALL FUNCTION 'C13Z_RAWDATA_READ'
    EXPORTING
      i_file           = i_file_appl
    IMPORTING
      e_file_size      = l_orln
      e_lines          = l_lines
    TABLES
      e_rcgrepfile_tab = l_data_tab
    EXCEPTIONS
      no_permission    = 1
      open_failed      = 2
      read_error       = 3
* Begin Correction 24.09.2010 1505368 ********************
      path_error       = 4
      OTHERS           = 5.
  sy-cprog = sy-repid.

STEP 6

Convert the above BINARY data to XSTRING using the below function module:

  DATA:
    ld_buffer	TYPE xstring,
    lv_orln   TYPE i.

  CLEAR:ld_buffer,lv_orln.

  lv_orln = l_orln.


  CALL FUNCTION 'SCMS_BINARY_TO_XSTRING'
    EXPORTING
      input_length = lv_orln
*     first_line   = ld_first_line
*     last_line    = ld_last_line
    IMPORTING
      buffer       = ld_buffer
    TABLES
      binary_tab   = l_data_tab
    EXCEPTIONS
      failed       = 1
    .  "  SCMS_BINARY_TO_XSTRING

STEP 7

Now to attach the PDF file in an email when sending we need to convert the above LD_BUFFER data to HEX format using the below Call method XSTRING_TO_SOLIX:

  DATA content_hex TYPE solix_tab.

  REFRESH:content_hex[].


  CALL METHOD cl_bcs_convert=>xstring_to_solix
    EXPORTING
      iv_xstring = ld_buffer
    RECEIVING
      et_solix   = content_hex.

STEP 8

Below Logic is for Email to be sent with a PDF attachment from SAP to an employee

  DATA:  lo_send_request TYPE REF TO cl_bcs
        ,lo_document     TYPE REF TO cl_document_bcs
        ,lo_sender       TYPE REF TO if_sender_bcs
        ,lo_recipient    TYPE REF TO if_recipient_bcs      ,
        lt_message_body TYPE bcsy_text
        ,lx_document_bcs TYPE REF TO cx_document_bcs
        ,lv_send         TYPE ad_smtpadr VALUE 'xyz@gmail.com'
        ,lv_sent_to_all  TYPE os_boolean     .

  DATA recipient      TYPE REF TO if_recipient_bcs.
  "create send request
  lo_send_request = cl_bcs=>create_persistent( ).

  DATA gv_message TYPE string.
  DATA gv_subject TYPE so_obj_des.
  DATA gv_subject1 TYPE so_obj_des.
  CLEAR:gv_message,gv_subject,gv_subject1.

  "create message body and subject
  CONCATENATE 'Dear' wa_final-ename INTO gv_message SEPARATED BY space.
  CONCATENATE gv_message ',' INTO gv_message..
  APPEND gv_message   TO lt_message_body.
  CLEAR:gv_message.
  APPEND INITIAL LINE TO lt_message_body.

  CONCATENATE 'Please find your payslip for the month of'  gv_month gv_year 'attached with the mail.' INTO gv_message SEPARATED BY space.
  APPEND gv_message   TO lt_message_body.
  CLEAR:gv_message.
  APPEND INITIAL LINE TO lt_message_body.

  IF wa_final-civil_id IS NOT INITIAL.
    APPEND 'For added security concerns, your payslip is protected by a unique password, which is your Civil ID number.' TO lt_message_body.
  ENDIF.

  IF wa_final-civil_id IS INITIAL.
    APPEND 'For added security concerns, your payslip is protected by a unique password, which is your Passport number.' TO lt_message_body.
  ENDIF.

  APPEND INITIAL LINE TO lt_message_body.

  APPEND 'Regards,' TO lt_message_body.
  APPEND 'HR Department' TO lt_message_body.

  CONCATENATE 'Your Payslip for' gv_month gv_year INTO gv_subject SEPARATED BY space.

  "put your text into the document
  lo_document = cl_document_bcs=>create_document(
  i_type = 'RAW'
  i_text = lt_message_body
  i_subject = gv_subject ).


  CONCATENATE 'YourPayslip_' gv_month gv_year INTO gv_subject1.
  CONDENSE gv_subject1.

  TRY.
      lo_document->add_attachment(
      EXPORTING
        i_attachment_type = 'ZIP'
        i_attachment_subject = gv_subject
        i_att_content_hex = content_hex ).

    CATCH cx_document_bcs INTO lx_document_bcs.
  ENDTRY.

* Add attachment
* Pass the document to send request
  lo_send_request->set_document( lo_document ).

  lo_sender = cl_cam_address_bcs=>create_internet_address( 'sap.support@domain.com' ).

  lo_send_request->set_sender( lo_sender ).




*--------- add recipient (e-mail address) -----------------------
*     create recipient object
  DATA:lv_email TYPE pa0105-usrid_long.
  CLEAR:lv_email.
  SELECT SINGLE usrid_long FROM pa0105 INTO lv_email WHERE pernr = wa_final-pernr  AND  subty ='0010' AND endda = '99991231'.

  IF lv_email IS NOT INITIAL.
    recipient = cl_cam_address_bcs=>create_internet_address( lv_email ).

    lo_send_request->add_recipient( recipient ).
    DATA sent_to_all    TYPE os_boolean.

    sent_to_all = lo_send_request->send( i_with_error_screen = 'X' ).

    COMMIT WORK.
  ENDIF.

  DELETE DATASET l_file.
  DELETE DATASET l_file_zip.

CONCLUSION

Now you can generate a ZIP FILE (PDF file inside the ZIP folder)  of a smartform, encrypt the file with a password of your choice using external commands, and can send it as an attachment to an employee via email.

Thanks for reading this blog post.

Please correct me if mistaken at some point, also suggest improvement points.

I hope this blog post will be helpful. If you have questions/suggestions/issues about this, please feel free to leave them in the comments section.

I would like to see your comments and would like to answer questions which you can post at Q&A tag area: https://answers.sap.com/tags/66233466-fcd6-45d2-a9ae-2cba38c72e19

Assigned Tags

      6 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Shai Sinai
      Shai Sinai

      Thanks for sharing.

      Just a small semantic correction: You are basically creating a password-protected ZIP file and not a password-protected PDF.

      Author's profile photo Vipin Saraika
      Vipin Saraika
      Blog Post Author

      Thank you for your comment, I have updated the blog post accordingly

      Author's profile photo Jelena Perfiljeva
      Jelena Perfiljeva

      There is an old blog post on the same subject: https://blogs.sap.com/2012/07/06/email-pdf-attachment-with-password-protection/

      But, in general, approach is the same: using external command. It's probably worth mentioning that it requires additional software (i.e. a program that will be executed by the external command) and comes with some security risks.

      Not to throw shade on this post but I'm wondering if such requirements even make sense to pursue using ABAP these days. There are better and more secure alternatives to emailing password-protected files, when it comes to secure data exchange. Just a thought.

      Author's profile photo Raka Bag
      Raka Bag

      Hi Vipin,

      Thank you for the post. If I need to send a txt file inside the zip and do the same. I have created the external command in SM69 but somehow it is not working. Not sure if I am missing anything. and also not clear about the FM C13Z_RAWDATA_READ. Do I need to add any external command or anything addition to SM69 configuration  ? And also what are you sending in i_file_appl ?

      Author's profile photo Filipe Santos
      Filipe Santos

      Hi Raka,

      I´m facing the same problem as you. I do not know what Vipin sent to i_file_appl.

      Did you manage to solve this problem?

      Best regards.

      Author's profile photo Sandra Rossi
      Sandra Rossi

      I had to go in depth in your ABAP code to understand the approach you have used. So, if anyone wonders, the approach was:

      1. Using a command at Linux level, which is zip -P "password" "zip_file.zip" "file_to_be_zipped" (unix - how to create a file in shell script with specific password - Stack Overflow)
      2. Using SM69, SXPG_COMMAND_EXECUTE, to run the OS command from an ABAP program