原文链接:https://blog.csdn.net/sapliumeng/article/details/134152739
在SAP实施中,邮件发送功能在很多项目都会用到,而且往往是把内表以Excel或者CSV的格式发送附件,最好是这个表格也可以显示在正文中,这样的话如果数据行数比较少,就不需要打开附件了。
发送的邮件如下图所示:
以往这种需要都是每个程序单独写好长的代码,代码的工作量非常大,本文就是把功能都集成到几个子程序和函数中,大大减少了开发工作量。
程序特点:
1、支持发送到多个外部邮箱
2、支持发送到SAP账号(使用事务码SBWP看邮件)
3、可以选择是否紧急邮件
4、支持多个内表发送,表格和附件分别显示
5、附件压缩为ZIP文件
6、邮件表格界面友好美观
7、如果正文表格未显示所有内表行,则最后一行为省略号
示例代码:
*&---------------------------------------------------------------------*
*& Report ZCYCLE064
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zcycle064.
**** RFC 版发送邮件测试 START ********
*DATA: it_document_data TYPE sodocchgi1,
* it_content_text TYPE STANDARD TABLE OF solisti1 WITH HEADER LINE,
* it_packing_list TYPE TABLE OF sopcklsti1 WITH HEADER LINE,
* it_receivers TYPE STANDARD TABLE OF somlreci1 WITH HEADER LINE,
* lc_mail_attach TYPE string,
* lt_content_hex TYPE STANDARD TABLE OF solix WITH HEADER LINE,
* lt_object_header TYPE STANDARD TABLE OF solisti1 WITH HEADER LINE,
* lc_mail_xattach TYPE xstring,
* lv_send_all TYPE c,
* it_makt LIKE TABLE OF makt WITH HEADER LINE,
* fir_date TYPE sy-datum,
* mimetype TYPE char64.
*DATA: it_itab TYPE TABLE OF itab WITH HEADER LINE,
* wa_itab TYPE itab.
*
*CONSTANTS:lc_tab TYPE c VALUE cl_bcs_convert=>gc_tab, "excel换格符
* lc_ctrl TYPE c VALUE cl_bcs_convert=>gc_crlf. "excel换行符
*
*PARAMETER p_flag TYPE c AS CHECKBOX.
*
*IF p_flag = 'X'.
* PERFORM send_email.
*ENDIF.
*
**&---------------------------------------------------------------------*
**& Form SEND_EMAIL
**&---------------------------------------------------------------------*
** text
**----------------------------------------------------------------------*
*FORM send_email.
* DATA sy_vline TYPE i.
* DATA:mblnr TYPE string, "物料凭证
* matnr TYPE string, "物料
* mjahr TYPE string, "年度
* maktx TYPE string. "物料描述
*
* it_document_data-obj_descr = '邮件主题' . "内容的简短描述
* it_document_data-priority = '1'. "优先次序 1~9 1:最高优先权
* it_document_data-obj_name = 'OFFER'.
* it_document_data-obj_langu = sy-langu.
*
** ****邮件正文信息
* it_content_text = '各位好:'.
* APPEND it_content_text.
* it_content_text = ' 此邮件为测试邮件!!!!!!!'.
* APPEND it_content_text.
*
* DESCRIBE TABLE it_content_text LINES sy_vline.
* it_document_data-doc_size = 255 * ( sy_vline - 1 ) + strlen( it_content_text ). "SAPoffice 文档的大小(用于 API1)
*
* it_packing_list-transf_bin = space.
* it_packing_list-head_start = 1.
* it_packing_list-head_num = 0 .
* it_packing_list-body_num = sy_vline.
* it_packing_list-body_start = 1.
* it_packing_list-doc_type = 'RAW'.
* APPEND it_packing_list.
*
*
****收件人信息
* it_receivers-receiver = '1243327997@qq.com'. "收件人地址
* it_receivers-rec_type = 'U'.
* it_receivers-com_type = 'INT'.
* it_receivers-notif_del = 'X'.
* it_receivers-notif_ndel = 'X'.
* APPEND it_receivers.
*
* CONCATENATE '物料' lc_tab
* '物料凭证' lc_tab
* '物料描述' lc_tab
* '年度' lc_ctrl INTO lc_mail_attach. "lc_ctrl换行符
*
* CLEAR:mblnr, matnr, mjahr, maktx.
* mblnr = '7777777'.
* matnr = '7777777'.
* mjahr = '7777'.
* maktx = 'seven'."物料类型
*
* CONCATENATE lc_mail_attach
* matnr lc_tab
* mblnr lc_tab
* mjahr lc_tab
* maktx lc_ctrl INTO lc_mail_attach. "lc_ctrl换行符
*
* CLEAR:mblnr, matnr, mjahr, maktx.
* mblnr = '8888888'.
* matnr = '8888888'.
* mjahr = '8888'.
* maktx = 'seven'."物料类型
*
* CONCATENATE lc_mail_attach
* matnr lc_tab
* mblnr lc_tab
* mjahr lc_tab
* maktx lc_ctrl INTO lc_mail_attach. "lc_ctrl换行符
*
* mimetype = 'APPLICATION/MSEXCEL;CHARSET=UTF-16LE'.
* CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
* EXPORTING
* text = lc_mail_attach
* mimetype = mimetype
** ENCODING =
* IMPORTING
* buffer = lc_mail_xattach
* EXCEPTIONS
* failed = 1
* others = 2 .
*
* IF sy-subrc = 0.
* CONCATENATE cl_abap_char_utilities=>byte_order_mark_little lc_mail_xattach INTO lc_mail_xattach IN BYTE MODE.
* ENDIF.
*
* CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
* EXPORTING
* buffer = lc_mail_xattach
** APPEND_TO_TABLE = ' '
** IMPORTING
** OUTPUT_LENGTH =
* TABLES
* binary_tab = lt_content_hex.
*
*"不知道干啥用的
* lt_object_header = 'Seven test'.
* APPEND lt_object_header.
*
* DESCRIBE TABLE lt_content_hex LINES sy_vline.
*
* it_packing_list-transf_bin = 'X'.
* it_packing_list-head_start = 1 .
* it_packing_list-head_num = 0 .
* it_packing_list-body_start = 1.
* it_packing_list-body_num = sy_vline.
* it_packing_list-doc_type = 'XLS'.
* it_packing_list-doc_size = 255 * sy_vline.
* it_packing_list-obj_name = '附件名'.
* it_packing_list-obj_descr = it_packing_list-obj_name.
* APPEND it_packing_list.
*
*
*"方法1 无法指定发送人邮箱
******** CALL FUNCTION 'SO_NEW_DOCUMENT_ATT_SEND_API1'
******** EXPORTING
******** document_data = it_document_data
******** put_in_outbox = 'X'
******** commit_work = 'X'
******** IMPORTING
******** sent_to_all = lv_send_all
********* NEW_OBJECT_ID =
******** TABLES
******** packing_list = it_packing_list[]
******** object_header = lt_object_header[]
********* contents_bin =
******** contents_txt = it_content_text[]
******** contents_hex = lt_content_hex[]
********* object_para =
********* object_parb =
******** receivers = it_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 .
*
*"方法2 可以指定发送人邮箱
* CALL FUNCTION 'SO_DOCUMENT_SEND_API1'
* EXPORTING
* document_data = it_document_data
* put_in_outbox = 'X'
* sender_address = 'lei.cao@lifotronic.com' "发件人邮箱
* sender_address_type = 'INT'
* commit_work = 'X'
** IP_ENCRYPT =
** IP_SIGN =
** IV_VSI_PROFILE =
* IMPORTING
* sent_to_all = lv_send_all
** NEW_OBJECT_ID =
** SENDER_ID =
* TABLES
* packing_list = it_packing_list[]
* object_header = lt_object_header[]
** CONTENTS_BIN =
* contents_txt = it_content_text[]
* contents_hex = lt_content_hex[]
** OBJECT_PARA =
** OBJECT_PARB =
* receivers = it_receivers[]
** ET_VSI_ERROR =
* 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.
** Implement suitable error handling here
* ELSE.
* SUBMIT RSCONN01 WITH MODE = 'INT'
* WITH OUTPUT = 'X'
* AND RETURN.
* ENDIF.
*
*ENDFORM. "SEND_EMAIL
**** RFC 版发送邮件测试 END ************ OO 版发送邮件测试 START ********************
TABLES adr6.
DATA: BEGIN OF gt_out OCCURS 0,bukrs TYPE t001-bukrs,butxt TYPE t001-butxt,ort01 TYPE t001-ort01,land1 TYPE t001-land1,waers TYPE t001-waers,spras TYPE t001-spras,END OF gt_out.SELECT-OPTIONS s_smtp FOR adr6-smtp_addr NO INTERVALS OBLIGATORY.
PARAMETERS p_subj TYPE so_obj_des DEFAULT '发送邮件测试'.AT SELECTION-SCREEN OUTPUT.%_s_smtp_%_app_%-text = '接收邮箱'.%_p_subj_%_app_%-text = '邮件主题'.START-OF-SELECTION.SELECT * INTO CORRESPONDING FIELDS OF TABLE gt_out FROM t001.PERFORM sendmail.MESSAGE s000(oo) WITH 'Done'.*&---------------------------------------------------------------------*
*& sendmail
*&---------------------------------------------------------------------*
FORM sendmail.DATA lv_string TYPE string.DATA lv_csvxstr TYPE xstring.DATA lv_binlen TYPE i.DATA lt_html TYPE TABLE OF w3html WITH HEADER LINE.DATA lt_smtp TYPE TABLE OF piqapp_email WITH HEADER LINE.DATA lt_atta TYPE wlftt_mail_attachment WITH HEADER LINE.***邮件内容文本APPEND 'TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST<br/>' TO lt_html.APPEND 'TEST TEST TEST TEST TEST TEST TEST TEST <br/>' TO lt_html.APPEND 'TEST TEST TEST TEST <br/><br/>' TO lt_html.***下面显示表格,如果有多个内表需要发送,重复下面4个步骤即可SELECT * INTO CORRESPONDING FIELDS OF TABLE gt_out FROM t001.
***内表转为CSV文件PERFORM itab_to_csvTABLES gt_outUSING '公司代码,名称,城市,国家,货币,语言' "CSV文件的标题CHANGING lv_string lv_csvxstr.***压缩CSV文件PERFORM xstr2zipxstrUSING 'BUKRS.XLS' lv_csvxstrCHANGING lv_csvxstr.***压缩文件作为附件CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'EXPORTINGbuffer = lv_csvxstrIMPORTINGoutput_length = lv_binlenTABLESbinary_tab = lt_atta-binary_content.lt_atta-description = 'BUKRS.zip'.lt_atta-binary_size = lv_binlen.APPEND lt_atta.***内表的前N条以表格的形式显示在邮件正文中PERFORM itab_to_mail_bodyTABLES gt_out lt_htmlUSING '公司代码列表:' "表格上面文本'公司代码,名称,城市,国家,货币,语言' "表格标题'XXXXXX' "要显示的列,按照顺序,如果显示为X,不显示为空格'10'. "显示内表前N行,如果内表大于N行则最后一行显示省略号***接收邮箱LOOP AT s_smtp.APPEND s_smtp-low TO lt_smtp.ENDLOOP.***调用发送函数CALL FUNCTION 'ZPUB_SEND_MAIL'EXPORTINGsubject = p_subjcommit = 'X'atta_tab = lt_atta[]TABLESmail_body = lt_htmlrecv_smtp = lt_smtp.
ENDFORM.*&---------------------------------------------------------------------*
*& 内表转为CSV文件
*&---------------------------------------------------------------------*
FORM itab_to_csv TABLES t_intab USING pv_headerCHANGING cv_str cv_utf8x.DATA: lo_csv TYPE REF TO cl_rsda_csv_converter.DATA: lv_str TYPE char2048.CALL METHOD cl_rsda_csv_converter=>createRECEIVINGr_r_conv = lo_csv.IF pv_header IS NOT INITIAL.cv_str = pv_header && %_cr_lf.ENDIF.LOOP AT t_intab.CALL METHOD lo_csv->structure_to_csvEXPORTINGi_s_data = t_intabIMPORTINGe_data = lv_str.cv_str = cv_str && lv_str && %_cr_lf.ENDLOOP.CALL FUNCTION 'SCMS_STRING_TO_XSTRING'EXPORTINGtext = cv_strmimetype = 'UTF8'IMPORTINGbuffer = cv_utf8xEXCEPTIONSfailed = 1OTHERS = 2.IF sy-subrc = 0.cv_utf8x = cl_abap_char_utilities=>byte_order_mark_utf8 && cv_utf8x.ENDIF.
ENDFORM.*&---------------------------------------------------------------------*
*& XSTRING压缩为ZIP文件XSTRING
*&---------------------------------------------------------------------*
FORM xstr2zipxstr USING pv_filename pv_xstr CHANGING cv_zipxstr.DATA: lo_zip TYPE REF TO cl_abap_zip.DATA: lv_str TYPE string.lv_str = pv_filename.CREATE OBJECT lo_zip.CALL METHOD lo_zip->addEXPORTINGname = lv_strcontent = pv_xstr.CALL METHOD lo_zip->saveRECEIVINGzip = cv_zipxstr.
ENDFORM.*&---------------------------------------------------------------------*
*& 内表写到邮件表格
*&---------------------------------------------------------------------*
FORM itab_to_mail_body TABLES t_intab t_contents STRUCTURE solisti1USING pv_text pv_coldesc pv_mask pv_toline.DATA: lt_conts TYPE TABLE OF solisti1 WITH HEADER LINE,lt_title TYPE TABLE OF char40 WITH HEADER LINE.DATA: subrc TYPE sy-subrc,index TYPE sy-index,charc TYPE char2048,charstr TYPE string,lmask TYPE char200,omitnum TYPE i,ftype .FIELD-SYMBOLS <fs_fld> .CHECK t_intab[] IS NOT INITIAL.SPLIT pv_coldesc AT ',' INTO TABLE lt_title.lmask = pv_mask.APPEND pv_text TO lt_conts.APPEND:`<style type="text/css">.solid{BORDER-TOP: 1px solid;` TO lt_conts,`BORDER-RIGHT:1px solid;BORDER-BOTTOM: 1px solid; ` TO lt_conts,`BORDER-LEFT: 1px solid}</style><table border=1 ` TO lt_conts,`cellpadding=2 style='border-collapse:collapse;font-` TO lt_conts,`size:10.5pt'><tbody><tr style="background:#DDD9C4;">` TO lt_conts.LOOP AT lt_title.APPEND |<td class="solid">{ lt_title }</td>| TO lt_conts.ENDLOOP.APPEND `</tr>` TO lt_conts.LOOP AT t_intab FROM 0 TO pv_toline.APPEND '<tr>' TO lt_conts.CLEAR omitnum.DO.index = sy-index - 1.ASSIGN COMPONENT sy-index OF STRUCTURE t_intab TO <fs_fld>.IF sy-subrc <> 0.EXIT.ENDIF.CHECK lmask+index(1) = 'X' OR lmask = ''.omitnum = omitnum + 1.DESCRIBE FIELD <fs_fld> TYPE ftype.CASE ftype.WHEN 'I' OR 'P' OR 'F' OR 'a' OR 'e' OR 'b' OR 's'.charc = abs( <fs_fld> ).CONDENSE charc NO-GAPS.IF <fs_fld> < 0.CONCATENATE '-' charc INTO charc.ENDIF.charstr = charc.WHEN 'D' OR 'T'.IF <fs_fld> IS INITIAL OR <fs_fld> = ''.charc = ''.ELSE.WRITE <fs_fld> TO charc .ENDIF.charstr = charc.WHEN 'X' OR 'y' OR 'g'.charstr = <fs_fld> .WHEN OTHERS.WRITE <fs_fld> TO charc .charstr = charc.ENDCASE.APPEND |<td class="solid">{ charstr }</td>| TO lt_conts.ENDDO.APPEND `</tr>` TO lt_conts.ENDLOOP.IF lines( t_intab ) > pv_toline.APPEND '<tr>' TO lt_conts.DO omitnum TIMES.APPEND |<td class="solid">...</td>| TO lt_conts.ENDDO.APPEND '</tr>' TO lt_conts.ENDIF.APPEND '</tbody></table> <br/> ' TO lt_conts.APPEND LINES OF lt_conts TO t_contents.
ENDFORM.
**** OO 版发送邮件测试 END ********************
发送函数 ZPUB_SEND_MAIL:
源代码:
FUNCTION zpub_send_mail.
*"----------------------------------------------------------------------
*"*"本地接口:
*" IMPORTING
*" REFERENCE(SUBJECT) TYPE SO_OBJ_DES
*" REFERENCE(SENDER) TYPE AD_SMTPADR OPTIONAL
*" REFERENCE(EXPRESS) TYPE OS_BOOLEAN OPTIONAL
*" REFERENCE(COMMIT) TYPE CHAR1 OPTIONAL
*" REFERENCE(ATTA_TAB) TYPE WLFTT_MAIL_ATTACHMENT OPTIONAL
*" EXPORTING
*" REFERENCE(RTYPE) TYPE BAPI_MTYPE
*" REFERENCE(RTMSG) TYPE BAPI_MSG
*" TABLES
*" MAIL_BODY STRUCTURE SOLISTI1 OPTIONAL
*" RECV_USER STRUCTURE SSCRUSER OPTIONAL
*" RECV_SMTP STRUCTURE PIQAPP_EMAIL OPTIONAL
*"----------------------------------------------------------------------DATA lr_email TYPE REF TO cl_bcs.DATA lr_body TYPE REF TO cl_document_bcs.DATA lr_sender TYPE REF TO if_sender_bcs.DATA lr_recver TYPE REF TO if_recipient_bcs.DATA lr_cxbcs TYPE REF TO cx_bcs.DATA ls_atta TYPE wlfs_mail_attachment.DATA lv_result TYPE os_boolean.TRY.lr_email = cl_bcs=>create_persistent( ).lr_body = cl_document_bcs=>create_document( i_type = 'HTM'i_text = mail_body[]i_subject = subject ).LOOP AT atta_tab INTO ls_atta.CALL METHOD lr_body->add_attachmentEXPORTINGi_attachment_type = ls_atta-typei_attachment_subject = ls_atta-descriptioni_attachment_size = ls_atta-binary_sizei_att_content_hex = ls_atta-binary_content.ENDLOOP.lr_email->set_document( lr_body ).IF sender IS INITIAL.lr_sender = cl_sapuser_bcs=>create( sy-uname ).ELSE.CALL METHOD cl_cam_address_bcs=>create_internet_addressEXPORTINGi_address_string = senderi_address_name = 'Sender'RECEIVINGresult = lr_sender.ENDIF.lr_email->set_sender( lr_sender ).LOOP AT recv_user.lr_recver = cl_sapuser_bcs=>create( recv_user-uname ).lr_email->add_recipient( i_recipient = lr_recver i_express = express ).ENDLOOP.LOOP AT recv_smtp.lr_recver = cl_cam_address_bcs=>create_internet_address( recv_smtp-e_mail ).lr_email->add_recipient( i_recipient = lr_recver i_express = express ).ENDLOOP.lr_email->set_send_immediately( 'X' ).lv_result = lr_email->send( i_with_error_screen = '' ).IF lv_result = 'X'.IF commit IS NOT INITIAL.COMMIT WORK. "在Update进程或者增强里面,禁止提交ENDIF.ENDIF.CATCH cx_bcs INTO lr_cxbcs. " cx_root INTO lr_cxroot.rtype = 'E'.rtmsg = lr_cxbcs->get_text( ).ENDTRY.ENDFUNCTION.