Menu

Sending E-Mails with Attachments from SAP ERP

2014-08-10       

After discussing how to send e-mails from SAP in yesterday’s post, today I want to take it a bit further and explain how to add attachments or even executable SAP transactions to these mails.

Sending e-mails with attachments from SAP

Attaching a file to an e-mail in SAP ERP is not really hard. Basically, it consists of three steps:

Sounds like a bit of function module action, right? Luckily, there’s another catch-em-all function module available in function group SOI1: The function module SO_NEW_DOCUMENT_ATT_SEND_API1 will do everything you want in one simple step.

When it comes to the attached file, there are three common options of how the attachment is created:

In my example, I’m going to attach just a few lines of text as a .txt file in order to make it not too complicated – the basic steps remain the same anyway.

You should already know how to fill the parameters that are related to the e-mail itself, so I’m not going over that again (if you don’t, read yesterday’s post). Instead, let’s focus on the parameters and input tables required to make the file attachment work.

Compared to SO_NEW_DOCUMENT_SEND_API1,  the  function module SO_NEW_DOCUMENT_ATT_SEND_API1  has one additional mandatory parameter which is called packing_list. This parameter is a bit tricky. To understand it, you must be aware that all of the email content – email body as well as attachments – goes into the same tables. The packing list defines which lines of these tables belong to which objects (email body or attachments). The packing list also contains the metadata of the e-mail parts, including the document type (e.g. “RAW”). From a technical perspective, we’re now sending a so-called multipart e-mail (MIME type multipart/mixed) instead of a plain text one (MIME type text/plain).

Let’s look at the necessary steps we need to execute. I’m omitting the variable definitions here, you’ll find the entire sample program on the second page of this article. First, we fill our content table with the e-mail body content.

* Fill the mail contents
ls_objcont-line = 'Test e-mail with attachment'.
APPEND ls_objcont TO lt_objcont.
ls_objcont-line = 'Second line of text'.
APPEND ls_objcont TO lt_objcont.

We now have two lines of text in our content table. Now we need to tell the packing list about that.

* E-mail body starts at first line
ls_packing_list-body_start = 1.
* Length equals the table length
DESCRIBE TABLE lt_objcont LINES lv_body_length.
ls_packing_list-body_num = lv_body_length.
* The doc type for the e-mail body is now defined here
ls_packing_list-doc_type = 'RAW'.
* The remaining fields stay empty for the first line
APPEND ls_packing_list TO lt_packing_list.

Quite easy so far. Now we just append the content of the attachment directly after the content of the e-mail body.

* Fill in the next lines, these contain the attachment
ls_objcont-line = 'First line of attached txt file'.
APPEND ls_objcont TO lt_objcont.
ls_objcont-line = 'Second line of attached txt file'.
APPEND ls_objcont TO lt_objcont.
ls_objcont-line = 'Third line of attached txt file'.
APPEND ls_objcont TO lt_objcont.

And again, the packing list needs to know about that attachment. This time, the calculation is a bit trickier and we have to fill more fields.

* Create the packing list entry for the attachment
CLEAR ls_packing_list.
ls_packing_list-head_start = 1.
ls_packing_list-head_num = 1.
* The attachment starts where the e-mail body stopped
ls_packing_list-body_start = 1 + lv_body_length.
DESCRIBE TABLE lt_objcont LINES lv_attc_length.
* Substract the length of the email body from total
lv_attc_length = lv_attc_length - lv_body_length.
ls_packing_list-body_num = lv_attc_length.
* Fill the rest of the fields for the attachment
ls_packing_list-doc_type = 'RAW'.
ls_packing_list-obj_name = 'textfile.txt'.
ls_packing_list-obj_descr = 'Some text file'.
ls_packing_list-doc_size = 255 * lv_attc_length.
APPEND ls_packing_list TO lt_packing_list.

Almost done! All you need to do now is fill the receivers and document metadata parameters. Then you can supply all this data to the function module SO_NEW_DOCUMENT_ATT_SEND_API1 and fire off your e-mail. You can monitor it with the SCOT transaction just like before.

Be aware which tables you’re using, though. In this example, both our e-mail body and the attachment were plain ASCII text. If you’re sending a binary file as an attachment (such as a PDF), you will need to use the CONTENTS_BIN table instead of the CONTENTS_TXT. The packing list needs to know about this by setting the flag TRANSF_BIN in the respective packing list entry.

And that’s it! Check out the next page to find out how to attach executable transaction or even program links to an e-mail sent from SAP.

Sample program for e-mails with attachments

Here is the entire program I used to demonstrate how to send e-mails with attachments from SAP ERP.

REPORT ztestemail.

DATA lt_objcont TYPE STANDARD TABLE OF solisti1.
DATA ls_objcont TYPE solisti1.
DATA lt_receivers TYPE STANDARD TABLE OF somlreci1.
DATA ls_receivers TYPE somlreci1.
DATA ls_document_data LIKE sodocchgi1.
 
DATA lv_body_length TYPE i.
DATA lv_attc_length TYPE i.
 
DATA lt_objhead TYPE STANDARD TABLE OF solisti1.
DATA ls_objhead TYPE solisti1.
 
DATA lt_packing_list TYPE STANDARD TABLE OF sopcklsti1.
DATA ls_packing_list TYPE sopcklsti1.
 
* Fill the document header
ls_document_data-obj_name = 'Test'.
ls_document_data-obj_descr = 'This is the e-mail title!'.
 
* Fill the mail contents
ls_objcont-line = 'Test e-mail with attachment'.
APPEND ls_objcont TO lt_objcont.
ls_objcont-line = 'Second line of text'.
APPEND ls_objcont TO lt_objcont.
 
* Email body is done - create the packing list entry
* E-mail body starts at first line
ls_packing_list-body_start = 1.
DESCRIBE TABLE lt_objcont LINES lv_body_length.
ls_packing_list-body_num = lv_body_length.
* The doc type for the e-mail body now is defined here
ls_packing_list-doc_type = 'RAW'.
* The remaining fields stay empty for the first line
APPEND ls_packing_list TO lt_packing_list.
 
* Fill in the next lines, these contain the attachment
ls_objcont-line = 'First line of attached txt file'.
APPEND ls_objcont TO lt_objcont.
ls_objcont-line = 'Second line of attached txt file'.
APPEND ls_objcont TO lt_objcont.
ls_objcont-line = 'Third line of attached txt file'.
APPEND ls_objcont TO lt_objcont.
 
* Create the packing list entry for the attachment
CLEAR ls_packing_list.
ls_packing_list-head_start = 1.
ls_packing_list-head_num = 1.
* The attachment starts where the e-mail body stopped
ls_packing_list-body_start = 1 + lv_body_length.
DESCRIBE TABLE lt_objcont LINES lv_attc_length.
* Substract the length of the email body from total
lv_attc_length = lv_attc_length - lv_body_length.
ls_packing_list-body_num = lv_attc_length.
* Fill the rest of the fields for the attachment
ls_packing_list-doc_type = 'RAW'.
ls_packing_list-obj_name = 'textfile.txt'.
ls_packing_list-obj_descr = 'Some text file'.
ls_packing_list-doc_size = 255 * lv_attc_length.
APPEND ls_packing_list TO lt_packing_list.
 
* We also needs an object header with the filename
ls_objhead-line = 'textfile.txt'.
APPEND ls_objhead TO lt_objhead.
 
* Fill the receiver list
ls_receivers-receiver = 'someguy@example.xyz'.
ls_receivers-rec_type = 'U'.
APPEND ls_receivers TO lt_receivers.
 
* Create the e-mail with the attachment and send it
CALL FUNCTION 'SO_NEW_DOCUMENT_ATT_SEND_API1'
  EXPORTING
    document_data              = ls_document_data
    commit_work                = 'X'
  TABLES
    packing_list               = lt_packing_list
    object_header              = lt_objhead
    contents_txt               = lt_objcont
    receivers                  = lt_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.
  WRITE 'Email could not be sent.'.
  WRITE sy-subrc.
ELSE.
  WRITE 'Email was sent!'.
ENDIF.