在SAP实施中,邮件发送功能在很多项目都会用到,而且往往是把内表以Excel或者CSV的格式发送附件,最好是这个表格也可以显示在正文中,这样的话如果数据行数比较少,就不需要打开附件了。
发送的邮件如下图所示:
以往这种需要都是每个程序单独写好长的代码,代码的工作量非常大,本文就是把功能都集成到几个子程序和函数中,大大减少了开发工作量。
程序特点:
1、支持发送到多个外部邮箱
2、支持发送到SAP账号(使用事务码SBWP看邮件)
3、可以选择是否紧急邮件
4、支持多个内表发送,表格和附件分别显示
5、附件压缩为ZIP文件
6、邮件表格界面友好美观
7、如果正文表格未显示所有内表行,则最后一行为省略号
示例代码:
REPORT zsenmail NO STANDARD PAGE HEADING.
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个步骤即可
***内表转为CSV文件
PERFORM itab_to_csv IN PROGRAM zrpubform
TABLES gt_out
USING '公司代码,名称,城市,国家,货币,语言' "CSV文件的标题
CHANGING lv_string lv_csvxstr.
***压缩CSV文件
PERFORM xstr2zipxstr IN PROGRAM zrpubform
USING 'BUKRS.XLS' lv_csvxstr
CHANGING lv_csvxstr.
***压缩文件作为附件
CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
EXPORTING
buffer = lv_csvxstr
IMPORTING
output_length = lv_binlen
TABLES
binary_tab = lt_atta-binary_content.
lt_atta-description = 'BUKRS.zip'.
lt_atta-binary_size = lv_binlen.
APPEND lt_atta.
***内表的前N条以表格的形式显示在邮件正文中
PERFORM itab_to_mail_body IN PROGRAM zrpubform
TABLES gt_out lt_html
USING '公司代码列表:' "表格上面文本
'公司代码,名称,城市,国家,货币,语言' "表格标题
'XXXXXX' "要显示的列,按照顺序,如果显示为X,不显示为空格
'10'. "显示内表前N行,如果内表大于N行则最后一行显示省略号
***接收邮箱
LOOP AT s_smtp.
APPEND s_smtp-low TO lt_smtp.
ENDLOOP.
***调用发送函数
CALL FUNCTION 'ZPUB_SEND_MAIL'
EXPORTING
subject = p_subj
commit = 'X'
atta_tab = lt_atta[]
TABLES
mail_body = lt_html
recv_smtp = lt_smtp.
ENDFORM.
几个子程序如下:
*&---------------------------------------------------------------------*
*& 内表转为CSV文件
*&---------------------------------------------------------------------*
FORM itab_to_csv TABLES t_intab USING pv_header
CHANGING 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=>create
RECEIVING
r_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_csv
EXPORTING
i_s_data = t_intab
IMPORTING
e_data = lv_str.
cv_str = cv_str && lv_str && %_cr_lf.
ENDLOOP.
CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
EXPORTING
text = cv_str
mimetype = 'UTF8'
IMPORTING
buffer = cv_utf8x
EXCEPTIONS
failed = 1
OTHERS = 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->add
EXPORTING
name = lv_str
content = pv_xstr.
CALL METHOD lo_zip->save
RECEIVING
zip = cv_zipxstr.
ENDFORM.
*&---------------------------------------------------------------------*
*& 内表写到邮件表格
*&---------------------------------------------------------------------*
FORM itab_to_mail_body TABLES t_intab t_contents STRUCTURE solisti1
USING 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.
发送函数:
FUNCTION zpub_send_mail.
*"----------------------------------------------------------------------
*"*"本地接口:
*" IMPORTING
*" VALUE(SUBJECT) TYPE SO_OBJ_DES
*" VALUE(SENDER) TYPE AD_SMTPADR OPTIONAL
*" VALUE(EXPRESS) TYPE OS_BOOLEAN OPTIONAL
*" VALUE(COMMIT) TYPE CHAR1 OPTIONAL
*" VALUE(ATTA_TAB) TYPE WLFTT_MAIL_ATTACHMENT OPTIONAL
*" EXPORTING
*" VALUE(RTYPE) TYPE BAPI_MTYPE
*" VALUE(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_attachment
EXPORTING
i_attachment_type = ls_atta-type
i_attachment_subject = ls_atta-description
i_attachment_size = ls_atta-binary_size
i_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_address
EXPORTING
i_address_string = sender
i_address_name = 'Sender'
RECEIVING
result = 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.