目录
1.前言
2.介绍
3.正文
3.1自开发邮件发送工具类的使用
3.2邮件模板上传及调用
3.2.1 SO10上传邮件模板
3.2.2 SMW0上传html模板
3.2.3 SE80->Email Template创建邮件模板
4.模板中图片的替换
4.1 直接指定图片Base64编码
4.2 使用SMW0上传图片
4.3 使用SO2_MIME_REPOSITORY上传图片
5.Smartforms转PDF并添加为邮件附件
5.1 PDF合并功能
6.ALV转换为PDF并添加为邮件附件
7.框架源码及表结构信息
8.SE38 Demo程序源码
总结这边文章起因是近期碰到需要使用ABAP给客户发送邮件功能,需求只是简单的发送邮件并且将明细内容以表格形式置于邮件正文中,之前只是知道大概怎么发送邮件,没有自己完整的从头写过,所以借着这个机会把发送邮件这部分能想到的需求全部进行集中测试实现,以后就不用再到处搜了。
发送邮件的API有很多种,但是SAP早在note190669中就提到,推荐使用CL_BCS来进行邮件发送,BCS(Business Communication Service)接口提供了一种舒适的、基于类的方法来发送文档,比起API1接口,更易使用,参数更加清晰和容易理解,也不在需要填充让人难以理解的装箱单参数,此外,CL_BCS还提供了更多选项。
比较旧的功能模块:
SAP针对于CL_BCS提供了以下示例程序可供参考,这些程序是模板程序,不能直接执行,因为有些内容是硬编码的:
基于平时开发习惯,我将邮件功能调用的部分基于CL_BCS封装成了一个自开发工具类,将一些通用功能进行封装,可以使代码调用时,可以减少重复的代码量,基于该封装类我同时创建了一份参考代码,其中包括以下功能:
在实现这些功能的过程中,或多或少都碰到了一些问题,在后文中我会将解决方式详细补充。
Demo程序效果:
以下代码截图为封装的工具类的部分源码,完整源码会在最下面附上。
实例化邮件对象:
* create instance of CL_BCS
lo_send_request = cl_bcs=>create_persistent( ).
设置发件人:
* Set sender email address
lo_mail_from = cl_cam_address_bcs=>create_internet_address( iv_mail_from_address ).
lo_send_request->set_sender( lo_mail_from ).
设置收件人及立即发送:
* Set receiver email address
LOOP AT it_mail_to_address INTO DATA(ls_mail_to_address).
lo_mail_to = cl_cam_address_bcs=>create_internet_address( ls_mail_to_address ).
* Send immediately
lo_send_request->set_send_immediately( i_send_immediately = abap_true ).
* Set address
lo_send_request->add_recipient( i_recipient = lo_mail_to
i_express = abap_true ).
ENDLOOP.
设置抄送人及立即发送,i_copy 参数指定为'X'即可:
* Set CC email address
LOOP AT it_mail_cc_address INTO DATA(ls_mail_cc_address).
lo_mail_cc = cl_cam_address_bcs=>create_internet_address( ls_mail_cc_address ).
* Send immediately
lo_send_request->set_send_immediately( i_send_immediately = abap_true ).
* Set address
lo_send_request->add_recipient( i_recipient = lo_mail_cc
i_copy = abap_true
i_express = abap_true ).
ENDLOOP.
文本类型正文,i_type 类型可以是 'RAW','TXT' 等:
lt_mail_body = ls_body_in-body_tline-tline.
* Create mail body document object
lo_document = cl_document_bcs=>create_document(
i_type = ls_body_in-body_tline-type
i_text = lt_mail_body
i_subject = iv_title ).
HTML类型正文,i_type 类型为 'HTM':
* Convert string to solitab
lt_mail_body = cl_bcs_convert=>string_to_soli(
EXPORTING
iv_string = ls_body_in-body_html-html
).
* Create mail body document object
lo_document = cl_document_bcs=>create_document(
i_type = ls_body_in-body_html-type
i_text = lt_mail_body
i_subject = iv_title ).
SE80创建的邮件模板内容动态替换:
* Standard Template ->SE80->Email Template
IF ls_body_in-body_template IS NOT INITIAL.
CLEAR:
ls_body_in-body_tline,
ls_body_in-body_html,
ls_body_in-body_temp_smw0.
* Build document object with template
build_document_with_template(
EXPORTING
is_body_temp = ls_body_in-body_template
IMPORTING
eo_document = lo_document
es_return = es_return
).
CHECK es_return-type <> gc_type_e.
ENDIF.
SMW0邮件模板内容动态替换:
* Template ->SMW0
IF ls_body_in-body_temp_smw0 IS NOT INITIAL.
CLEAR:
ls_body_in-body_tline,
ls_body_in-body_html,
ls_body_in-body_template.
* Build document object with template
build_document_with_temp_smw0(
EXPORTING
is_body_temp = ls_body_in-body_temp_smw0
IMPORTING
eo_document = lo_document
es_return = es_return
).
CHECK es_return-type <> gc_type_e.
ENDIF.
添加邮件附件:
* Add attachment
IF it_attachment IS NOT INITIAL.
LOOP AT it_attachment INTO DATA(ls_attachment).
lo_document->add_attachment( i_attachment_type = ls_attachment-type
i_attachment_subject = ls_attachment-att_name
i_attachment_size = ls_attachment-size
i_att_content_hex = ls_attachment-body_content ).
ENDLOOP.
ENDIF.
构建邮件主体及邮件发送:
* Binding mail body
lo_send_request->set_document( lo_document ).
* Send mail
lv_result = lo_send_request->send( i_with_error_screen = abap_true ).
获取邮件UUID,用于检索SOST中的状态:
* Get UUID
lv_oid = lo_send_request->oid( ).
根据UUID检索邮件状态,因为CL_BCS类只负责发起邮件传输请求,无法立刻获取邮件的状态信息,虽然有函数 SX_SNDREC_SELECT 可以获取SOST的列表信息,但是该函数不能抓取到具体某一条记录,所以直接从底表抓取。(SAP发送邮件只负责将邮件推送至邮件服务器,然后再由邮件服务器发给收件人,至于收件人有没有收到该邮件,只有邮件服务器知道,SAP并不会接收到该反馈,所以SOST中状态成功只表明邮件已成功推送至邮件服务器)
此处使用时间戳来替代wait up to ** seconds的写法,使其只需要等待他真正所需要的时间,不需要浪费任何零点几秒,或者零点零几秒。
IF lv_result = abap_true.
COMMIT WORK AND WAIT.
GET TIME STAMP FIELD ls_time-start.
WHILE ls_time-elapsed < ls_time-limit.
* Get mail send status in SOST
SELECT SINGLE
a~objtp,
a~objyr,
a~objno,
a~fortp,
a~foryr,
a~forno,
a~rectp,
a~recyr,
a~recno,
a~sndreq,
b~status,
b~msgid,
b~msgty,
b~msgv1,
b~msgv2,
b~msgv3,
b~msgv4
INTO @DATA(ls_mail_status)
FROM soos AS a
INNER JOIN soes AS b
ON a~rectp = b~rectp
AND a~recyr = b~recyr
AND a~recno = b~recno
WHERE a~sndreq = @lv_oid.
IF ls_mail_status-msgid IS NOT INITIAL.
EXIT.
ENDIF.
GET TIME STAMP FIELD ls_time-now.
ls_time-elapsed = cl_abap_tstmp=>subtract(
tstmp1 = ls_time-now
tstmp2 = ls_time-start
).
ENDWHILE.
IF ls_mail_status-status <> gc_success_status.
es_return-type = ls_mail_status-msgty.
lv_msgno = ls_mail_status-status.
CALL FUNCTION 'BAPI_MESSAGE_GETDETAIL'
EXPORTING
id = ls_mail_status-msgid
number = lv_msgno
textformat = gc_textformat
message_v1 = ls_mail_status-msgv1
message_v2 = ls_mail_status-msgv2
message_v3 = ls_mail_status-msgv3
message_v4 = ls_mail_status-msgv4
IMPORTING
message = es_return-message.
ELSE.
es_return-type = gc_type_s.
es_return-message = 'Mail send success.'(002).
ENDIF.
ELSE.
ROLLBACK WORK.
es_return-type = gc_type_e.
es_return-message = 'Mail send failed, Please use tcode SOST to check detail.'(003).
ENDIF.
具体实现细节可以阅读底部源码,下面只介绍其中一些功能的实现过程。
SAP中目前我了解到的有以下三种方式来创建邮件模板:
跟长文本一样的形式,通过READ_TEXT获取到长文本后,对某些变量进行替换,来构建正文内容,其实也可以直接维护一段html进去,在运行时替换到里面的某些标记字符,有些项目对邮件内容格式没有太多要求,且只有文本内容时,会选择此方式进行邮件模板的维护。
事实上SO10似乎还支持上传一些具有富文本格式的RTF文件作为模板,配合READ_TEXT 和 CONVERT_ITF_TO_STREAM_TEXT 可以得到具有格式的邮件内容,不过我没有对此过多研究,使用下面两种方式可以更简单的创建具体格式的邮件模板。
事先通过Vscode或者一些在线html编辑工具,构建好自己想要的效果的html文件,将其保存到本地,并通过SMW0上传,我这里用了一个在线网站去编写了html代码,因为可以即时生成预览画面,方便调整。
在模板中预留了一些占位符,在后续传值时会被程序传入的内容动态替换掉。
调用方式:
key-objid = is_body_temp-id.
IMPORT html TO lt_html_table FROM DATABASE wwwdata(ht) ID key.
IF sy-subrc <> 0.
* Object &1 does not exist in Web Repository
MESSAGE s000(swww) WITH is_body_temp-id INTO es_return-message.
es_return-type = gc_type_e.
RETURN.
ENDIF.
lv_html_string = cl_bcs_convert=>txt_to_string( EXPORTING it_soli = lt_html_table ).
LOOP AT is_body_temp-replace_info INTO DATA(ls_repace_info).
REPLACE ALL OCCURRENCES OF ls_repace_info-mark_field
IN lv_html_string
WITH cl_bcs_convert=>txt_to_string( EXPORTING it_soli = ls_repace_info-body_html ).
ENDLOOP.
lt_html_table = cl_bcs_convert=>string_to_soli( EXPORTING iv_string = lv_html_string ).
DATA(lo_multipart) = NEW cl_gbt_multirelated_service( ).
lo_multipart->set_main_html(
EXPORTING
content = lt_html_table
).
先从 WWWDATA 表中取出html数据,转换为string后,根据传入的标记字段名mark_field去替换对应的内容,本来SAP提供了一个替换SMW0模板内容的函数 WWW_HTML_MERGER,但是该函数有个bug,由于他返回的html是CHAR255的表类型,而函数中替换逻辑是循环这个表去根据传入的内容进行替换,这就有可能会有两个问题:
问题1:有可能解析出来模板里的标记字段刚好被分隔到了两行中,这样就无法检索到这个标记字段进行替换。
....... ......
问题2:有可能我要替换的内容超过了255个长度,那么就会导致内容丢失。
Document ............
所以需要将html表转换为string类型后,再依次去替换内容。
3.2.3 SE80->Email Template创建邮件模板
以下是Email Template的一些特性:
1.可以关联CDS VIEW,使用CDS VIEW可以在调用时通过传入CDS KEY,来自动填充通过 {{}}包裹的字段变量,包括标题和正文,如上图中的{{banfn}},注意区分大小写,适合正文中只需要单条数据进行填充的邮件模板,因为框架源码中使用的是SELECT SINGLE来获取的CDS VIEW数据,此时代码中只需传入发件人,收件人,抄送人,CDS KEY即可生成邮件并发送,不需要额外代码。
2.支持多语言版本,调用时可以传入指定语言和默认语言,当指定语言版本的模板不存在时,会以默认语言版本生成邮件内容。
3.可以直接进行内容预览,点击Preview按钮即可直接查看html预览画面,方便修正一些信息。
4.支持在右侧编辑区域构建html及纯文本格式的邮件内容,可以附加一些字体及样式等控制(最好使用内联方式指定样式,因为很多邮箱产品基于各种因素会对邮件内容进行截取,很多时候
标签之外的内容都会截取,所以style声明的一些样式控制在某些邮箱中可能不会生效)。
5.该应用在Fiori中比起SO10有更好的界面。
创建CDS:
普通CDS创建完成后填入邮件模板会报下面这个错误:
在CDS VIEW的属性中,进行发布后就可以消除这个提示:
创建Email Template内容:
除了手动编写,Vscode或者在线网站编写html外,还有一种方式也可以快速的生成html,借助word工具,将邮件需要内容填写好,包括字体样式颜色等,直接另存为.html格式,好处是借助这种方式生成的html的样式控制都是内联方式的,可以直接上传到邮件模板中去,不好的地方是,转换的html内容非常长,包含了一些无用信息。
同SMW0上传的模板一样,有些CDS VIEW不能获取的信息,html中仍需要留下标记字段,在代码中进行替换:
调用方式:
① 根据模板ID(SE80创建的模板名)获取模板对象实例。
② CDS KEY赋值,例:
name
value
BANFN
0010000129
③ 根据指定的模板语言及CDS KEY获取替换后内容的html内容及邮件标题。
④ 根据传入的替换信息,替换html模板中仍未填充的动态变量,例:
mark_field
body_html
MrMeng
物料A 12348523 ...
⑤ 将String类型html转换为类需要的类型。
⑥ 将最终完整的信息进行绑定。
4.模板中图片的替换
邮件正文中的图片可以有三种方式进行替换:
4.1 直接指定图片Base64编码
直接在src中指定图片的Base64编码,但是通常图片的Base64编码会非常长,会让你的html充满大量的字符,会显得很臃肿,如果某些图片是固定的,也可以使用这种方式去创建模板。
4.2 使用SMW0上传图片
需要注意的是,如果系统中没有分配图片类型对应的MIME TYPE,创建的时候需要注意,TYPE不能只填png,需要填写完整的类型名称 image/png,因为后续函数获取图片信息时,有一处硬编码,只填写png时会引发系统dump。
获取图片信息:
DATA:
lt_query TYPE STANDARD TABLE OF w3query,
ls_query TYPE w3query,
lt_html TYPE STANDARD TABLE OF w3html,
lv_length TYPE w3param-cont_len,
lv_return_code TYPE w3param-ret_code.
CHECK iv_smw0_name IS NOT INITIAL.
ls_query-name = gc_object_id.
ls_query-value = iv_smw0_name.
APPEND ls_query TO lt_query.
* Get content from SMW0
* This function is obsolete,MIME Repository is recommended
CALL FUNCTION 'WWW_GET_MIME_OBJECT'
TABLES
query_string = lt_query
html = lt_html
mime = et_solix
CHANGING
return_code = lv_return_code
content_type = ev_type
content_length = lv_length
EXCEPTIONS
object_not_found = 1
parameter_not_found = 2
OTHERS = 3.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
ev_length = lv_length.
Tips:该函数调用时会提示函数已弃用,所以不是很建议用这种方式。
替换模板中图片:
① 获取实例
② 将替换完毕的正文内容进行绑定
③ 获取图片信息
④ 绑定图片信息
⑤ 根据绑定了正文及图片信息的对象生成最终完整的邮件对象
4.3 使用SO2_MIME_REPOSITORY上传图片
使用事务代码 SO2_MIME_REPOSITORY 上传图片,或者从以下入口进入MIME Repository。
关于MIME Repository的更多信息,可以阅读Jerry老师的这篇文章。
SAP ABAP MIME Repository 和 API 介绍https://blog.csdn.net/i042416/article/details/129785805?ops_request_misc=&request_id=c36bf275b8ae432e9b36e6ae3486f0d4&biz_id=&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~koosearch~default-1-129785805-null-null.268%5Ev1%5Econtrol&utm_term=MIME%20&spm=1018.2226.3001.4450 本例中我没有上传个人的图片,发现有现有的图片可以测试用,该图片在路径/SAP/PUBLIC下。
获取图片信息:
DATA:
lo_mr_api TYPE REF TO if_mr_api,
lv_content TYPE xstring.
CHECK iv_mime_path IS NOT INITIAL.
lo_mr_api = cl_mime_repository_api=>get_api( ).
lo_mr_api->get(
EXPORTING
i_url = iv_mime_path
IMPORTING
e_content = lv_content
e_mime_type = ev_type
).
et_solix = cl_bcs_convert=>xstring_to_solix( EXPORTING iv_xstring = lv_content ).
对于邮件中内容格式的各种转换,SAP提供了一个工具类,提供了丰富的内容格式转换方法,使用该工具类,基本可以完成使用过程中任意格式之间的转换。
替换模板中的图片:
5.Smartforms转PDF并添加为邮件附件
主要参数为以下三个参数:
no_dialog: 保证不显示弹窗
tdnewid: 设置创建假脱机请求
user_settings:置空,保证上面两个参数生效
调用CONVERT_OTFSPOOLJOB_2_PDF将打印池中的信息转换为PDF。
SAP标准参考程序:RSTXPDFT4。
5.1 PDF合并功能:
SAP提供了工具类CL_RSPO_PDF_MERGE,可以便捷的实现将多个PDF合并为同一个PDF。
SAP标准参考程序:RSPO_TEST_MERGE_PDF_FILES。
6.ALV转换为PDF并添加为邮件附件
主要问题点有以下三点:
PRINT = 'X' :保证ALV不显示,只作为后台打印。
GET_PRINT_PARAMETERS:通过设定好打印设备,格式化样式,不显示弹窗等参数,得到完整打印参数。
NEW-PAGE PRINT...: 保证打印时不会出现选打印设备的弹窗,不介意弹窗的可以不加这句代码,但是加了句代码会带来一个额外的问题,下面会说。
调用 CONVERT_ABAPSPOOLJOB_2_PDF 可以直接获取到 PDF 的 XSTRING 类型内容,后续可以自行选择是否删除打印池中的记录。
问题点:
使用NEW-PAGE PRINT...带来的问题是,虽然弹窗没有了,但是调用ALV刷新方法时会引发系统dump。
原因是该语法之后调用ALV DISPLAY函数会产生一条新的屏幕堆栈记录,我没有详细追究其原理,只是确定了解决方式,在调用刷新之前,进行如下处理即可解决。
至此,一些特殊的问题点已补充完毕。下面是完整的框架源码及表结构信息。
7.框架源码及表结构信息:
其他的系统标准结构在源码中都能看到。
CLASS zprbccl_send_mail DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
CONSTANTS gc_type_e TYPE char1 VALUE 'E' ##NO_TEXT.
CONSTANTS gc_type_s TYPE char1 VALUE 'S' ##NO_TEXT.
CONSTANTS gc_state_a TYPE r3state VALUE 'A' ##NO_TEXT.
CONSTANTS gc_object_id TYPE w3_qname VALUE '_OBJECT_ID' ##NO_TEXT.
CONSTANTS gc_textformat TYPE bapi_tfrmt VALUE 'ASC' ##NO_TEXT.
CONSTANTS gc_success_status TYPE so_rec_sta VALUE '073' ##NO_TEXT.
CONSTANTS gc_command_r TYPE char1 VALUE 'R' ##NO_TEXT.
CLASS-METHODS send_mail
IMPORTING
!iv_title TYPE so_obj_des OPTIONAL
!iv_mail_from_address TYPE ad_smtpadr
!it_mail_to_address TYPE zprbct_mail_address
!it_mail_cc_address TYPE zprbct_mail_address OPTIONAL
!is_body TYPE zprbcs_mail_body
!it_attachment TYPE zprbct_mail_attachment OPTIONAL
EXPORTING
!es_return TYPE bapiret2 .
PROTECTED SECTION.
PRIVATE SECTION.
CLASS-METHODS build_document_with_temp_smw0
IMPORTING
!is_body_temp TYPE zprbcs_mail_temp_smw0
EXPORTING
!es_return TYPE bapiret2
!eo_document TYPE REF TO cl_document_bcs .
CLASS-METHODS build_document_with_template
IMPORTING
!is_body_temp TYPE zprbcs_mail_template
EXPORTING
!es_return TYPE bapiret2
!eo_document TYPE REF TO cl_document_bcs .
CLASS-METHODS get_image_solix_smw0
IMPORTING
!iv_smw0_name TYPE w3objid
EXPORTING
!ev_type TYPE w3conttype
!et_solix TYPE solix_tab
!ev_length TYPE so_obj_len .
CLASS-METHODS get_image_solix_mime
IMPORTING
!iv_mime_path TYPE string
EXPORTING
!ev_type TYPE w3conttype
!ev_length TYPE so_obj_len
!et_solix TYPE solix_tab .
ENDCLASS.
CLASS ZPRBCCL_SEND_MAIL IMPLEMENTATION.
* ---------------------------------------------------------------------------------------+
* | Static Private Method ZPRBCCL_SEND_MAIL=>BUILD_DOCUMENT_WITH_TEMPLATE
* +-------------------------------------------------------------------------------------------------+
* | [--->] IS_BODY_TEMP TYPE ZPRBCS_MAIL_TEMPLATE
* | [<---] ES_RETURN TYPE BAPIRET2
* | [<---] EO_DOCUMENT TYPE REF TO CL_DOCUMENT_BCS
* +--------------------------------------------------------------------------------------
METHOD build_document_with_template.
DATA:
lo_email_api TYPE REF TO if_smtg_email_api,
lo_exception TYPE REF TO cx_smtg_email_common,
lv_subject TYPE string,
lv_title TYPE so_obj_des,
lv_body_html TYPE string,
lt_body_html_soli TYPE soli_tab,
lt_image_solix TYPE solix_tab,
lv_image_type TYPE w3conttype,
lv_image_length TYPE so_obj_len,
lt_data_key TYPE if_smtg_email_template=>ty_gt_data_key.
DATA:
lo_excep_smtg_email_common TYPE REF TO cx_smtg_email_common,
lo_excep_document_bcs TYPE REF TO cx_document_bcs,
lo_excep_gbt_mime TYPE REF TO cx_gbt_mime,
lo_excep_bcom_mime TYPE REF TO cx_bcom_mime.
CHECK is_body_temp-id IS NOT INITIAL.
TRY .
* Get template object
lo_email_api = cl_smtg_email_api=>get_instance( iv_template_id = is_body_temp-id ).
MOVE-CORRESPONDING is_body_temp-cds_key TO lt_data_key.
TRY .
* Get html body and replace parameters by cds key.
* If a variable needs to be replaced, it should look like this {{BUKRS}}
lo_email_api->render(
EXPORTING
iv_language = sy-langu
it_data_key = lt_data_key
IMPORTING
ev_body_html = lv_body_html
ev_subject = lv_subject
).
lv_title = lv_subject.
* If the template include some content need to replace,
* You should set the MARK_FIELD and BODY_HTML,
LOOP AT is_body_temp-replace_info INTO DATA(ls_replace_info).
REPLACE ls_replace_info-mark_field IN lv_body_html WITH ls_replace_info-body_html.
ENDLOOP.
lt_body_html_soli = cl_bcs_convert=>string_to_soli( lv_body_html ).
DATA(lo_multipart) = NEW cl_gbt_multirelated_service( ).
lo_multipart->set_main_html(
EXPORTING
content = lt_body_html_soli
).
* If you want set some image,you must set value for 'CID',
* you can only choose one parameter between 'SMW0_NAME' and 'MIME_PATH'.
LOOP AT is_body_temp-image_info INTO DATA(ls_image_info).
IF ls_image_info-cid IS INITIAL.
CONTINUE.
ENDIF.
IF ls_image_info-smw0_name IS NOT INITIAL.
* Get SMW0 object content
get_image_solix_smw0(
EXPORTING
iv_smw0_name = ls_image_info-smw0_name
IMPORTING
et_solix = lt_image_solix
ev_type = lv_image_type
ev_length = lv_image_length
).
lo_multipart->add_binary_part(
EXPORTING
content = lt_image_solix
content_type = lv_image_type
length = lv_image_length
content_id = ls_image_info-cid
).
ENDIF.
IF ls_image_info-mime_path IS NOT INITIAL.
* Get MIME object content
get_image_solix_mime(
EXPORTING
iv_mime_path = ls_image_info-mime_path
IMPORTING
et_solix = lt_image_solix
ev_type = lv_image_type
ev_length = lv_image_length
).
* Add image content
lo_multipart->add_binary_part(
EXPORTING
content = lt_image_solix
content_type = lv_image_type
length = lv_image_length
content_id = ls_image_info-cid
).
ENDIF.
CLEAR:
lt_image_solix,
lv_image_type,
lv_image_length.
ENDLOOP.
TRY .
* Generate email document object
eo_document = cl_document_bcs=>create_from_multirelated(
EXPORTING
i_subject = lv_title
i_multirel_service = lo_multipart ).
CATCH cx_document_bcs INTO lo_excep_document_bcs.
es_return-type = gc_type_e.
es_return-message = lo_excep_document_bcs->get_text( ).
RETURN.
CATCH cx_gbt_mime INTO lo_excep_gbt_mime.
es_return-type = gc_type_e.
es_return-message = lo_excep_gbt_mime->get_text( ).
RETURN.
CATCH cx_bcom_mime INTO lo_excep_bcom_mime.
es_return-type = gc_type_e.
es_return-message = lo_excep_bcom_mime->get_text( ).
RETURN.
ENDTRY.
CATCH cx_smtg_email_common INTO lo_excep_smtg_email_common.
es_return-type = gc_type_e.
es_return-message = lo_excep_smtg_email_common->get_text( ).
RETURN.
ENDTRY.
CATCH cx_smtg_email_common INTO lo_excep_smtg_email_common.
es_return-type = gc_type_e.
es_return-message = lo_excep_smtg_email_common->get_text( ).
RETURN.
ENDTRY.
ENDMETHOD.
* ---------------------------------------------------------------------------------------+
* | Static Private Method ZPRBCCL_SEND_MAIL=>GET_IMAGE_SOLIX_MIME
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_MIME_PATH TYPE STRING
* | [<---] EV_TYPE TYPE W3CONTTYPE
* | [<---] EV_LENGTH TYPE SO_OBJ_LEN
* | [<---] ET_SOLIX TYPE SOLIX_TAB
* +--------------------------------------------------------------------------------------
METHOD get_image_solix_mime.
DATA:
lo_mr_api TYPE REF TO if_mr_api,
lv_content TYPE xstring.
CHECK iv_mime_path IS NOT INITIAL.
lo_mr_api = cl_mime_repository_api=>get_api( ).
lo_mr_api->get(
EXPORTING
i_url = iv_mime_path
IMPORTING
e_content = lv_content
e_mime_type = ev_type
).
et_solix = cl_bcs_convert=>xstring_to_solix( EXPORTING iv_xstring = lv_content ).
ENDMETHOD.
* ---------------------------------------------------------------------------------------+
* | Static Private Method ZPRBCCL_SEND_MAIL=>GET_IMAGE_SOLIX_SMW0
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_SMW0_NAME TYPE W3OBJID
* | [<---] EV_TYPE TYPE W3CONTTYPE
* | [<---] ET_SOLIX TYPE SOLIX_TAB
* | [<---] EV_LENGTH TYPE SO_OBJ_LEN
* +--------------------------------------------------------------------------------------
METHOD get_image_solix_smw0.
DATA:
lt_query TYPE STANDARD TABLE OF w3query,
ls_query TYPE w3query,
lt_html TYPE STANDARD TABLE OF w3html,
lv_length TYPE w3param-cont_len,
lv_return_code TYPE w3param-ret_code.
CHECK iv_smw0_name IS NOT INITIAL.
ls_query-name = gc_object_id.
ls_query-value = iv_smw0_name.
APPEND ls_query TO lt_query.
* Get content from SMW0
* This function is obsolete,MIME Repository is recommended
CALL FUNCTION 'WWW_GET_MIME_OBJECT'
TABLES
query_string = lt_query
html = lt_html
mime = et_solix
CHANGING
return_code = lv_return_code
content_type = ev_type
content_length = lv_length
EXCEPTIONS
object_not_found = 1
parameter_not_found = 2
OTHERS = 3.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
ev_length = lv_length.
ENDMETHOD.
* ---------------------------------------------------------------------------------------+
* | Static Public Method ZPRBCCL_SEND_MAIL=>SEND_MAIL
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_TITLE TYPE SO_OBJ_DES(optional)
* | [--->] IV_MAIL_FROM_ADDRESS TYPE AD_SMTPADR
* | [--->] IT_MAIL_TO_ADDRESS TYPE ZPRBCT_MAIL_ADDRESS
* | [--->] IT_MAIL_CC_ADDRESS TYPE ZPRBCT_MAIL_ADDRESS(optional)
* | [--->] IS_BODY TYPE ZPRBCS_MAIL_BODY
* | [--->] IT_ATTACHMENT TYPE ZPRBCT_MAIL_ATTACHMENT(optional)
* | [<---] ES_RETURN TYPE BAPIRET2
* +--------------------------------------------------------------------------------------
METHOD send_mail.
DATA:
lo_send_request TYPE REF TO cl_bcs,
lo_mail_from TYPE REF TO cl_cam_address_bcs,
lo_mail_to TYPE REF TO cl_cam_address_bcs,
lo_mail_cc TYPE REF TO cl_cam_address_bcs,
lt_mail_body TYPE soli_tab,
lt_attc_body TYPE solix_tab,
ls_body_in TYPE zprbcs_mail_body,
lo_document TYPE REF TO cl_document_bcs,
lv_result TYPE os_boolean,
lo_bcs_exception TYPE REF TO cx_root,
lv_oid TYPE sysuuid_x,
lv_msgno TYPE symsgno.
DATA:
BEGIN OF ls_time,
start TYPE timestampl, "Start time
now TYPE timestampl, "End time
elapsed TYPE tzntstmpl, "Elapsed time
limit TYPE tzntstmpl VALUE 3, "Max seconds
END OF ls_time.
TRY .
* create instance of CL_BCS
lo_send_request = cl_bcs=>create_persistent( ).
* Set sender email address
lo_mail_from = cl_cam_address_bcs=>create_internet_address( iv_mail_from_address ).
lo_send_request->set_sender( lo_mail_from ).
* Set receiver email address
LOOP AT it_mail_to_address INTO DATA(ls_mail_to_address).
IF ls_mail_to_address IS INITIAL.
es_return-type = gc_type_e.
es_return-message = 'The email address cannot be empty.'(001).
RETURN.
ENDIF.
lo_mail_to = cl_cam_address_bcs=>create_internet_address( ls_mail_to_address ).
* Send immediately
lo_send_request->set_send_immediately( i_send_immediately = abap_true ).
* Set address
lo_send_request->add_recipient( i_recipient = lo_mail_to
i_express = abap_true ).
ENDLOOP.
* Set CC email address
LOOP AT it_mail_cc_address INTO DATA(ls_mail_cc_address).
IF ls_mail_to_address IS INITIAL.
es_return-type = gc_type_e.
es_return-message = 'The email address cannot be empty.'(001).
RETURN.
ENDIF.
lo_mail_cc = cl_cam_address_bcs=>create_internet_address( ls_mail_cc_address ).
* Send immediately
lo_send_request->set_send_immediately( i_send_immediately = abap_true ).
* Set address
lo_send_request->add_recipient( i_recipient = lo_mail_cc
i_copy = abap_true
i_express = abap_true ).
ENDLOOP.
ls_body_in = is_body.
* Text body
IF ls_body_in-body_tline IS NOT INITIAL.
CLEAR:
ls_body_in-body_html,
ls_body_in-body_template,
ls_body_in-body_temp_smw0.
lt_mail_body = ls_body_in-body_tline-tline.
* Create mail body document object
lo_document = cl_document_bcs=>create_document(
i_type = ls_body_in-body_tline-type
i_text = lt_mail_body
i_subject = iv_title ).
ENDIF.
* HTML body
IF ls_body_in-body_html IS NOT INITIAL.
CLEAR:
ls_body_in-body_tline,
ls_body_in-body_template,
ls_body_in-body_temp_smw0.
* Convert string to solitab
lt_mail_body = cl_bcs_convert=>string_to_soli(
EXPORTING
iv_string = ls_body_in-body_html-html
).
* Create mail body document object
lo_document = cl_document_bcs=>create_document(
i_type = ls_body_in-body_html-type
i_text = lt_mail_body
i_subject = iv_title ).
ENDIF.
* Standard Template ->SE80->Email Template
IF ls_body_in-body_template IS NOT INITIAL.
CLEAR:
ls_body_in-body_tline,
ls_body_in-body_html,
ls_body_in-body_temp_smw0.
* Build document object with template
build_document_with_template(
EXPORTING
is_body_temp = ls_body_in-body_template
IMPORTING
eo_document = lo_document
es_return = es_return
).
CHECK es_return-type <> gc_type_e.
ENDIF.
* Template ->SMW0
IF ls_body_in-body_temp_smw0 IS NOT INITIAL.
CLEAR:
ls_body_in-body_tline,
ls_body_in-body_html,
ls_body_in-body_template.
* Build document object with template
build_document_with_temp_smw0(
EXPORTING
is_body_temp = ls_body_in-body_temp_smw0
IMPORTING
eo_document = lo_document
es_return = es_return
).
CHECK es_return-type <> gc_type_e.
ENDIF.
* Add attachment
IF it_attachment IS NOT INITIAL.
LOOP AT it_attachment INTO DATA(ls_attachment).
lo_document->add_attachment( i_attachment_type = ls_attachment-type
i_attachment_subject = ls_attachment-att_name
i_attachment_size = ls_attachment-size
i_att_content_hex = ls_attachment-body_content ).
ENDLOOP.
ENDIF.
* Binding mail body
lo_send_request->set_document( lo_document ).
* Send mail
lv_result = lo_send_request->send( i_with_error_screen = abap_true ).
* Get UUID
lv_oid = lo_send_request->oid( ).
IF lv_result = abap_true.
COMMIT WORK AND WAIT.
GET TIME STAMP FIELD ls_time-start.
WHILE ls_time-elapsed < ls_time-limit.
* Get mail send status in SOST
SELECT SINGLE
a~objtp,
a~objyr,
a~objno,
a~fortp,
a~foryr,
a~forno,
a~rectp,
a~recyr,
a~recno,
a~sndreq,
b~status,
b~msgid,
b~msgty,
b~msgv1,
b~msgv2,
b~msgv3,
b~msgv4
INTO @DATA(ls_mail_status)
FROM soos AS a
INNER JOIN soes AS b
ON a~rectp = b~rectp
AND a~recyr = b~recyr
AND a~recno = b~recno
WHERE a~sndreq = @lv_oid.
IF ls_mail_status-msgid IS NOT INITIAL.
EXIT.
ENDIF.
GET TIME STAMP FIELD ls_time-now.
ls_time-elapsed = cl_abap_tstmp=>subtract(
tstmp1 = ls_time-now
tstmp2 = ls_time-start
).
ENDWHILE.
IF ls_mail_status-status <> gc_success_status.
es_return-type = ls_mail_status-msgty.
lv_msgno = ls_mail_status-status.
CALL FUNCTION 'BAPI_MESSAGE_GETDETAIL'
EXPORTING
id = ls_mail_status-msgid
number = lv_msgno
textformat = gc_textformat
message_v1 = ls_mail_status-msgv1
message_v2 = ls_mail_status-msgv2
message_v3 = ls_mail_status-msgv3
message_v4 = ls_mail_status-msgv4
IMPORTING
message = es_return-message.
ELSE.
es_return-type = gc_type_s.
es_return-message = 'Mail send success.'(002).
ENDIF.
ELSE.
ROLLBACK WORK.
es_return-type = gc_type_e.
es_return-message = 'Mail send failed, Please use tcode SOST to check detail.'(003).
ENDIF.
CATCH cx_bcs INTO lo_bcs_exception.
es_return-type = gc_type_e.
es_return-message = lo_bcs_exception->get_text( ).
ENDTRY.
ENDMETHOD.
* ---------------------------------------------------------------------------------------+
* | Static Private Method ZPRBCCL_SEND_MAIL=>BUILD_DOCUMENT_WITH_TEMP_SMW0
* +-------------------------------------------------------------------------------------------------+
* | [--->] IS_BODY_TEMP TYPE ZPRBCS_MAIL_TEMP_SMW0
* | [<---] ES_RETURN TYPE BAPIRET2
* | [<---] EO_DOCUMENT TYPE REF TO CL_DOCUMENT_BCS
* +--------------------------------------------------------------------------------------
METHOD build_document_with_temp_smw0.
DATA:
lt_html_table TYPE swww_t_html_table,
lv_html_string TYPE string,
lt_merge_table TYPE swww_t_merge_table,
ls_merge_table TYPE swww_t_merge_item,
lt_image_solix TYPE solix_tab,
lv_image_type TYPE w3conttype,
lv_image_length TYPE so_obj_len.
DATA:
key TYPE wwwdataid.
DATA:
lo_excep_smtg_email_common TYPE REF TO cx_smtg_email_common,
lo_excep_document_bcs TYPE REF TO cx_document_bcs,
lo_excep_gbt_mime TYPE REF TO cx_gbt_mime,
lo_excep_bcom_mime TYPE REF TO cx_bcom_mime.
CHECK is_body_temp-id IS NOT INITIAL.
* Set replace body
* LOOP AT is_body_temp-replace_info INTO DATA(ls_repace_info).
* ls_merge_table-name = ls_repace_info-mark_field.
* ls_merge_table-command = gc_command_r.
* ls_merge_table-html[] = ls_repace_info-body_html.
* APPEND ls_merge_table TO lt_merge_table.
* CLEAR ls_merge_table.
* ENDLOOP.
* Replace html body
* CALL FUNCTION 'WWW_HTML_MERGER'
* EXPORTING
* template = is_body_temp-id
** MERGE_TEXTPOOL =
** TEMPLATE_TABLE =
* IMPORTING
* html_table = lt_html_table
* CHANGING
* merge_table = lt_merge_table
* EXCEPTIONS
* template_not_found = 1
* OTHERS = 2.
key-objid = is_body_temp-id.
IMPORT html TO lt_html_table FROM DATABASE wwwdata(ht) ID key.
IF sy-subrc <> 0.
* Object &1 does not exist in Web Repository
MESSAGE s000(swww) WITH is_body_temp-id INTO es_return-message.
es_return-type = gc_type_e.
RETURN.
ENDIF.
lv_html_string = cl_bcs_convert=>txt_to_string( EXPORTING it_soli = lt_html_table ).
LOOP AT is_body_temp-replace_info INTO DATA(ls_repace_info).
REPLACE ALL OCCURRENCES OF ls_repace_info-mark_field
IN lv_html_string
WITH cl_bcs_convert=>txt_to_string( EXPORTING it_soli = ls_repace_info-body_html ).
ENDLOOP.
lt_html_table = cl_bcs_convert=>string_to_soli( EXPORTING iv_string = lv_html_string ).
DATA(lo_multipart) = NEW cl_gbt_multirelated_service( ).
lo_multipart->set_main_html(
EXPORTING
content = lt_html_table
).
* If you want set some image,you must set value for 'CID',
* you can only choose one parameter between 'SMW0_NAME' and 'MIME_PATH'.
LOOP AT is_body_temp-image_info INTO DATA(ls_image_info).
IF ls_image_info-cid IS INITIAL.
CONTINUE.
ENDIF.
IF ls_image_info-smw0_name IS NOT INITIAL.
* Get SMW0 object content
get_image_solix_smw0(
EXPORTING
iv_smw0_name = ls_image_info-smw0_name
IMPORTING
et_solix = lt_image_solix
ev_type = lv_image_type
ev_length = lv_image_length
).
lo_multipart->add_binary_part(
EXPORTING
content = lt_image_solix
content_type = lv_image_type
length = lv_image_length
content_id = ls_image_info-cid
).
ENDIF.
IF ls_image_info-mime_path IS NOT INITIAL.
* Get MIME object content
get_image_solix_mime(
EXPORTING
iv_mime_path = ls_image_info-mime_path
IMPORTING
et_solix = lt_image_solix
ev_type = lv_image_type
ev_length = lv_image_length
).
* Add image content
lo_multipart->add_binary_part(
EXPORTING
content = lt_image_solix
content_type = lv_image_type
length = lv_image_length
content_id = ls_image_info-cid
).
ENDIF.
CLEAR:
lt_image_solix,
lv_image_type,
lv_image_length.
ENDLOOP.
TRY .
* Generate email document object
eo_document = cl_document_bcs=>create_from_multirelated(
EXPORTING
i_subject = is_body_temp-title
i_multirel_service = lo_multipart ).
CATCH cx_document_bcs INTO lo_excep_document_bcs.
es_return-type = gc_type_e.
es_return-message = lo_excep_document_bcs->get_text( ).
RETURN.
CATCH cx_gbt_mime INTO lo_excep_gbt_mime.
es_return-type = gc_type_e.
es_return-message = lo_excep_gbt_mime->get_text( ).
RETURN.
CATCH cx_bcom_mime INTO lo_excep_bcom_mime.
es_return-type = gc_type_e.
es_return-message = lo_excep_bcom_mime->get_text( ).
RETURN.
ENDTRY.
ENDMETHOD.
ENDCLASS.
8.SE38 Demo程序源码:
CDS VIEW可自行换成自己需要的CDS VIEW名称
*&---------------------------------------------------------------------*
*& Report ZTEST_SEND_MAIL
*&---------------------------------------------------------------------*
*& Author: DeveloperMrMeng
*& Date: 2023/07/16
*&---------------------------------------------------------------------*
*& The sample program includes the following functions:
*& 1. send mail with txt body
*& 2. send mail with html body(use abap build body)
*& 3. send mail with template (SE80->create email template)
*& 3.1 replace fields with cds
*& 4. send mail with template (SMW0)
*& 5. add image with SMW0
*& 6. add image with SO2_MIME_REPOSITORY
*& 7. add attchment
*& 7.1 add .txt file
*& 7.2 add .csv file
*& 7.3 add .pdf from smartforms
*& 7.3.1 Mergae PDF
*& 7.4 add .pdf from alv
*&---------------------------------------------------------------------*
REPORT ztest_send_mail.
TABLES:eban.
TYPES:
ty_alv TYPE zstest_send_mail,
tt_alv TYPE STANDARD TABLE OF ty_alv.
DATA:
gt_alv TYPE tt_alv,
gs_alv TYPE ty_alv,
gt_sf_alv TYPE tt_alv.
DATA:
go_alv_grid TYPE REF TO cl_gui_alv_grid,
gt_fieldcat TYPE lvc_t_fcat,
gs_layout TYPE lvc_s_layo.
CONSTANTS:
gc_temp_smw0 TYPE w3objid VALUE 'ZTEST_TEMP_SMW0'.
SELECT-OPTIONS:s_banfn FOR eban-banfn.
START-OF-SELECTION.
PERFORM frm_get_data.
PERFORM frm_show_alv.
*&---------------------------------------------------------------------*
*& Form frm_get_data
*&---------------------------------------------------------------------*
*& Get data
*&---------------------------------------------------------------------*
FORM frm_get_data .
* Get relevant data
SELECT a~banfn, "Purchase Requisition Number
a~bnfpo, "Item number of purchase requisition
a~bsart, "Order Type (Purchasing)
a~frgst, "Release strategy in the purchase requisition
a~frggr, "Release group
a~zrelcode_next, "Release code(Next)
b~approver, "Approver
b~email, "Approver’s Email
a~ekgrp, "Purchasing Group
a~werks, "Plant
a~ernam, "Name of Person who Created the Object
a~afnam, "Name of requisitioner/requester
a~matnr, "Material Number
a~txz01, "Short Text
a~menge, "Quantity
a~meins, "Base Unit of Measure
a~value_item, "Total value at time of release
a~frgdt, "Purchase Requisition Release Date
a~lfdat, "Delivery date
a~webaz, "Goods receipt processing time in days
a~matkl, "Material Group
a~dispo, "MRP Controller
a~lifnr "Account Number of Vendor or Creditor
FROM zprmmt_relstat_pr AS a
INNER JOIN zprmmtapprinfo AS b
ON a~frggr = b~frggr
AND a~frgst = b~frgst
AND a~zrelcode_next = b~frgco
WHERE a~banfn IN @s_banfn
AND b~email IS NOT INITIAL
AND b~approver IS NOT INITIAL
INTO TABLE @DATA(lt_data).
IF lt_data IS INITIAL.
MESSAGE 'No data' TYPE 'S'.
LEAVE LIST-PROCESSING.
ENDIF.
SORT lt_data BY banfn ASCENDING
bnfpo ASCENDING.
LOOP AT lt_data INTO DATA(ls_data).
gs_alv-banfn = ls_data-banfn. "Purchase Requisition Number
gs_alv-bnfpo = ls_data-bnfpo. "Item number of purchase requisition
gs_alv-bsart = ls_data-bsart. "Order Type (Purchasing)
gs_alv-frgst = ls_data-frgst. "Release strategy in the purchase requisition
gs_alv-frggr = ls_data-frggr. "Release group
gs_alv-frgco = ls_data-zrelcode_next. "Release code(Next)
gs_alv-approver = ls_data-approver. "Approver
gs_alv-email = ls_data-email. "Approver’s Email
gs_alv-ekgrp = ls_data-ekgrp. "Purchasing Group
gs_alv-werks = ls_data-werks. "Plant
gs_alv-ernam = ls_data-ernam. "Name of Person who Created the Object
gs_alv-afnam = ls_data-afnam. "Name of requisitioner/requester
gs_alv-matnr = ls_data-matnr. "Material Number
gs_alv-txz01 = ls_data-txz01. "Short Text
gs_alv-menge = ls_data-menge. "Quantity
gs_alv-meins = ls_data-meins. "Base Unit of Measure
gs_alv-value_item = ls_data-value_item. "Total value at time of release
gs_alv-frgdt = ls_data-frgdt. "Purchase Requisition Release Date
gs_alv-lfdat = ls_data-lfdat. "Delivery date
gs_alv-webaz = ls_data-webaz. "Goods receipt processing time in days
gs_alv-matkl = ls_data-matkl. "Material Group
gs_alv-dispo = ls_data-dispo. "MRP Controller
gs_alv-lifnr = ls_data-lifnr. "Account Number of Vendor or Creditor
APPEND gs_alv TO gt_alv.
CLEAR gs_alv.
ENDLOOP.
SORT gt_alv BY banfn ASCENDING
bnfpo ASCENDING
email ASCENDING.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_show_alv
*&---------------------------------------------------------------------*
*& Show ALV
*&---------------------------------------------------------------------*
FORM frm_show_alv .
* Set layout
gs_layout-zebra = 'X'.
gs_layout-cwidth_opt = 'X'.
gs_layout-box_fname = 'CBOX'.
gs_layout-sel_mode = 'D'.
* Get fieldcat
CALL FUNCTION 'LVC_FIELDCATALOG_MERGE' ##FM_SUBRC_OK
EXPORTING
i_structure_name = 'ZSTEST_SEND_MAIL'
i_bypassing_buffer = abap_true
CHANGING
ct_fieldcat = gt_fieldcat
EXCEPTIONS
inconsistent_interface = 1
program_error = 2
OTHERS = 3.
* Hide checkbox
READ TABLE gt_fieldcat ASSIGNING FIELD-SYMBOL()
WITH KEY fieldname = 'CBOX'.
IF sy-subrc = 0.
-no_out = 'X'.
-tech = 'X'.
ENDIF.
* ALV display
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
EXPORTING
i_callback_program = syst-repid
it_fieldcat_lvc = gt_fieldcat
i_callback_user_command = 'FRM_USER_COMMAND'
i_callback_pf_status_set = 'FRM_PF_STATUS_SET'
is_layout_lvc = gs_layout
i_save = 'A'
TABLES
t_outtab = gt_alv
EXCEPTIONS
program_error = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_pf_status_set
*&---------------------------------------------------------------------*
*& Set status
*&---------------------------------------------------------------------*
FORM frm_pf_status_set USING rt_extab TYPE slis_t_extab.
SET PF-STATUS 'STATUS'." EXCLUDING RT_EXTAB.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_user_command
*&---------------------------------------------------------------------*
*& Process user command
*&---------------------------------------------------------------------*
FORM frm_user_command USING r_ucomm LIKE sy-ucomm
rs_selfield TYPE slis_selfield.
DATA:
lo_grid TYPE REF TO cl_gui_alv_grid,
ls_stable TYPE lvc_s_stbl,
ls_layout TYPE lvc_s_layo.
DATA:
lo_control TYPE REF TO cl_gui_control,
lt_control TYPE cnto_control_list.
CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
IMPORTING
e_grid = lo_grid.
CASE r_ucomm.
* Send mail
WHEN 'SEND'.
* Send test email
PERFORM frm_send_test_email.
WHEN OTHERS.
ENDCASE.
************************************************************************
* If you use NEW-PAGE to process ALV->PDF,you need to delete the subscriber index 1.
cl_gui_cfw=>get_subscriber_by_id(
EXPORTING
shellid = 0
IMPORTING
subscriber = lo_control
EXCEPTIONS
cntl_error = 1
).
IF lo_control IS NOT INITIAL.
cl_gui_cfw=>unsubscribe( EXPORTING ref = lo_control ).
ENDIF.
************************************************************************
CALL METHOD lo_grid->get_frontend_layout
IMPORTING
es_layout = ls_layout.
ls_layout-cwidth_opt = 'X'.
* Set Optimize column width
CALL METHOD lo_grid->set_frontend_layout
EXPORTING
is_layout = ls_layout.
ls_stable-row = 'X'.
ls_stable-col = 'X'.
* Refresh ALV
CALL METHOD lo_grid->refresh_table_display
EXPORTING
is_stable = ls_stable
EXCEPTIONS
finished = 1
OTHERS = 2.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_send_test_email
*&---------------------------------------------------------------------*
*& Send test email
*&---------------------------------------------------------------------*
FORM frm_send_test_email .
DATA:
lt_alv_mail TYPE tt_alv,
ls_alv_mail TYPE ty_alv.
* Email parameters
DATA:
lv_message TYPE string,
lv_html_string TYPE string,
ls_body TYPE zprbcs_mail_body,
lt_mail_to_address TYPE zprbct_mail_address,
ls_mail_to_address TYPE ad_smtpadr,
ls_mail_template TYPE zprbcs_mail_template,
ls_mail_temp_smw0 TYPE zprbcs_mail_temp_smw0,
lt_cds_key TYPE zprbct_mail_cds_key_value,
ls_cds_key TYPE zprbcs_mail_cds_key_value,
lt_temp_replace TYPE zprbct_mail_temp_replace,
ls_temp_replace TYPE zprbcs_mail_temp_replace,
lt_temp_rep_smw0 TYPE zprbct_mail_temp_smw0_replace,
ls_temp_rep_smw0 TYPE zprbcs_mail_temp_smw0_replace,
lt_body_html_smw0 TYPE w3html_tab,
ls_body_html_smw0 TYPE w3html,
lv_html_str_smw0 TYPE string,
lv_approver TYPE string,
lt_images TYPE zprbct_mail_temp_img,
ls_images TYPE zprbcs_mail_temp_img,
lt_attch TYPE zprbct_mail_attachment,
ls_attch TYPE zprbcs_mail_attachment,
ls_return TYPE bapiret2.
DATA:
lo_bcs TYPE REF TO cx_bcs.
lt_alv_mail = gt_alv.
DELETE lt_alv_mail WHERE cbox IS INITIAL.
CHECK lt_alv_mail IS NOT INITIAL.
SORT lt_alv_mail BY banfn ASCENDING
bnfpo ASCENDING
email ASCENDING.
LOOP AT lt_alv_mail INTO ls_alv_mail
GROUP BY ( banfn = ls_alv_mail-banfn
email = ls_alv_mail-email ) ASCENDING
REFERENCE INTO DATA(lo_mail_data).
CLEAR gt_sf_alv.
LOOP AT GROUP lo_mail_data ASSIGNING FIELD-SYMBOL().
**********************************************************************
* Build html replace info ->SE80->Email template
**********************************************************************
* Set CDS Key
ls_cds_key-value = -banfn.
* Set approver
lv_approver = -approver.
* Set receiver address
ls_mail_to_address = -email.
* Dynamic HTML body:
lv_html_string = lv_html_string &&
'' &&
'' && -banfn && ' ' &&
'' && -bnfpo && ' ' &&
'' && -bsart && ' ' &&
'' && -frggr && ' ' &&
'' && -frgst && ' ' &&
'' && -frgco && ' ' &&
'' && -ekgrp && ' ' &&
'' && -werks && ' ' &&
'' && -ernam && ' ' &&
'' && -afnam && ' ' &&
'' && -matnr && ' ' &&
'' && -txz01 && ' ' &&
'' && -menge && ' ' &&
'' && -meins && ' ' &&
'' && -value_item && ' ' &&
'' && -frgdt && ' ' &&
'' && -lfdat && ' ' &&
'' && -webaz && ' ' &&
'' && -matkl && ' ' &&
'' && -dispo && ' ' &&
'' && -lifnr && ' ' &&
' '.
APPEND TO gt_sf_alv.
ENDLOOP.
* Set template replace content --Approver
ls_temp_replace-mark_field = ''.
ls_temp_replace-body_html = lv_approver.
APPEND ls_temp_replace TO lt_temp_replace.
* Set template replace content --Table
ls_temp_replace-mark_field = ''.
ls_temp_replace-body_html = lv_html_string.
APPEND ls_temp_replace TO lt_temp_replace.
* Set template replace content --System Date
ls_temp_replace-mark_field = ''.
ls_temp_replace-body_html = sy-datlo.
APPEND ls_temp_replace TO lt_temp_replace.
SORT lt_temp_replace BY mark_field ASCENDING.
DELETE ADJACENT DUPLICATES FROM lt_temp_replace COMPARING mark_field.
* CDS Key
ls_cds_key-name = 'BANFN'.
APPEND ls_cds_key TO lt_cds_key.
**********************************************************************
* Build html replace info ->SMW0
**********************************************************************
ls_temp_rep_smw0-mark_field = ''.
ls_body_html_smw0-line = -banfn.
APPEND ls_body_html_smw0 TO lt_body_html_smw0.
ls_temp_rep_smw0-body_html = lt_body_html_smw0.
APPEND ls_temp_rep_smw0 TO lt_temp_rep_smw0.
ls_temp_rep_smw0-mark_field = ''.
ls_temp_rep_smw0-body_html = cl_bcs_convert=>string_to_soli( EXPORTING iv_string = lv_html_string ).
APPEND ls_temp_rep_smw0 TO lt_temp_rep_smw0.
**********************************************************************
* Email Address info
**********************************************************************
APPEND ls_mail_to_address TO lt_mail_to_address.
SORT lt_mail_to_address ASCENDING.
DELETE ADJACENT DUPLICATES FROM lt_mail_to_address COMPARING ALL FIELDS.
**********************************************************************
* Email Image with SMW0
**********************************************************************
ls_images-cid = 'SAP_LOGO_SMW0'.
ls_images-smw0_name = 'ZSAP_LOGO'.
APPEND ls_images TO lt_images.
CLEAR ls_images.
**********************************************************************
* Email Image with SO2_MIME_REPOSITORY
**********************************************************************
ls_images-cid = 'SAP_LOGO_MIME'.
ls_images-mime_path = '/SAP/PUBLIC/SAPLOGO_TR.bmp'.
APPEND ls_images TO lt_images.
CLEAR ls_images.
**********************************************************************
* Email Attchment - txt
**********************************************************************
ls_attch-type = 'TXT'.
ls_attch-att_name = 'TestTXT.txt'.
TRY .
cl_bcs_convert=>string_to_solix(
EXPORTING
iv_string = 'Hello word'
IMPORTING
et_solix = ls_attch-body_content
ev_size = ls_attch-size
).
APPEND ls_attch TO lt_attch.
CLEAR ls_attch.
CATCH cx_bcs INTO lo_bcs.
ENDTRY.
**********************************************************************
* Email Attchment - csv
**********************************************************************
ls_attch-type = 'CSV'.
ls_attch-att_name = 'TestCSV.csv'.
DATA(lv_string) = 'Hello' && ',' && 'World' && cl_abap_char_utilities=>cr_lf &&
'Hello' && ',' && 'DeveloperMrMeng'.
TRY .
cl_bcs_convert=>string_to_solix(
EXPORTING
iv_string = lv_string
IMPORTING
et_solix = ls_attch-body_content
ev_size = ls_attch-size
).
APPEND ls_attch TO lt_attch.
CLEAR ls_attch.
CATCH cx_bcs INTO lo_bcs.
ENDTRY.
**********************************************************************
* Email Attchment - Smartform to PDF
**********************************************************************
ls_attch-type = 'PDF'.
ls_attch-att_name = 'TestPDF_Smartforms.pdf'.
* Smartform convert to PDF
PERFORM frm_get_sf_pdf_solix CHANGING ls_attch-body_content
ls_attch-size.
APPEND ls_attch TO lt_attch.
CLEAR ls_attch.
**********************************************************************
* Email Attchment - ALV to PDF
**********************************************************************
ls_attch-type = 'PDF'.
ls_attch-att_name = 'TestPDF_ALV.pdf'.
* ALV convert to PDF
PERFORM frm_get_alv_pdf_solix CHANGING ls_attch-body_content
ls_attch-size.
APPEND ls_attch TO lt_attch.
CLEAR ls_attch.
**********************************************************************
* Email template ->SE80->Email template
**********************************************************************
ls_mail_template-id = 'ZTEST_TEMP_DEMO'.
ls_mail_template-cds_key = lt_cds_key.
ls_mail_template-replace_info = lt_temp_replace.
ls_mail_template-image_info = lt_images.
ls_body-body_template = ls_mail_template.
**********************************************************************
* Email template ->SMW0
**********************************************************************
* ls_mail_temp_smw0-id = 'ZTEMP_SMW0'.
* ls_mail_temp_smw0-title = 'This is a test title'.
* ls_mail_temp_smw0-replace_info = lt_temp_rep_smw0.
* ls_mail_temp_smw0-image_info = lt_images.
*
* ls_body-body_temp_smw0 = ls_mail_temp_smw0.
* Send Mail
zprbccl_send_mail=>send_mail(
EXPORTING
iv_mail_from_address = '[email protected]'
it_mail_to_address = lt_mail_to_address
is_body = ls_body
it_attachment = lt_attch
IMPORTING
es_return = ls_return
).
IF sy-batch = abap_true.
ASSIGN COMPONENT 'BANFN' OF STRUCTURE lo_mail_data TO FIELD-SYMBOL().
* &1 send mail success.
MESSAGE s057(zprbcmsg) WITH .
ELSE.
LOOP AT GROUP lo_mail_data ASSIGNING .
READ TABLE gt_alv ASSIGNING FIELD-SYMBOL()
WITH KEY banfn = -banfn
bnfpo = -bnfpo
email = -email
BINARY SEARCH.
IF ls_return-type = 'S'.
-icon = icon_led_green.
ELSE.
-icon = icon_led_red.
ENDIF.
-msg = ls_return-message.
ENDLOOP.
ENDIF.
CLEAR:
lv_html_string,
lt_mail_to_address,
ls_mail_to_address,
ls_body,
lt_cds_key,
ls_cds_key,
ls_temp_replace,
lt_temp_replace,
lt_temp_rep_smw0,
ls_temp_rep_smw0,
lt_body_html_smw0,
ls_body_html_smw0,
ls_return.
ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_get_sf_pdf_solix
*&---------------------------------------------------------------------*
*& Smartform convert to PDF
*&---------------------------------------------------------------------*
*& <-- CS_ATTCH_BODY_CONTENT
*& <-- CS_ATTCH_SIZE
*&---------------------------------------------------------------------*
FORM frm_get_sf_pdf_solix CHANGING cs_attch_body_content TYPE solix_tab
cs_attch_size TYPE so_obj_len.
DATA:
lv_fname TYPE rs38l_fnam.
DATA:
ls_control_para TYPE ssfctrlop,
ls_output_option TYPE ssfcompop,
ls_job_output_info TYPE ssfcrescl,
lv_spoolid TYPE rspoid.
DATA:
lv_size TYPE i,
lv_xstring TYPE xstring.
* Get dynamic runtime function name
CALL FUNCTION 'SSF_FUNCTION_MODULE_NAME'
EXPORTING
formname = 'ZTEST_SF2PDF'
* VARIANT = ' '
* DIRECT_CALL = ' '
IMPORTING
fm_name = lv_fname
EXCEPTIONS
no_form = 1
no_function_module = 2
OTHERS = 3.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
* ls_control_para-getotf = 'X'.
ls_control_para-no_dialog = 'X'.
ls_output_option-tddest = 'LP01'.
ls_output_option-tdnewid = 'X'.
* Call Smartforms
CALL FUNCTION lv_fname
EXPORTING
control_parameters = ls_control_para
output_options = ls_output_option
user_settings = ''
IMPORTING
job_output_info = ls_job_output_info
EXCEPTIONS
formatting_error = 1
internal_error = 2
send_error = 3
user_canceled = 4
OTHERS = 5.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
CHECK ls_job_output_info-spoolids IS NOT INITIAL.
READ TABLE ls_job_output_info-spoolids INTO DATA(ls_spoolids) INDEX 1.
lv_spoolid = ls_spoolids.
* Convert OTF to PDF
CALL FUNCTION 'CONVERT_OTFSPOOLJOB_2_PDF'
EXPORTING
src_spoolid = lv_spoolid
* NO_DIALOG = 'X'
* DST_DEVICE =
pdf_destination = 'X'
no_background = 'X'
* USE_CASCADING = ' '
* MODIFIED_PARAM_TABLE =
IMPORTING
pdf_bytecount = lv_size
* PDF_SPOOLID =
* OTF_PAGECOUNT =
* BTC_JOBNAME =
* BTC_JOBCOUNT =
bin_file = lv_xstring
* TABLES
* PDF =
EXCEPTIONS
err_no_otf_spooljob = 1
err_no_spooljob = 2
err_no_permission = 3
err_conv_not_possible = 4
err_bad_dstdevice = 5
user_cancelled = 6
err_spoolerror = 7
err_temseerror = 8
err_btcjob_open_failed = 9
err_btcjob_submit_failed = 10
err_btcjob_close_failed = 11
OTHERS = 12.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
TRY .
DATA(lo_pdf_merge) = NEW cl_rspo_pdf_merge( ).
lo_pdf_merge->check_document(
EXPORTING
document = lv_xstring
IMPORTING
error_text = DATA(error_text)
rc = DATA(rc)
).
lo_pdf_merge->add_document( lv_xstring ).
lo_pdf_merge->add_document( lv_xstring ).
lo_pdf_merge->merge_documents(
IMPORTING
merged_document = DATA(lv_new_xstring)
).
CATCH cx_rspo_pdf_merge.
ENDTRY.
lv_size = xstrlen( lv_new_xstring ).
cs_attch_body_content = cl_bcs_convert=>xstring_to_solix( EXPORTING iv_xstring = lv_new_xstring ).
cs_attch_size = lv_size.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_get_alv_pdf_solix
*&---------------------------------------------------------------------*
*& ALV convert to PDF
*&---------------------------------------------------------------------*
*& <-- CS_ATTCH_BODY_CONTENT
*& <-- CS_ATTCH_SIZE
*&---------------------------------------------------------------------*
FORM frm_get_alv_pdf_solix CHANGING cs_attch_body_content TYPE solix_tab
cs_attch_size TYPE so_obj_len.
DATA:
ls_print TYPE lvc_s_prnt,
lv_spoolid TYPE rspoid,
lv_spoolid_del TYPE rqident,
lt_pdf_tab TYPE STANDARD TABLE OF tline,
lv_pdf_xstring TYPE xstring,
lv_pdf_size TYPE i.
ls_print-print = 'X'.
* Set print no dialog
CALL FUNCTION 'GET_PRINT_PARAMETERS'
EXPORTING
destination = 'LP01'
immediately = 'X'
layout = 'X_65_255'
mode = 'BATCH'
no_dialog = 'X'
IMPORTING
out_parameters = ls_print-print_ctrl-pri_params
* VALID =
* VALID_FOR_SPOOL_CREATION =
EXCEPTIONS
archive_info_not_found = 1
invalid_print_params = 2
invalid_archive_params = 3
OTHERS = 4.
IF sy-subrc <> 0.
* Implement suitable error handling here
ELSE.
ls_print-print = 'X'.
ls_print-no_change_print_params = 'X'.
NEW-PAGE PRINT ON NEW-SECTION PARAMETERS ls_print-print_ctrl-pri_params NO DIALOG.
* ALV display
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
EXPORTING
* i_callback_program = syst-repid
it_fieldcat_lvc = gt_fieldcat
is_layout_lvc = gs_layout
is_print_lvc = ls_print
TABLES
t_outtab = gt_sf_alv
EXCEPTIONS
program_error = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ELSE.
CHECK sy-spono IS NOT INITIAL.
lv_spoolid = sy-spono.
* Get PDF content
CALL FUNCTION 'CONVERT_ABAPSPOOLJOB_2_PDF'
EXPORTING
src_spoolid = lv_spoolid
pdf_destination = 'X'
* NO_DIALOG =
IMPORTING
pdf_bytecount = lv_pdf_size
bin_file = lv_pdf_xstring
EXCEPTIONS
err_no_abap_spooljob = 1
err_no_spooljob = 2
err_no_permission = 3
err_conv_not_possible = 4
err_bad_destdevice = 5
user_cancelled = 6
err_spoolerror = 7
err_temseerror = 8
err_btcjob_open_failed = 9
err_btcjob_submit_failed = 10
err_btcjob_close_failed = 11
OTHERS = 12.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
cs_attch_body_content = cl_bcs_convert=>xstring_to_solix( EXPORTING iv_xstring = lv_pdf_xstring ).
cs_attch_size = lv_pdf_size.
lv_spoolid_del = lv_spoolid.
*
* CALL FUNCTION 'RSPO_R_RDELETE_SPOOLREQ'
* EXPORTING
* spoolid = lv_spoolid_del.
ENDIF.
ENDIF.
ENDFORM.
以上。
你可能感兴趣的:(SAP技术小知识,sap,abap,erp,html)