Skip to Content
Author's profile photo Michelle Crapo

Challenge for the Day! Month or even Next Year! Project you are working on…

I try to blog. Some people will say most of it is not technical. And yes, they would be right. Today I’m issuing a challenge. It is specific to all those people who are out there writing ABAP. It could also be for non-ABAP languages. Get the theme? Technical blog.

My challenge: Write a blog about what you are working on!

Why? Because when I ask people why they don’t write blogs about ABAP, the answer is that it’s all been done. We don’t want to just repeat things. So if you are writing about your project you won’t be duplicating anything. AND we will get some new ABAP (technical type) blogs.  Heck, you can write about an old project, we wouldn’t know. It can also be an old project.

You can share as little or as much code as you want!

This is cool, because there is something in it for you!

Over one million users stop in to the SAP Community. If you aren’t doing something “right” then they will probably comment. Worried about that? Don’t be. I don’t do a lot of things “right”. That’s OK. I learn and get better. Note to those who comment constructive feedback is always welcome. Rude feedback is not welcome. An example would be you telling me that I’m an idiot. Yes, part of the rules. Sadly, people like me rarely read all of them.   (I did not either – but I’m going to go look at them today.)

Anyway Challenge time

So I thought – I’d just pull out a project that I worked on before.   I am on 4.6C. Yes, it’s still working great! That means I have limited access to classes/objects. That’s why I’ve been bookmarking so many things.

So I’m trying to decide what fun things to share from the project.    I think you may want to know the description. We wanted to save our “PDF” documents to a directory, be able to retrieve and mail them. This is a general area where we could put whatever documents we wanted.  I think we have more than 10 types of documents there. Some we create at the time we are using this, Some are uploaded from a directory, some are created via output types and/or messages.  It just depended on what we wanted.  And we could add or remove document types at a later date.

I decided to share the mailing piece of it because it could use some help with some of the newer ABAP objects that are available.

This is a function module that accepts the email name, the document and the body.  The document is actually a key for where we pull the information. It is also an RFM – it’s called from a webpage.

 LOOP AT gt_doc INTO gs_doc.
    IF gv_message IS INITIAL.
      PERFORM check_input.
      message = gv_message.
  IF gv_message IS INITIAL.
    PERFORM fill_receiver_table.
    gv_start = 1.
    gv_cnt = 1.
    LOOP AT gt_doc INTO gs_doc.
      PERFORM get_attachment.
    IF gt_contents_bin IS INITIAL.
      gv_message = 'No attachments selected.'.
      message = gv_message.
      PERFORM email_create.
      PERFORM send_email.
    message = gv_message.

So this tells you next to nothing.  Here I loop through the receivers:

  LOOP AT gt_email INTO gs_email.
    CLEAR gs_receivers.
    gs_receivers-receiver = gs_email-email_add.
    gs_receivers-com_type = lc_send_internet.
    gs_receivers-rec_type = lc_internet.
    APPEND gs_receivers TO gt_receivers.

Easy! Now I’m pulling the “PDF” from our system:


  IF sy-subrc <> 0.
    CONCATENATE 'Could not open file' docs-file_name
        INTO message SEPARATED BY space.
    PERFORM update_log USING imp

    READ DATASET docs-file_name INTO pdf LENGTH lv_size.
    IF sy-subrc <> 0.
    pdf_size = pdf_size + lv_size.
    APPEND pdf.

Got it!  So now I get it ready!

* Move the 134 character table to a 255 format need for PDF attachment
              line_width_dst              = 255
              content_in                  = lt_pdf[]
              content_out                 = lt_contents_bin[]
              err_line_width_src_too_long = 1
              err_line_width_dst_too_long = 2
              err_conv_failed             = 3
              OTHERS                      = 4.

* Add the contents to the table that will have all the attachments
    CLEAR ls_contents_bin.
    LOOP AT lt_contents_bin INTO ls_contents_bin.
      APPEND ls_contents_bin TO gt_contents_bin.
      CLEAR gs_contents_bin.

    CLEAR: lv_lines_bin, gs_packing_list.
* Set up the name & Description
    WRITE gs_doc-document TO lv_document NO-ZERO.
    WRITE gs_doc-document TO lv_document15 NO-ZERO.
    WRITE gs_doc-item TO lv_item NO-ZERO.
    WRITE gs_doc-item TO lv_item6 NO-ZERO.
    WRITE gv_cnt TO lv_cnt NO-ZERO.
    CONDENSE: lv_document NO-GAPS,
              lv_document15 NO-GAPS,
              lv_item NO-GAPS,
              lv_item6 NO-GAPS,
              lv_cnt NO-GAPS.
    CONCATENATE lv_document lv_item lv_cnt
                INTO gs_packing_list-obj_name.
    CONCATENATE lv_document15 lv_item6 lv_cnt
                INTO gs_packing_list-obj_descr
                SEPARATED BY space.

* Set up the packing list describint the current attachment

    DESCRIBE TABLE lt_contents_bin LINES lv_lines_bin.
    READ TABLE lt_contents_bin INTO ls_contents_bin INDEX lv_lines_bin.
    gs_packing_list-transf_bin = 'X'.
    gs_packing_list-head_start = gv_start.
    gs_packing_list-head_num = gv_start.
    gs_packing_list-body_start = gv_start.
    gs_packing_list-doc_type = 'PDF'.
    gs_packing_list-doc_size = lv_pdf_size.
    gs_packing_list-body_num = lv_lines_bin.
    APPEND gs_packing_list TO gt_packing_list.

* Set up start position for next attachment
    gv_start = gv_start + lv_lines_bin.
    gv_cnt = gv_cnt + 1.

Here’s the fun part – creating the attachment.

 CLEAR: gs_contents_txt, gs_packing_list.
  READ TABLE gt_doc INTO gs_doc INDEX 1.
  lv_numc = gs_doc-document.
  lv_vbeln = lv_numc.
* Create Message Body Title and Description
  IF gs_imp-mail_mess IS INITIAL AND
     gt_email_body IS INITIAL.
    gs_contents_txt-line = 'See attachment.'.
    APPEND gs_contents_txt TO gt_contents_txt.
  ELSEIF NOT gs_imp-mail_mess IS INITIAL.
    ls_text-mail_mess = gs_imp-mail_mess.
    APPEND ls_text TO lt_text.
              language    = sy-langu
              text_stream = lt_text[]
              itf_text    = lt_mail_content[].

    LOOP AT lt_mail_content INTO ls_mail_content.
      gs_contents_txt-line = ls_mail_content-tdline.
      APPEND gs_contents_txt TO gt_contents_txt.
    LOOP AT gt_email_body INTO gs_email_body.
      gs_contents_txt-line = gs_email_body-email.
      APPEND gs_contents_txt TO gt_contents_txt.

  IF gs_imp-doc_type IS INITIAL.
    READ TABLE gt_doc INTO gs_doc INDEX 1.
    IF sy-subrc = 0.
      gs_imp-doc_type = gs_doc-doc_type.

  IF gs_imp-doc_type = 'TD'.

    SELECT SINGLE vbeln INTO vbak FROM vbak       
    WHERE vbeln = lv_vbeln.                      
    IF sy-subrc = 0.
                document_number      = lv_vbeln
                i_block              = ' '
                i_no_authority_check = 'X'
                ekuwev               = ls_ekuwev.
      IF NOT ls_ekuwev-name1 IS INITIAL.
        CONCATENATE 'Deliver to ' ls_ekuwev-name1
                     INTO lv_obj_descript
                     SEPARATED BY space.
      SELECT SINGLE banfn INTO eban FROM eban        
      WHERE banfn = lv_vbeln.                       
      IF sy-subrc = 0.
        CONCATENATE 'Deliver to' 'Furst-McNess Company'
                     INTO lv_obj_descript
                     SEPARATED BY space.



  IF NOT gs_imp-doc_type IS INITIAL AND
         lv_obj_descript IS INITIAL.
    SELECT SINGLE description INTO lv_description
           FROM zdoc_types
             WHERE doc_type = gs_imp-doc_type.
    IF sy-subrc = 0.
      CONCATENATE 'McNess' lv_description 'Document'
            INTO lv_obj_descript
            SEPARATED BY space.
  IF lv_obj_descript IS INITIAL.
    gs_document_data-obj_descr = 'McNess Documents'.
    gs_document_data-obj_descr = lv_obj_descript.
  gs_document_data-expiry_dat = sy-datum + 10.

  gs_document_data-sensitivty = 'F'.
  gs_document_data-doc_size = gv_total_size.

* Body of E-mail
  CLEAR gs_packing_list.
  gs_packing_list-head_start = 1.
  gs_packing_list-head_num = 0.
  gs_packing_list-body_start = 1.
  gs_packing_list-body_num = gv_start.
  gs_packing_list-doc_type = 'RAW'.
  INSERT gs_packing_list INTO gt_packing_list INDEX 1.


Finally Send it!

TYPES: BEGIN OF lty_obj,
         tp TYPE soos-objtp,
         yr TYPE soos-objyr,
         no TYPE soos-objno,
         END OF lty_obj.

  DATA: lv_objid TYPE sofolenti1-object_id,
        ls_obj TYPE lty_obj,
        lv_objtp TYPE soos-objtp.

            document_data              = gs_document_data
            put_in_outbox              = ' '
            commit_work                = 'X'
            new_object_id              = lv_objid
            packing_list               = gt_packing_list[]
            contents_txt               = gt_contents_txt[]
            contents_bin               = gt_contents_bin[]
            receivers                  = gt_receivers[]
            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.
    CASE sy-subrc.
      WHEN 1.
        MESSAGE e007  INTO gv_message.
      WHEN 2.
        MESSAGE e008 INTO gv_message.
      WHEN 3.
        MESSAGE e009 INTO gv_message.
      WHEN 4.
        MESSAGE e010 INTO gv_message.
        MESSAGE e011 INTO gv_message.
    ls_obj = lv_objid.
*** Try to verify the record is ready to send - wait only 100 times
    DO 100 TIMES.
      SELECT SINGLE  objtp INTO lv_objtp
        FROM soos
          WHERE objtp = ls_obj-tp AND
                objyr = ls_obj-yr AND
                objno = ls_obj-no.
      IF sy-subrc = 0.

    SUBMIT rsconn01 WITH mode = 'INT' AND RETURN.
*    gv_message = 'Mail sent'.


This is the end of just a piece of that development.  We have screens where the user can enter requests for different documents.  If they double click then they have the PDF display so they can look at it prior to sending it. AND a co-worker put together a webpage that calls some of this code. That ways it can look pretty when they call it. And yes – this was 4.6C. She used JavaScript and Visual Basic. Cool. This is prior to even Webdynpro.

GUI Result:


Webpage result:


So my challenge is to share your project.  As much or as little code as you want. I promise we will be nice!

A side challenge – use objects to send the e-mail. I didn’t have them available. SO if someone could put them in the comments – that would be so nice.

Also anything else you would like to know about this? Hate the idea? Feel free to comment. I love responding to them.

Assigned Tags

      You must be Logged on to comment or reply to a post.
      Author's profile photo Panda Cheng
      Panda Cheng

      The interface of displaying PDF is really nice.

      I‘ll show this blog to my partner and tell him how to develop a nice display interface ^_^.

      Moreover, would you show more details about displaying PDF within a dialog screen?


      Author's profile photo Michelle Crapo
      Michelle Crapo
      Blog Post Author

      Sure - I'll type up another blog and add even more details.   This one just got too long. 🙂

      Thank you for your comment!


      Author's profile photo Jelena Perfiljeva
      Jelena Perfiljeva

      There is a good old blog about the "new way" to send emails using CL_BCS class. It's been a bit mangled by the new "world class" blog platform, unfortunately. Maybe a moderator could volunteer to fix and retag it?

      Considering the low version, I think it's pretty cool, with web page and all. We've also used PDF documents and emails a lot in my old job. We used GOS attachments to make the documents available in the standard transactions. Of course, that's not of use in 4.6 either. 🙂 If anything, I feel this makes me appreciate more what we have in ECC. And I imagine there are tons of things I don't even know we have available.

      Author's profile photo Michelle Crapo
      Michelle Crapo
      Blog Post Author

      Too true! A lot of advancement forward with the newer versions. I have to say I do miss 6.0 badly at times. Thank you for the CL_BCS class! I knew there was one.

      Yes - GOS, too new fangled for me. BUT it will be of use for people who read this, and want to do it in a different way.

      Thank you!

      Author's profile photo Florian Henninger
      Florian Henninger

      Hi Michelle,

      like the blog and like the challenge. Years ago, in my first project as an developer I also had to send mails and did it in a very similar way.

      Doing a blog about an ongoing project is a nice way to share something. Right at the moment I'm struggling putting an app to my Gateway, so this will be my blog for your challenge.

      Let's see how long it takes to get it running 🙂



      Author's profile photo Florian Henninger
      Florian Henninger

      Hi Michelle,


      here you got a codingline how to use the cl_bcs Jelena Perfiljeva mentioned.

      Some of those variables are selfmade, but I think everyone can get out how to use the class. I have wrapped it into a function to replace the call function easily.

      DATA: lcl_send_request       TYPE REF TO cl_bcs.
        DATA: lt_text                TYPE bcsy_text.
        DATA: lcl_document           TYPE REF TO cl_document_bcs.
        DATA: lcl_sender             TYPE REF TO cl_sapuser_bcs.
        DATA: lcl_reply_guy          TYPE REF TO if_recipient_bcs.
        DATA: lcl_recipient          TYPE REF TO if_recipient_bcs.
        DATA: bcs_exception          TYPE REF TO cx_bcs.
        DATA: lv_sent_to_all         TYPE os_boolean.
        DATA: lv_in_updatetask       TYPE sysubrc.
        ls_mailbasics = is_email_basic.
        lt_attachments = it_attachments.
        lv_express = iv_express_sending.
        lv_errorscreen = iv_with_errorscreen.
        IF ls_mailbasics-recipienttab IS INITIAL.
          RAISE no_recipients.
        IF ls_mailbasics-subject IS INITIAL.
          RAISE no_subject.
      *     -------- create persistent send request ------------------------
            lcl_send_request = cl_bcs=>create_persistent( ).
      *     -------- create and set document -------------------------------
      *     create document from internal table with text (Bodytext)
            lcl_document = cl_document_bcs=>create_document(
                            i_type    = ls_mailbasics-type      "First step always RAW
                            i_text    = ls_mailbasics-chardata
                            i_length  = ls_mailbasics-length
                            i_subject = ls_mailbasics-subject ).
      *     -------- add attachment-documents -------------------------------
      *     put all attachments to the email
            LOOP AT lt_attachments INTO ls_attachment.
              CALL METHOD lcl_document->add_attachment
                  i_attachment_type    = ls_attachment-type     "Should be always BIN in first release
                  i_attachment_subject = ls_attachment-subject
                  i_att_content_text   = ls_attachment-chardata
                  i_att_content_hex    = ls_attachment-hexdata.
      *     add document to send request
            CALL METHOD lcl_send_request->set_document( lcl_document ).
      *     --------- set sender -------------------------------------------
      * We want another sender for this document!
            IF ls_mailbasics-sender IS NOT INITIAL.
              lcl_sender = cl_sapuser_bcs=>create( ls_mailbasics-sender ).
              CALL METHOD lcl_send_request->set_sender
                  i_sender = lcl_sender.
      *     --------- set reply-recipient ----------------------------------
      * We need to get the reply to the given user!
            IF ls_mailbasics-reply_to_email IS NOT INITIAL.
              lcl_reply_guy = cl_cam_address_bcs=>create_internet_address(
                                                       ls_mailbasics-reply_to_email ).
      *     add reply-recipient with its respective attributes to send request
              CALL METHOD lcl_send_request->set_reply_to
                  i_reply_to = lcl_reply_guy.
      *     --------- add recipient (e-mail address) -----------------------
      *     create recipient - please replace e-mail address !!!
            LOOP AT  ls_mailbasics-recipienttab INTO ls_recipient.
              lcl_recipient = cl_cam_address_bcs=>create_internet_address(
                                                                     ls_recipient ).
      *     add recipient with its respective attributes to send request
              CALL METHOD lcl_send_request->add_recipient
                  i_recipient = lcl_recipient
                  i_express   = lv_express.
      *     ---------- send document ---------------------------------------
            CALL METHOD lcl_send_request->send(
                i_with_error_screen = lv_errorscreen
                result              = lv_sent_to_all ).
            IF lv_sent_to_all = 'X'.
              WRITE text-003.
                in_update_task = lv_in_updatetask.
      *         We are not in an Updatetask
            IF lv_in_updatetask = 0.
              COMMIT WORK.
      * -----------------------------------------------------------
      * *                     exception handling
      * -----------------------------------------------------------
      * * replace this very rudimentary exception handling
      * * with your own one !!!
      * But, if we get here, someone who wants to use this function
      * do not understand how this work!
      * So, a exception is quiet consequent!
      * -----------------------------------------------------------
          CATCH cx_bcs INTO bcs_exception.
      *      WRITE: text-001.
      *      WRITE: text-002, bcs_exception->error_type.
      *      EXIT.
            RAISE something_went_wrong.
      Author's profile photo Michelle Crapo
      Michelle Crapo
      Blog Post Author

      Perfect!!!!  Thank you.  Improvement comments are very welcome.


      Author's profile photo Mark Wagener
      Mark Wagener

      Hi Michelle,

      challenge accepted. Feel free to read and leave your opinion:



      Author's profile photo Michelle Crapo
      Michelle Crapo
      Blog Post Author

      Well worth reading this.

      Thank you, Thank you