在 SAP ABAP 开发过程中,从 ABAP 发送电子邮件是一项非常常见的要求。在发送电子邮件之前,SAP 服务器中 SMTP 和邮件服务器的所有必需配置都需要就位。
电子邮件发送是获取 SAP 工作日志或报告详细信息的现有方法。收件箱中收到电子邮件的人会根据其中的内容执行不同的操作。电子邮件可能只包含描述,也可能包含附件文件,这取决于业务需求。
在 SAP 中发送带有 XML、DOC、XLS 等附件的外部电子邮件是一种常见的方法,现在 SAP 用户希望接收 XLSX、DOCX 格式的附件,因为这是 MS Office 2007 中的格式。我们将详细介绍如何创建 XLSX(一般为四位数文件扩展名)文件附件,这与我们在 sap 外部电子邮件发送中创建二进制 XLS 附件的方法略有不同。
发送带有附件的邮件: SO_NEW_DOCUMENT_ATT_SEND_API1 函数模块
此 ABAP 程序使用功能模块 "SO_NEW_DOCUMENT_ATT_SEND_API1 "来发送带有附件的电子邮件。发送带有附件的电子邮件涉及五个步骤。
- 添加收件人
- 输入邮件内容
- 创建附件
- 打包邮件内容和附件
- 最后,发送邮件。
在开始编写代码之前,请确保在 SCOT 中正确配置了一切。请联系 Basis 团队,他们会帮助您进行配置。
声明以下内容:
DATA: lt_mailrecipients TYPE STANDARD TABLE OF somlrec90 WITH HEADER LINE,
lt_mailtxt TYPE STANDARD TABLE OF soli WITH HEADER LINE,
lt_attachment TYPE STANDARD TABLE OF solisti1 WITH HEADER LINE,
lt_mailsubject TYPE sodocchgi1,
lt_packing_list TYPE STANDARD TABLE OF sopcklsti1 WITH HEADER LINE,
gv_cnt TYPE i.
现在,让我们开始格式化邮件。
lt_mailrecipients-rec_type = 'U'.
lt_mailrecipients-com_type = 'INT'.
lt_mailrecipients-receiver = 'someone@erpdb.info'.
APPEND lt_mailrecipients .
CLEAR lt_mailrecipients .
写入邮件内容:
lt_mailtxt = 'Hi How are you'. APPEND lt_mailtxt. CLEAR lt_mailtxt.
lt_mailtxt = 'Here is a test mail'. APPEND lt_mailtxt. CLEAR lt_mailtxt.
lt_mailtxt = 'Thanks'. APPEND lt_mailtxt. CLEAR lt_mailtxt.
创建附件:
DATA: BEGIN OF lt_po_data_cons OCCURS 0,
ebeln like ekpo-ebeln,
ebelp like ekpo-ebelp,
END OF lt_po_data_cons.
SELECT ebeln ebelp INTO TABLE lt_po_data_cons UP TO 10 ROWS FROM ekpo.
CLASS cl_abap_char_utilities DEFINITION LOAD.
CONCATENATE 'PO' 'PO Line'
INTO lt_attachment SEPARATED BY
cl_abap_char_utilities=>horizontal_tab.
APPEND lt_attachment.
CLEAR lt_attachment.
LOOP AT lt_po_data_cons.
CONCATENATE lt_po_data_cons-ebeln lt_po_data_cons-ebelp
INTO lt_attachment SEPARATED BY
cl_abap_char_utilities=>horizontal_tab.
CONCATENATE cl_abap_char_utilities=>newline lt_attachment
INTO lt_attachment.
APPEND lt_attachment.
CLEAR lt_attachment.
ENDLOOP.
打包邮件内容和附件:
lt_packing_list-transf_bin = space.
lt_packing_list-head_start = 1.
lt_packing_list-head_num = 0.
lt_packing_list-body_start = 1.
lt_packing_list-body_num = LINES( lt_mailtxt ).
lt_packing_list-doc_type = 'RAW'.
APPEND lt_packing_list. CLEAR lt_packing_list.
lt_packing_list-transf_bin = 'X'.
lt_packing_list-head_start = 1.
lt_packing_list-head_num = 1.
lt_packing_list-body_start = 1.
lt_packing_list-body_num = LINES( lt_attachment ).
lt_packing_list-doc_type = 'XLS'. " You can give RAW incase if you want just a txt file.
lt_packing_list-obj_name = 'data.xls'.
lt_packing_list-obj_descr = 'data.xls'.
lt_packing_list-doc_size = lt_packing_list-body_num * 255.
APPEND lt_packing_list. CLEAR lt_packing_list.
lt_mailsubject-obj_name = 'MAILATTCH'.
lt_mailsubject-obj_langu = sy-langu.
lt_mailsubject-obj_descr = 'You have got mail'.
lt_mailsubject-sensitivty = 'F'.
gv_cnt = LINES( lt_attachment ).
lt_mailsubject-doc_size = ( gv_cnt - 1 ) * 255 + STRLEN( lt_attachment ).
最后,将邮件发出去。 就是这样。你们都完成了。只需调用该功能模块即可将邮件发送出去。
CALL FUNCTION 'SO_NEW_DOCUMENT_ATT_SEND_API1'
EXPORTING
document_data = lt_mailsubject
TABLES
packing_list = lt_packing_list
contents_bin = lt_attachment
contents_txt = lt_mailtxt
receivers = lt_mailrecipients
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 EQ 0.
COMMIT WORK.
SUBMIT rsconn01 WITH mode = 'INT' AND RETURN.
ENDIF.
使用 CL_DOCUMENT_BCS
在开始代码之前,请看下图。这将有助于您理解代码流程,因为每个节点(带框)都是通过调用 CL_BCS 和 CL_DOCUMENT_BCS 类的方法分别创建的。
| Node | Description | Class Reference |
|---|---|---|
| Send Request | Primary object used create and send an email | CL_BCS |
| Document | Subject, body and attachment | CL_DOCUMENT_BCS |
| Sender | Sender i.e. From email address | IF_SENDER_BCS |
| Recipient | Recipient i.e. To email address | IF_RECIPIENT_BCS |
| Attachment | This has a Type, Subject, Name, Size and Content | – |
第一步:声明必要的变量
我们必须使用基于 CL_BCS 类的电子邮件发送技术,因此开发的第一步是为所需的类/接口创建实例声明,如下所示:
* Business Communication Service object
DATA: send_request TYPE REF TO cl_bcs.
* Wrapper Class for Office Documents
DATA: document TYPE REF TO cl_document_bcs.
* Object Represents an SAP User
DATA: sender TYPE REF TO cl_sapuser_bcs.
* Interface of Recipient Object in BCS
DATA: recipient TYPE REF TO if_recipient_bcs.
* BCS: General Exceptions
DATA: bcs_exception TYPE REF TO cx_bcs.
* Utility Class
DATA: lo_result_data TYPE REF TO cl_salv_ex_result_data_table.
*Data
DATA: lo_data TYPE REF TO data.
CL_BCS 是向指定为收件人的人群发送电子邮件通知的类,下面的代码将返回 CL_BCS 类的引用。
TRY.
"Create persistent send request
DATA(lo_send_request) = cl_bcs=>create_persistent( ).
要创建电子邮件正文,需要使用 CL_DOCUMENT_BCS。下面是在程序中创建该对象引用的方法。
" Create and set up document object with attachment
DATA(lo_document) = cl_document_bcs=>create_document(
i_type = 'RAW' " Type of data
i_text = lt_body " Email body text
i_length = l_count " String length of email body
i_subject = 'Flight Details' ).
第二步:准备在附件中发送的最终数据。
这是您将准备最终数据表的步骤。根据客户的要求,我们需要填充附件文件的内部表。在此示例程序中,我创建了一个包含物料、工厂特定物料状态、采购组和利润中心的结构。
在示例代码中,我创建了一个选择查询来根据此示例需求从 MARC 读取相关条目。
我们需要为我们正在使用的内表准备字段目录。使用 LVC_S_FCAT 结构填充示例程序中指定的字段目录。
下面提供一个字段的示例:
APPEND INITIAL LINE TO i_fldcat ASSIGNING <fs_fieldcat>.
<fs_fieldcat>-no_out = ''.
<fs_fieldcat>-fieldname = 'MATNR'. " Fieldname
<fs_fieldcat>-outputlen = 18.
<fs_fieldcat>-dd_outlen = 18.
<fs_fieldcat>-reptext = 'Material Number'.
<fs_fieldcat>-edit = 'X'. " Edit
该字段目录用于创建输出 XLSX 文件的页眉。
为内部表 I_LINE 创建数据对象引用,如下所示:
* Create data object reference.
GET REFERENCE of i_line INTO lo_data.
创建实用程序类引用,如下所示:
CLEAR: lo_result_data.
lo_result_data = cl_salv_ex_util=>factory_result_data_table(
r_data = lo_data " internal table data reference
t_fieldcatalog = i_fldcat " field cat
).
第三步:获取 XML 版本并准备内部表条目的 XSTRING 值
下面是获取当前系统 XML 版本和要使用的 XML 版本的方法。
* get the version from Abstract Super Class for All Transformations
CLEAR: l_version.
l_version = cl_salv_bs_a_xml_base=>get_version( ).
* Get the file Type
* value 10 for XLSX file type
CLEAR: l_file_type.
l_file_type = if_salv_bs_xml=>c_type_xlsx.
* Get the flavour export
* Flavor for complete ALV XML
Clear: l_flavour.
l_flavour = if_salv_bs_c_tt=>c_tt_xml_flavour_export.
下面的步骤将根据所传递的 XML 版本和味道将输出附件数据转换为 XSTRING 格式。
" Transformation of data to XSTRING
CLEAR: l_contents_line.
CALL METHOD cl_salv_bs_tt_util=>if_salv_bs_tt_util~transform
EXPORTING
xml_type = l_file_type
xml_version = l_version
r_result_data = lo_result_data
xml_flavour = l_flavour
gui_type = if_salv_bs_xml=>c_gui_type_gui
IMPORTING
xml = l_contents_line.
下面是将 XSTRING 转换为二进制格式的步骤,I_OBJ_BIN 将包含二进制数据
" Converting the table contents from xstring to binary
CLEAR i_obi_bin.
CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
EXPORTING
buffer = l_contents_line
IMPORTING
output_length = l_count1
TABLES
binary_tab = i_obj_bin.
APPEND LINES oF i_obi_bin To i_binary_content.
第 4 步: 创建文件名和附件对象引用
创建带有 XLSX 扩展名(一般为 4 位数扩展名)的文件名,下面的逻辑还将为用户提供从电子邮件打开文件时输入费用文本选项,并保存到本地系统中。
创建附件文档引用,并将其分配给发送请求对象。
第 5 步:设置发件人和收件人详细信息
仅当您想要将发件人设置为不同于实际用户 (SY-UNAME) 时,才需要创建发件人对象。否则,发送者将自动与实际用户一起设置。
收件人可通过以下方式添加、
第 6 步:发送电子邮件的最后一步
下面的实例方法将发送带有附件的电子邮件,并返回成功标志。这是发送电子邮件的最后一步,下一步是处理任何异常的错误选项。
我们需要在发送电子邮件时明确给出提交工作。
第 7 步:异常处理
一般 BCS 异常类可用于此目的。
下面是捕捉异常并显示错误信息的方法:
现在,让我们看一下代码。
*&---------------------------------------------------------------------*
*& Report ZSEND_EMAIL
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zsend_email.
*This report will show the sample of how to send XLSX attachments to email address from sap.
* Types declaration.
TYPES: BEGIN OF ty_line,
matnr TYPE matnr, "Material Number
mmsta TYPE mmsta, "Plant-Specific Material Status
ekgrp TYPE ekgrp, "Purchasing Group
prctr TYPE prctr, "Profit Center
END OF ty_line.
*Data declaration
DATA:
l_version TYPE string, " Version
l_flavour TYPE fpm_file_name, " Flavour
l_sent_to_all TYPE os_boolean,
l_contents_line TYPE xstring, "vac53733 10642
l_i TYPE sood-objlen,
l_file_type TYPE salv_bs_constant,
l_count TYPE so_obj_len, " string length of email body
l_count1 TYPE i,
w_line TYPE ty_line. "work area for data table
* Business Communication Service object
DATA: send_request TYPE REF TO cl_bcs.
* Wrapper Class for Office Documents
DATA: document TYPE REF TO cl_document_bcs.
* Object Represents an SAP User
DATA: sender TYPE REF TO cl_sapuser_bcs.
* Interface of Recipient Object in BCS
DATA: recipient TYPE REF TO if_recipient_bcs.
*BCS: General Exceptions
DATA: bcs_exception TYPE REF TO cx_bcs.
* Utility Class
DATA: lo_result_data TYPE REF TO cl_salv_ex_result_data_table.
* Data
DATA: lo_data TYPE REF TO data.
*Internal table declarations.
DATA: i_fldcat TYPE STANDARD TABLE OF lvc_s_fcat
INITIAL SIZE 0, "Field catalog
i_text TYPE bcsy_text, "report internal table
i_binary_content TYPE solix_tab,
i_att_head TYPE soli_tab,
i_obj_bin TYPE solix_tab, "Binary Internal Table
l_text_line TYPE soli,
l_filename TYPE string.
DATA: i_line TYPE STANDARD TABLE OF ty_line INITIAL SIZE 0.
* Field symbol declaration.
FIELD-SYMBOLS: <fs_fieldcat> TYPE lvc_s_fcat. "Field catalog
* Selection screen parameter
PARAMETERS: p_werks TYPE marc-werks OBLIGATORY.
INITIALIZATION.
p_werks = 'XXXX'. "initialize default plant
START-OF-SELECTION.
PERFORM main.
*---------------------------------------------------------------------*
* FORM main *
*---------------------------------------------------------------------*
FORM main.
* Data selection to be sent.
SELECT matnr "Material Number
mmsta "Plant-Specific Material Status
ekgrp "Purchasing Group
prctr "Profit Center
FROM marc
INTO TABLE i_line
WHERE werks = p_werks AND
lvorm = 'X'.
* Preare the fieldcat for output structure.
APPEND INITIAL LINE TO i_fldcat
ASSIGNING <fs_fieldcat>.
<fs_fieldcat>-no_out = ''. "Hide
<fs_fieldcat>-fieldname = 'MATNR'. "Fieldname
<fs_fieldcat>-outputlen = 18. "Output length
<fs_fieldcat>-dd_outlen = 18. "Input length
<fs_fieldcat>-reptext = 'Material Number'. "Column text
<fs_fieldcat>-edit = 'X'. "Edit
APPEND INITIAL LINE TO i_fldcat
ASSIGNING <fs_fieldcat>.
<fs_fieldcat>-no_out = ''. "Hide
<fs_fieldcat>-fieldname = 'MMSTA'. "Fieldname
<fs_fieldcat>-outputlen = 2. "Output length
<fs_fieldcat>-dd_outlen = 2. "Input length
<fs_fieldcat>-reptext = 'Plant-Specific mat.status'. "Column text
<fs_fieldcat>-edit = 'X'. "Edit
APPEND INITIAL LINE TO i_fldcat
ASSIGNING <fs_fieldcat>.
<fs_fieldcat>-no_out = ''. "Hide
<fs_fieldcat>-fieldname = 'EKGRP'. "Fieldname
<fs_fieldcat>-outputlen = 3. "Output length
<fs_fieldcat>-dd_outlen = 3. "Input length
<fs_fieldcat>-reptext = 'Purch.group'. "Column text
<fs_fieldcat>-edit = 'X'. "Edit
APPEND INITIAL LINE TO i_fldcat
ASSIGNING <fs_fieldcat>.
<fs_fieldcat>-no_out = ''. "Hide
<fs_fieldcat>-fieldname = 'PRCTR'. "Fieldname
<fs_fieldcat>-outputlen = 10. "Output length
<fs_fieldcat>-dd_outlen = 10. "Input length
<fs_fieldcat>-reptext = 'Profit center'. "Column text
<fs_fieldcat>-edit = 'X'. "Edit
TRY.
* -------- create persistent send request ------------------------
send_request = cl_bcs=>create_persistent( ).
APPEND 'List of materials having deletion flag at plant'(a01) TO i_text.
APPEND p_werks TO i_text.
l_count = 255.
* -------- create and set document with attachment ---------------
document = cl_document_bcs=>create_document(
i_type = 'RAW' " Type of data
i_text = i_text " Email body text
i_length = l_count " String length of email body
i_subject = 'Materials deleted in Plant' ).
* Create data object reference.
GET REFERENCE OF i_line INTO lo_data.
CLEAR: lo_result_data.
lo_result_data =
cl_salv_ex_util=>factory_result_data_table(
r_data = lo_data " internal table data reference
t_fieldcatalog = i_fldcat"field cat
).
* get the version from Abstract Super Class for All Transformations
CLEAR: l_version.
l_version = cl_salv_bs_a_xml_base=>get_version( ).
* Get the file Type
* value 10 for XLSX file type
CLEAR: l_file_type.
l_file_type = if_salv_bs_xml=>c_type_xlsx.
* Get the flavour export
* Flavor for Complete ALV XML
CLEAR: l_flavour.
l_flavour = if_salv_bs_c_tt=>c_tt_xml_flavour_export.
* Transformation of data to XSTRING
CLEAR: l_contents_line.
CALL METHOD cl_salv_bs_tt_util=>if_salv_bs_tt_util~transform
EXPORTING
xml_type = l_file_type
xml_version = l_version
r_result_data = lo_result_data
xml_flavour = l_flavour
gui_type = if_salv_bs_xml=>c_gui_type_gui
IMPORTING
xml = l_contents_line.
* Converting the table contents from xstring to binary
CLEAR i_obj_bin.
CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
EXPORTING
buffer = l_contents_line
IMPORTING
output_length = l_count1
TABLES
binary_tab = i_obj_bin.
APPEND LINES OF i_obj_bin TO i_binary_content.
* Four character file extension '.XLSX' is set
l_filename = 'Materialsdeleted.XLSX'. " provide the extension in file name
* You can set a file name with a freely selectable file name extension
* separately from the document description. For this, use the header table
* of the document or the attachment with the key word '&SO_FILENAME='.
CONCATENATE '&SO_FILENAME='
l_filename
INTO
l_text_line.
APPEND l_text_line TO i_att_head.
*Calculate the xstring length
l_i = xstrlen( l_contents_line ).
* Create the attachment reference.
CALL METHOD document->add_attachment
EXPORTING
i_attachment_type = 'BIN' " type of data
i_attachment_subject = 'File with deleted materials'
i_attachment_size = l_i " XTRING length of l_contents_line
i_att_content_hex = i_binary_content
i_attachment_header = i_att_head. "file details
* add document to send request
CALL METHOD send_request->set_document( document ).
* --------- set sender -------------------------------------------
* note: this is necessary only if you want to set the sender
* different from actual user (SY-UNAME). Otherwise sender is
* set automatically with actual user.
"Provide the SAP logon user name to sent the sender (this example user sy-uname)
* You can use uer name as ('VAK10567', etc)
sender = cl_sapuser_bcs=>create( sy-uname ).
CALL METHOD send_request->set_sender
EXPORTING
i_sender = sender.
* --------- add recipient (e-mail address) -----------------------
* create recipient - please replace e-mail address !!!
* you can create multiple receipient by following this way or
* you can provide undisclosed recipients list
recipient = cl_cam_address_bcs=>create_internet_address(
'xxx@yyy.com' ).
* add recipient with its respective attributes to send request
CALL METHOD send_request->add_recipient
EXPORTING
i_recipient = recipient
i_express = 'X'.
* ---------- send document ---------------------------------------
CALL METHOD send_request->send(
EXPORTING
i_with_error_screen = 'X'
RECEIVING
result = l_sent_to_all ).
IF l_sent_to_all = 'X'.
WRITE 'Document Sent Successfully'(098).
ENDIF.
COMMIT WORK.
* -----------------------------------------------------------
* * Exception Handling
* -----------------------------------------------------------
* * Replace this very rudimentary exception handling
* * With your own one !!!
* -----------------------------------------------------------
CATCH cx_bcs INTO bcs_exception.
WRITE: 'Error occured'(001).
WRITE: 'Error type'(002), bcs_exception->error_type.
EXIT.
ENDTRY.
ENDFORM. "main
如果您想知道类 zcl_itab_to_excel 的代码在哪里。在前面的文章中,我们已经介绍了如何在应用服务器上写入 excel 文件。
以下是代码,供快速参考:
CLASS zcl_itab_to_excel DEFINITION PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
METHODS:
itab_to_xstring
IMPORTING ir_data_ref TYPE REF TO data
RETURNING VALUE(rv_xstring) TYPE xstring.
ENDCLASS.
CLASS zcl_itab_to_excel IMPLEMENTATION.
METHOD itab_to_xstring.
FIELD-SYMBOLS: <fs_data> TYPE ANY TABLE.
CLEAR rv_xstring.
ASSIGN ir_data_ref->* TO <fs_data>.
TRY.
cl_salv_table=>factory(
IMPORTING r_salv_table = DATA(lo_table)
CHANGING t_table = <fs_data> ).
DATA(lt_fcat) =
cl_salv_controller_metadata=>get_lvc_fieldcatalog(
r_columns = lo_table->get_columns( )
r_aggregations = lo_table->get_aggregations( ) ).
DATA(lo_result) =
cl_salv_ex_util=>factory_result_data_table(
r_data = ir_data_ref
t_fieldcatalog = lt_fcat ).
cl_salv_bs_tt_util=>if_salv_bs_tt_util~transform(
EXPORTING
xml_type = if_salv_bs_xml=>c_type_xlsx
xml_version = cl_salv_bs_a_xml_base=>get_version( )
r_result_data = lo_result
xml_flavour = if_salv_bs_c_tt=>c_tt_xml_flavour_export
gui_type = if_salv_bs_xml=>c_gui_type_gui
IMPORTING
xml = rv_xstring ).
CATCH cx_root.
CLEAR rv_xstring.
ENDTRY.
ENDMETHOD.
ENDCLASS.
电子邮件中的事务码为 SOST。
同样的代码也可用于创建其他附件或不带附件的电子邮件,以及带抄送/密送的电子邮件。
ABAP 程序发送电子邮件(不带附件)
* Data Declarations
DATA: lt_mailsubject TYPE sodocchgi1.
DATA: lt_mailrecipients TYPE STANDARD TABLE OF somlrec90 WITH HEADER LINE.
DATA: lt_mailtxt TYPE STANDARD TABLE OF soli WITH HEADER LINE.
* Recipients
lt_mailrecipients-rec_type = 'U'.
lt_mailrecipients-receiver = 'someone@erpdb.info'.
APPEND lt_mailrecipients .
CLEAR lt_mailrecipients .
* Subject.
lt_mailsubject-obj_name = 'TEST'.
lt_mailsubject-obj_langu = sy-langu.
lt_mailsubject-obj_descr = 'Mail Subject'.
* Mail Contents
lt_mailtxt = 'This is a test mail'.
APPEND lt_mailtxt. CLEAR lt_mailtxt.
* Send Mail
CALL FUNCTION 'SO_NEW_DOCUMENT_SEND_API1'
EXPORTING
document_data = lt_mailsubject
TABLES
object_content = lt_mailtxt
receivers = lt_mailrecipients
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 EQ 0.
COMMIT WORK.
* Push mail out from SAP outbox
SUBMIT rsconn01 WITH mode = 'INT' AND RETURN.
ENDIF.
参考链接:SAP-Sending Mail With XLSX Attachments Using CL_DOCUMENT_BCS. (sapabapmadeeasy.blogspot.com)