Wednesday, September 9, 2009

Generic E-Mail Program

The company I am working for converted to SAP a little over a year and a half ago and we e-mail/fax reports and documents to our clients.
But what we found was we were imbeding the same code into multiple programs.  Then we were getting phone calls stateing we did not get the e-mail or the fax. The final problem we were having was on the development box and QAS box whenever some one would test a program we would have to be carefull that we did not send the report out.
So we started a project with the following criteria:
  1. Create a simple interface for e-mailing/faxing reports.
  2. Allow for resending reports.
  3. Allow for changing who the report is to be sent to.
  4. Allow for viewing reports.
  5. Prevent test reports from being sent to customers.
  6. Create an archive ability.
First let me show you how the interface program works.
Selection Screen
This is the main screen

Clicking on History pulls up the following screen.
Currently the history screen really only makes sense for Faxes it will allways display emails as being verified.
Clicking on Details will display the following screen.
I hope this gives you an idea of how the program works.
Inorder to do this I created several custom tables.
Main Driver Table ZEMAIL_001
Receipents Table is ZEMAIL_002
Message Table ZEMAIL_003A
FTP Location ZEMAIL_004(Will discuss later why we need this)
Override Email Address for Test Systems ZEMAIL_005
If you have more then one attachment you will populate ZEMAIL_006
For the history screen I created one additional table ZEMAIL_008
Those are the tables I am using to hold the data for this process.
Now then I created a function module for adding records to these tables.
Function Module is called ZADD_EMAIL I simply pass to the function module four tables.
Source Code for Function Module.
function zadd_email.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  TABLES
*"      Z002A STRUCTURE  ZEMAIL_002
*"      Z003A STRUCTURE  ZEMAIL_003A
*"      Z006A STRUCTURE  ZEMAIL_006 OPTIONAL
*"      Z001A STRUCTURE  ZEMAIL_001
*"----------------------------------------------------------------------
  tables: zemail_001,
          zemail_002,
          zemail_003a,
          zemail_006.

  loop at z002a.
    move-corresponding z002a to zemail_002.
    zemail_002-source_program = z001a-source_program.
    zemail_002-email_date     = z001a-email_date.
    zemail_002-email_time     = z001a-email_time.
    insert zemail_002.
  endloop.

  loop at z003a.
    move-corresponding z003a to zemail_003a.
    zemail_003a-source_program = z001a-source_program.
    zemail_003a-email_date     = z001a-email_date.
    zemail_003a-email_time     = z001a-email_time.
    insert zemail_003a.
  endloop.

  loop at z006a.
    move-corresponding z006a to zemail_006.
    zemail_006-source_program = z001a-source_program.
    zemail_006-email_date     = z001a-email_date.
    zemail_006-email_time     = z001a-email_time.
    insert zemail_006.
  endloop.

  zemail_001-source_program   = z001a-source_program.
  zemail_001-email_date       = z001a-email_date.
  zemail_001-email_time       = z001a-email_time.
  zemail_001-kunnr            = z001a-kunnr.
  zemail_001-subject          = z001a-subject.
  zemail_001-attachment       = z001a-attachment.
  zemail_001-name_attach      = z001a-name_attach.
  zemail_001-type_attachment  = z001a-type_attachment.
  zemail_001-retain_until     = z001a-retain_until.
  zemail_001-status           = 'U'.
  insert zemail_001.
endfunction.
Now in your programs you will simply populate the internal tables and send to application server your pdf, text or whatever file you want and call this function module. (Of course you can simply populate the actual tables in your report program but I wanted to learn how to create a function module.

Now then the heart of this whole system the program that creates the email/fax itself.
I call it ZGENERIC_EMAIL
The following is a simple flow chart displaying how the program is working.  Sorry for the size of the flow chart still new to blogging.
Data Section
report  zgeneric_email.

tables: zemail_001,
        zemail_008.
types:
  begin of type_test,
    address_type type zemail_005-address_type,
    address      type zemail_005-address,
  end of type_test.

data: global_header     type table of zemail_001  with header line,
      global_address    type table of zemail_002  with header line,
      global_test_add   type table of type_test   with header line,
      global_message    type table of zemail_003a with header line,
      global_attachment type table of zemail_006  with header line,
      global_mult(1)    type c,
      it_message        type standard table of solisti1 initial size 0
                with header line,
      t_packing_list    like sopcklsti1 occurs 0 with header line,
      t_receivers       like somlreci1 occurs 0 with header line,
      t_receivers_bk    like somlreci1 occurs 0 with header line,
      t_attachment      like solisti1 occurs 0 with header line,
      ld_sender_address like soextreci1-receiver,
      ld_sender_address_type like  soextreci1-adr_typ,
      ld_format         type so_obj_tp,
      ld_attdescription type so_obj_nam,
      w_sent_all(1)     type c,
      global_cnt        type i,
      global_fax(1)     type c,
      global_error(1)   type c,
      local_time_dif    type sy-uzeit,
      global_doc_data   like sodocchgi1,
      ls_fax            type sadrfd,
      bindata           type table of solisti1 with header line,
      bindataotf        type table of solisti1 with header line,
      objhead           like solisti1   occurs 1  with header line.
The HTML gets confused with < receiver > just remove the space between "< and receiver and >".
field-symbols < receiver > type c.
select-options: s_source  for global_header-source_program no intervals no-extension,
                s_date    for global_header-email_date no intervals no-extension,
                s_time    for global_header-email_time no intervals no-extension,
                s_only    for global_address-email_address no intervals no-extension,
                s_type    for global_address-com_type no intervals no-extension,
                s_test    for global_address-email_address no intervals no-extension.

The program kept steping on top of itself so I put the following code in place to prevent that from happening I need to replace it with some locking logic but have not had a chance to do that.
local_time_dif = sy-datum - s_time-low.
if local_time_dif < 60.
  wait up to 60 seconds.
endif.
Next we grab some data.
select single * from zemail_001 into global_header
    where source_program = s_source-low
      and email_date     = s_date-low
      and email_time     = s_time-low.
if s_only-low = ''.
  select * from zemail_002 into table global_address
      where source_program = s_source-low
        and email_date     = s_date-low
        and email_time     = s_time-low.
else.
  select * from zemail_002 into table global_address
    where source_program = s_source-low
      and email_date     = s_date-low
      and email_time     = s_time-low
      and email_address  = s_only-low.
endif.
select * from zemail_003a into table global_message
    where source_program = s_source-low
      and email_date     = s_date-low
      and email_time     = s_time-low
    order by sequence.
select * from zemail_006 into table global_attachment
    where source_program = s_source-low
      and email_date     = s_date-low
      and email_time     = s_time-low
    order by sequence.
The following code is to handle if the attachements are stored off line I will discuss how we archived this later but for now I am going to show you the code
if global_header-stored_offline = 'Y'.
  if global_header-attachment <> ''.
    perform run_java.
  else.
    select * from zemail_006 into table global_attachment
                  where source_program = s_source-low
                    and email_date     = s_date-low
                    and email_time     = s_time-low.
    if sy-subrc = 0.
      loop at global_attachment.
        global_header-attachment = global_attachment-attachment.
        perform run_java.
        global_mult = 'Y'.
        update zemail_006 set stored_offline = ' '
             where source_program = global_header-source_program
               and email_date     = global_header-email_date
               and email_time     = global_header-email_time.
      endloop.
    endif.
  endif.
endif.
Now we go and get the attachments and build the message along with getting the receivers
perform get_attachment.
* Populate message body text
refresh it_message.
loop at global_message.
  it_message = global_message-message.
  append it_message.
endloop.

*  Build the Receivers file
clear t_receivers.
refresh t_receivers.


t_receivers-receiver = s_test-low.
t_receivers-rec_type = 'U'.
t_receivers-com_type = 'INT'.
t_receivers-notif_ndel = 'X'.
if s_test-low <> ''.
  append t_receivers.
endif.
This section allow for the overrideing of the e-mail address/fax number if the program is being run on the development machine. My production client is 400
if sy-mandt > 399.
  loop at global_address.
    if global_address-com_type <> 'TEL'.
      t_receivers-receiver = global_address-email_address.
      t_receivers-rec_type = 'U'.
      t_receivers-com_type = 'INT'.
      t_receivers-notif_ndel = 'X'.
      append t_receivers.
      clear t_receivers.
    else.
      global_fax = 'Y'.
    endif.
  endloop.
else.
  clear global_fax.
  loop at global_address.
    if global_address-com_type = 'TEL'.
      global_fax = 'Y'.
    endif.
  endloop.
  select address_type address from zemail_005 into table global_test_add.
  loop at global_test_add.
    if global_test_add-address_type = 'E'.
      t_receivers-receiver = global_test_add-address.
      t_receivers-rec_type = 'U'.
      t_receivers-com_type = 'INT'.
      t_receivers-notif_del = 'X'.
      append t_receivers.
      clear t_receivers.
    endif.
  endloop.
endif.
The following update is to prevent any other programs from grabing this same record I created this program so multiple copies could be run at the same time but it's not really needed again I should take this out and move to a SAP locking method but have not done this yet.
update  zemail_001 set sent_date = sy-datum
                       sent_user = sy-uname
                       status    = 'U'
    where source_program = s_source-low
      and email_date     = s_date-low
      and email_time     = s_time-low.
I have two function calls to transmit the e-mails one for a single attachment and another for multiple attachments
if global_mult = 'N'.

  t_receivers_bk[] = t_receivers[].
  call function 'SO_DOCUMENT_SEND_API1'
    exporting
      document_data              = global_doc_data
      put_in_outbox              = 'X'
    tables
      packing_list               = t_packing_list
      object_header              = objhead
      contents_bin               = bindata
      contents_txt               = it_message
      receivers                  = t_receivers
    exceptions
      too_many_receivers         = 1
      document_not_sent          = 2
      document_type_not_exist    = 3
      operation_no_authorization = 4
      parameter_error            = 5
      x_error                    = 6
      enqueue_error              = 7
      others                     = 8.
else.
  t_receivers_bk[] = t_receivers[].
  call function 'SO_NEW_DOCUMENT_ATT_SEND_API1'
    exporting
      document_data              = global_doc_data
      put_in_outbox              = 'X'
    tables
      packing_list               = t_packing_list
      object_header              = objhead
      contents_bin               = bindata
      contents_txt               = it_message
      receivers                  = t_receivers
    exceptions
      too_many_receivers         = 1
      document_not_sent          = 2
      document_type_not_exist    = 3
      operation_no_authorization = 4
      parameter_error            = 5
      x_error                    = 6
      enqueue_error              = 7
      others                     = 8.
endif.
I update zemail_008 with the results from the call to the function modules
global_error = sy-subrc.
if sy-subrc <> 0.
  global_error = sy-subrc.
else.
  perform insert_into008.
endif.
Now then we update the Header file with the fact that the e-mail was transmitted.
update zemail_001 set sent = global_error
       where source_program = global_header-source_program
         and email_date = global_header-email_date
         and email_time = global_header-email_time.
The previous code was for e-mail only this part is for faxing.
if global_fax = 'Y'.
  clear t_receivers.
  refresh t_receivers.
  if sy-mandt > 399.
    loop at global_address.
      if global_address-com_type = 'TEL'.
        ls_fax-rec_state = 'US'.
        ls_fax-rec_fax       = global_address-email_address.
        assign ls_fax to  casting.
        t_receivers-receiver = .
        t_receivers-rec_type = 'F'.
        t_receivers-com_type = 'TELFAX'.
        append t_receivers.
        clear t_receivers.
      endif.
    endloop.
  else.
    loop at global_test_add.
      if global_test_add-address_type = 'F'.
        ls_fax-rec_state = 'US'.
        ls_fax-rec_fax       = global_test_add-address.
        assign ls_fax to  casting.
        t_receivers-receiver = .
        t_receivers-rec_type = 'F'.
        t_receivers-com_type = 'TELFAX'.
        append t_receivers.
        clear t_receivers.
      endif.
    endloop.
  endif.
  t_receivers_bk[] = t_receivers[].
  perform insert_into008.
  call function 'SO_DOCUMENT_SEND_API1'
    exporting
      document_data              = global_doc_data
      put_in_outbox              = 'X'
    tables
      packing_list               = t_packing_list
      object_header              = objhead
      contents_bin               = bindata      "contents_bin = bindataotf
      contents_txt               = it_message
      receivers                  = t_receivers
    exceptions
      too_many_receivers         = 1
      document_not_sent          = 2
      document_type_not_exist    = 3
      operation_no_authorization = 4
      parameter_error            = 5
      x_error                    = 6
      enqueue_error              = 7
      others                     = 8.
  if sy-subrc <> 0.
    global_error = sy-subrc.
  endif.
  update zemail_001 set sent = global_error
         where source_program = global_header-source_program
           and email_date = global_header-email_date
           and email_time = global_header-email_time.
endif.
commit work.
Subroutines get_attachment Local Data
data: local_file_name(100) type c,
        global_slen          type i,
        global_key           type i value 26101957,
        mi_handle            type i,
        local_password(20)   type c,
        global_dest          like rfcdes-rfcdest,
        local_string(255)    type c,
        local_start          type i,
        local_count          type i,
        begin of mtab_data occurs 0,
          line(132) type c,
        end of mtab_data,
        tab_lines            like sy-tabix,
        local_bindata        type table of solisti1 with header line,
        local_bindataotf     type table of solisti1 with header line,
        blob_length type i,
        zemail_004_itab      type table of zemail_004 with header line.
Prelim work
global_mult = 'N'.
  clear: local_count,
         local_start.
  local_file_name = global_header-attachment.
Now we need to check to see if were attaching just a text file or a PDF etc
if global_header-type_attachment <> 'PDF' and global_header-type_attachment <> 'CSV'
     and global_header-type_attachment <> 'JPG'.
Text file
refresh bindata.
    open dataset local_file_name for input in text mode
                                  encoding default
                                  ignoring
                                  conversion errors.
    if sy-subrc eq 0.
      t_packing_list-doc_size = 0.
      clear t_packing_list.
      refresh t_packing_list.
      do.
        read dataset local_file_name into bindata.
        if sy-subrc <> 0.
          exit.
        endif.
        append bindata.
        clear bindata.
      enddo.
      close dataset local_file_name.
* Fill the document data and get size of attachment
      clear global_doc_data.
      read table bindata index global_cnt.
      global_doc_data-doc_size = ( global_cnt - 1 ) * 80.

* Fill the document data.
      global_doc_data-doc_size = 1.

* Populate the subject/generic message attributes
      global_doc_data-obj_name  = 'SAPRPT'.
      global_doc_data-obj_descr = global_header-subject.
* Populate the subject/generic message attributes
      global_doc_data-obj_name  = 'SAPRPT'.
      global_doc_data-obj_descr = global_header-subject.

* Describe the body of the message

      t_packing_list-transf_bin = space.
      t_packing_list-head_start = 1.
      t_packing_list-head_num = 0.
      t_packing_list-body_start = 1.
      describe table it_message lines t_packing_list-body_num.
      t_packing_list-doc_type = 'RAW'.
      append t_packing_list.

      t_packing_list-transf_bin = 'X'.
      t_packing_list-head_start = 1.
      t_packing_list-head_num   = 1.
      t_packing_list-body_start = 1.

      describe table bindata lines t_packing_list-body_num.
      t_packing_list-doc_type  = ld_format.
      t_packing_list-obj_descr = ld_attdescription.
      t_packing_list-doc_size  = t_packing_list-body_num * 80.
      t_packing_list-obj_name  = global_header-name_attach.
      t_packing_list-doc_type  = global_header-type_attachment.
      append t_packing_list.
      w_sent_all = 'X'.
      concatenate global_header-name_attach '.' global_header-type_attachment into objhead.
      append objhead.

    endif.
When it's not a text file
else.
    wait up to 5 seconds.
    clear: bindata,
           bindataotf.
    refresh: bindata,
             bindataotf.
    select single * from zemail_004 into zemail_004_itab.
    global_slen = strlen( zemail_004_itab-password ).
I choose to use FTP to get the attachment into an internal table in my program I am sure there are other ways of doing this but this is how I choose to do it. First you have to scramble the password.
*-- FTP_CONNECT requires an encrypted password to work
    call function 'HTTP_SCRAMBLE'
      exporting
        source      = zemail_004_itab-password
        sourcelen   = global_slen
        key         = global_key
      importing
        destination = local_password.
Now were ready to connect to the server.
global_dest = zemail_004_itab-address.
    call function 'FTP_CONNECT'
      exporting
        user            = zemail_004_itab-userid
        password        = local_password
        host            = global_dest
        rfc_destination = 'SAPFTPA'
      importing
        handle          = mi_handle
      exceptions
        not_connected   = 1
        others          = 2.
Pull the data from the server This section is to handle a single attachment
if local_file_name <> ''.
      call function 'FTP_SERVER_TO_R3'
        exporting
          handle      = mi_handle
          fname       = local_file_name
        importing
          blob_length = blob_length
        tables
          blob        = bindata.
The following will create the email attachments
* Fill the document data and get size of attachment
      clear global_doc_data.
      read table bindata index global_cnt.
      global_doc_data-doc_size = ( global_cnt - 1 ) * 80.

* Fill the document data.
      global_doc_data-doc_size = 1.

* Populate the subject/generic message attributes
      global_doc_data-obj_name  = 'SAPRPT'.
      global_doc_data-obj_descr = global_header-subject.

* Describe the body of the message
      clear t_packing_list.
      refresh t_packing_list.
      t_packing_list-transf_bin = space.
      t_packing_list-head_start = 1.
      t_packing_list-head_num   = 0.
      t_packing_list-body_start = 1.
      describe table it_message lines t_packing_list-body_num.
      t_packing_list-body_num = 1.
      t_packing_list-doc_type = 'RAW'.

      append t_packing_list.

      t_packing_list-transf_bin = 'X'.

      t_packing_list-head_start = 1.
      t_packing_list-head_num   = 1.
      t_packing_list-body_start = 1.

      describe table bindata lines t_packing_list-body_num.
      t_packing_list-doc_type  = ld_format.
      t_packing_list-obj_descr = ld_attdescription.
      t_packing_list-doc_size  = t_packing_list-body_num * 80.
      t_packing_list-obj_name  = global_header-name_attach.
      t_packing_list-doc_type  = global_header-type_attachment.
      append t_packing_list.
      w_sent_all = 'X'.
      concatenate global_header-name_attach '.' global_header-type_attachment into objhead.
      append objhead.

      call function 'FTP_SERVER_TO_R3'
        exporting
          handle      = mi_handle
          fname       = local_file_name
        importing
          blob_length = blob_length
        tables
          blob        = bindataotf.

* Fill the document data and get size of attachment
      clear global_doc_data.
      read table bindataotf index global_cnt.
      global_doc_data-doc_size = ( global_cnt - 1 ) * 80.

* Fill the document data.
      global_doc_data-doc_size = 1.

* Populate the subject/generic message attributes
      global_doc_data-obj_name  = 'SAPRPT'.
      global_doc_data-obj_descr = global_header-subject.

* Describe the body of the message
      clear t_packing_list.
      refresh t_packing_list.
      t_packing_list-transf_bin = space.
      t_packing_list-head_start = 1.
      t_packing_list-head_num = 0.
      t_packing_list-body_start = 1.
      describe table it_message lines t_packing_list-body_num.
      t_packing_list-doc_type = 'RAW'.
      append t_packing_list.

      t_packing_list-transf_bin = 'X'.
      t_packing_list-head_start = 1.
      t_packing_list-head_num   = 1.
      t_packing_list-body_start = 1.

      describe table bindataotf lines t_packing_list-body_num.
      t_packing_list-doc_type  = ld_format.
      t_packing_list-obj_descr = ld_attdescription.
      t_packing_list-doc_size  = t_packing_list-body_num * 80.
      t_packing_list-obj_name  = global_header-name_attach.
      t_packing_list-doc_type  = global_header-type_attachment.
      append t_packing_list.
      w_sent_all = 'X'.
      concatenate global_header-name_attach global_header-type_attachment into objhead.
      append objhead.
Multiple Attachments
else.
      loop at global_attachment.
        refresh local_bindata.
        clear   local_bindata.

* Fill the document data and get size of attachment
        clear global_doc_data.
        read table bindata index global_cnt.
        global_doc_data-doc_size = ( global_cnt - 1 ) * 255.

* Fill the document data.
        global_doc_data-doc_size = 1.

* Populate the subject/generic message attributes
        global_doc_data-obj_langu = sy-langu.
        global_doc_data-obj_name  = 'SAPRPT'.
        global_doc_data-obj_descr = global_header-subject.
        global_doc_data-sensitivty = 'F'.

* Describe the body of the message
        clear t_packing_list.
        if local_count = 0.
          t_packing_list-transf_bin = space.
          t_packing_list-head_start = 1.
          t_packing_list-head_num   = 0.
          t_packing_list-body_num   = 1.
          t_packing_list-body_start = 1.
          t_packing_list-doc_type = 'RAW'.
          local_start = 1.
          append t_packing_list.

        endif.

        call function 'FTP_SERVER_TO_R3'
          exporting
            handle      = mi_handle
            fname       = global_attachment-attachment
          importing
            blob_length = blob_length
          tables
            blob        = local_bindata.

        describe table local_bindata lines tab_lines.

        append lines of local_bindata to bindata.
        objhead = global_attachment-name_attach.
        append objhead.



        local_count = local_count + 1.
        if local_count > 1.
          global_mult = 'Y'.
        endif.

        t_packing_list-transf_bin = 'X'.
        t_packing_list-head_start = local_count.
        t_packing_list-head_num   = local_count.
        t_packing_list-body_start = local_start.
        t_packing_list-body_num   = tab_lines.
        t_packing_list-doc_type   = global_attachment-type_attachment.
        t_packing_list-obj_name   = 'ANALAGE'.
        t_packing_list-obj_descr  = global_attachment-description.
        t_packing_list-doc_size   = blob_length + strlen( objhead ).
        local_start               = local_start + tab_lines.
        append t_packing_list.
        clear  t_packing_list.
        clear  objhead.

      endloop.
    endif.
Now then we need to disconnect from the server
call function 'FTP_DISCONNECT'
      exporting
        handle = mi_handle.
* Fill the document data and get size of attachment
    clear global_doc_data.
    read table bindata index global_cnt.
    w_sent_all = 'X'.
    global_doc_data-doc_size = ( global_cnt - 1 ) * 255.

* Fill the document data.
    global_doc_data-doc_size = 1.

* Populate the subject/generic message attributes
    global_doc_data-obj_langu = sy-langu.
    global_doc_data-obj_name  = 'SAPRPT'.
    global_doc_data-obj_descr = global_header-subject.
    global_doc_data-sensitivty = 'F'.
  endif.
endform.                    " GET_ATTACHMENT
Update the History file
*&---------------------------------------------------------------------*
*&      Form  INSERT_INTO008
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
form insert_into008.
  data: local_sequence type zemail_008-sequence,
        local_com_type  type zemail_002-com_type.
  clear local_sequence.

  select sequence from zemail_008 into local_sequence
                           where source_program = global_header-source_program
                             and email_date     = global_header-email_date
                             and email_time     = global_header-email_time
            order by sequence descending.
    exit.
  endselect.
  loop at t_receivers_bk.
    local_sequence = local_sequence + 1.
    zemail_008-source_program = global_header-source_program.
    zemail_008-email_date     = global_header-email_date.
    zemail_008-email_time     = global_header-email_time.
    zemail_008-sequence       = local_sequence.
    zemail_008-email_address  = t_receivers_bk-receiver.
    zemail_008-sent_date      = sy-datum.
    zemail_008-sent_time      = sy-uzeit.
    select single com_type from zemail_002 into local_com_type
                          where source_program = global_header-source_program
                            and email_date     = global_header-email_date
                            and email_time     = global_header-email_time
                            and email_address  = zemail_008-email_address.
    zemail_008-com_type       = local_com_type.
    insert zemail_008.
  endloop.
endform.                    " INSERT_INTO008
Getting the file from the archive
*&---------------------------------------------------------------------*
*&      Form  RUN_JAVA
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
form run_java .
  data: local_commandline(350) type c,
        local_hold(350)        type c,
        local_hold2(250)       type c,
        local_file(100)        type c,
        local_position         type i.


  if sy-sysid = 'QAS'.
    sy-sysid  = 'TST'.
  endif.
  if sy-sysid = 'PRD'.
    sy-sysid  = 'PROD'.
  endif.
  search global_header-attachment for '/usr/sap/transfer/sapout/email/ar/stop_ship/'.
  if sy-subrc = 0.
    local_position = sy-fdpos + 44.
    local_file = global_header-attachment+local_position(100).
  else.
    search global_header-attachment  for '/usr/sap/transfer/sapout/email/ar/zauto/'.
    if sy-subrc = 0.
      local_position = sy-fdpos + 40.
      local_file = global_header-attachment+local_position(100).
    else.
      search global_header-attachment  for '/usr/sap/transfer/sapout/email/ap/zchecks/'.
      if sy-subrc = 0.
        local_position = sy-fdpos + 42.
        local_file = global_header-attachment+local_position(100).
      else.
        search global_header-attachment  for '/usr/sap/transfer/sapout/email/'.
        if sy-subrc = 0.
          local_position = sy-fdpos + 31.
          local_file = global_header-attachment+local_position(100).
        endif.
      endif.
    endif.
  endif.
  replace all occurrences of '/' in global_header-attachment with '\' .
  concatenate '"\\SAP' sy-sysid '\rootbin' global_header-attachment '"'
              into local_hold2.
  concatenate '"' local_file '"'
              into local_hold.
  concatenate local_hold local_hold2 into local_commandline separated by ' '.

  call function 'WS_EXECUTE'
    exporting
      program        = '\\mpfs-portalprod\sap\aws\dist\recvaws.bat'
      commandline    = local_commandline
      inform         = ''
    exceptions
      prog_not_found = 1.

  if sy-subrc = 0.
    if global_mult <> 'Y'.
      update zemail_001 set stored_offline = ' '
             where source_program = global_header-source_program
               and email_date     = global_header-email_date
               and email_time     = global_header-email_time.
    endif.
  endif.
endform.                    " RUN_JAVA
I put this routine in but it's very tied into what were doing you would need to handle this on your own. Just as a side note were using the Amazon S3 Cloud to hold the archive.
This is the heart of the system but I have another three programs to add I will be adding those in my next blog session. If you would like the full code to this program without all the breaks please e-mail me and I will be happy to send it to you.