Offline/External Mail Approval Process without using SAP Part-1
Dear Friends
Most of us have a requirement where clients try to use shortcuts in SAP for Approvals. I’ve seen many people asking the same question/requirement in SCN for Offline approvals. Even this was a requirement once in my case also. Then I’ve found one similar document with same requirement with ABAP stuff & later I tried the same. So, I wanted to make this as a document & share with all the SCN users. Hope you all support me.
Goto T-code SMICM or run Report RSMONICM_STANDARD
Now display the services via GotoàServices or press Shift+F1
Now select the logs & Activate
Now we can see the Active services
Now we need to configure & set the Email Exit Configuration
Goto T-code SO50
We can also access via T-code SCOT & by following the menu path click on SettingsàIn Bound processing as ,It also calls SO50 or we can also run a report BCS_IBND_MAINT
We have to write an Inbound Exit Class that will process the Inbound E-Mails. That class should be mentioned here.
Note that we mention our offline e-mail ID here (riploffline@eccdev.yourdomain.com). The class ZZZCL_PROCESS_INBOUND_WORKFLOW is the Exit Class designed to process inbound e-mails as per our need. By default generally the first entry with the CL_APPOINTMENT_REPLY is always present. We include our entry here and set the call sequence. The Document Class / Type is set as “*” to allow all types of documents available in ECC.
Creation of Inbound Exit class
This class implements the interface IF_INBOUND_EXIT_BCS (BCS: Exit for Inbound Processing). The properties tab of the class is shown as
Now click on Interface tab
Now click on Methods
The CREATE_INSTANCE method is called by standard SAP (via SO50 Configuration) to create a unique instance for each inbound e-mail. The code is written below
METHOD if_inbound_exit_bcs~create_instance.
DATA: ref TYPE REF TO zzzcl_process_inbound_workflow.
* Check if the Instance is initial
IF ref IS INITIAL.
CREATE OBJECT ref.
ENDIF.
* Return the Instance
ro_ref = ref.
- ENDMETHOD.
The interface of the method CREATE_INSTANCE is shown below
The PROCESS_INBOUND method is the place where we write the exit logic. This is where we will process the desired work item of the workflow and process it based on the e-mail action / reply created by the automated e-mail. The interface of method PROCESS_INBOUND is shown below.
The code in PROCESS_INBOUND method is below
METHOD if_inbound_exit_bcs~process_inbound.
* Declare for Inbound E-Mail processing (ENJOY )
DATA: lo_document TYPE REF TO if_document_bcs,
l_mail_attr TYPE bcss_dbpa,
l_mail_content TYPE bcss_dbpc,
lo_reply TYPE REF TO cl_send_request_bcs,
sender TYPE REF TO if_sender_bcs,
sender_addr TYPE string,
lv_email TYPE comm_id_long,
send_request TYPE REF TO cl_bcs,
ltext TYPE bcsy_text,
body_text TYPE so_text255,
document TYPE REF TO cl_document_bcs,
ex_sender TYPE REF TO cl_sapuser_bcs,
recipient TYPE REF TO if_recipient_bcs,
bcs_exception TYPE REF TO cx_bcs,
sent_to_all TYPE os_boolean,
lv_action TYPE char01,
lv_wid TYPE char12,
lv_wid_num TYPE sww_wiid,
lv_wid_func TYPE swr_struct-workitemid,
ls_swwwihead TYPE swwwihead,
lv_new_status TYPE sww_wistat,
lv_action_text TYPE char12.
*——————————————————————–*
*- Get a pointer to the reply email object -*
*——————————————————————–*
TRY.
lo_reply = io_sreq->reply( ).
CATCH cx_send_req_bcs.
ENDTRY.
**** Check to make sure this is from an approved Sender
sender = io_sreq->get_sender( ).
sender_addr = sender->address_string( ).
lv_email = sender_addr.
TRANSLATE sender_addr TO UPPER CASE.
**** Only reply if this message came from within our mail system or domain
**** SPAMMERS Beware, your e-mails will not be processed!!!
IF sender_addr CS ‘@YOURDOMAIN.COM‘.
**** send reply and inbound processing
*——————————————————————–*
*- Get email subject -*
*——————————————————————–*
TRY.
lo_document = io_sreq->get_document( ).
l_mail_attr = lo_document->get_body_part_attributes( ‘1’ ).
CATCH cx_document_bcs.
ENDTRY.
*——————————————————————–*
*- Get mail body, here you can read the REJECTION Reason -*
*——————————————————————–*
TRY.
l_mail_content = lo_document->get_body_part_content( ‘1’ ).
CATCH cx_document_bcs.
ENDTRY.
*——————————————————————–*
* YAAAAAHHHHHHOOOO at this point I have the Subject and the Body
*——————————————————————–*
* Now read the subject and process the work item
* Condense the subject to remove blank spaces
CONDENSE l_mail_attr-subject.
* Read the action
lv_action = l_mail_attr-subject+0(1).
* Read the work item ID
lv_wid = l_mail_attr-subject+1(12).
* Pass to variables
lv_wid_num = lv_wid.
lv_wid_func = lv_wid_num.
* First check the status of the work item, process only if READY or IN-PROCESS
SELECT SINGLE *
FROM swwwihead
INTO ls_swwwihead
WHERE wi_id = lv_wid_num.
* If data not found, indicates an invalid e-mail sent to offline ID
IF sy-subrc NE 0.
lv_wid = ‘INVALID WID’.
ENDIF.
* Check the status, if COMPLETED, send the notification
IF ls_swwwihead-wi_stat = ‘COMPLETED’.
TRY.
* ——– create persistent send request ————————
send_request = cl_bcs=>create_persistent( ).
* ——– create and set document ——————————-
* Build the e-mail Body
CLEAR: body_text.
CONCATENATE ‘WORK ITEM ID : ‘
lv_wid
‘is in status “COMPLETED”‘ INTO body_text SEPARATED BY space.
APPEND body_text TO ltext.
CLEAR: body_text.
CONCATENATE ‘This has already been processed ‘
‘and cannot be processed again.’ INTO body_text SEPARATED BY space.
APPEND body_text TO ltext.
document = cl_document_bcs=>create_document(
i_type = ‘RAW’
i_text = ltext
i_length = ‘510’
i_subject = ‘Work Item has already been processed’ ).
* 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.
sender = cl_sapuser_bcs=>create( ‘ECCOFFLINE’ ).
CALL METHOD send_request->set_sender
EXPORTING
i_sender = sender.
* ——— Add recipient (e-mail address) ———————–
* Create recipient – passing the receipient e-mail ID
recipient = cl_cam_address_bcs=>create_internet_address( lv_email ).
* 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 = sent_to_all ).
COMMIT WORK.
CATCH cx_bcs INTO bcs_exception.
ENDTRY.
ELSEIF ls_swwwihead-wi_stat = ‘READY’ OR
ls_swwwihead-wi_stat = ‘STARTED’.
* First process the Work Item Based on the action
IF lv_action = ‘A’.
* Set the ACTION Text
lv_action_text = ‘APPROVED’.
* If APPROVED
CALL FUNCTION ‘SAP_WAPI_DECISION_COMPLETE’
EXPORTING
workitem_id = lv_wid_func
language = sy-langu
user = sy-uname
decision_key = ‘0001’ “Approval Node
do_commit = ‘X’
IMPORTING
new_status = lv_new_status
* TABLES
* MESSAGE_LINES =
* MESSAGE_STRUCT =
.
ELSEIF lv_action = ‘R’.
* Set the ACTION Text
lv_action_text = ‘REJECTED’.
* If REJECTED
CALL FUNCTION ‘SAP_WAPI_DECISION_COMPLETE’
EXPORTING
workitem_id = lv_wid_func
language = sy-langu
user = sy-uname
decision_key = ‘0002’ “Rejection Node
do_commit = ‘X’
IMPORTING
new_status = lv_new_status
* TABLES
* MESSAGE_LINES =
* MESSAGE_STRUCT =
.
ENDIF.
* After the action now send the e-mail
TRY.
* ——– create persistent send request ————————
send_request = cl_bcs=>create_persistent( ).
* ——– create and set document ——————————-
* Build the e-mail Body
CLEAR: body_text.
CONCATENATE ‘WORK ITEM ID : ‘
lv_wid
‘has been’
lv_action_text INTO body_text SEPARATED BY space.
APPEND body_text TO ltext.
CLEAR: body_text.
CONCATENATE ‘New status of work item is ‘
lv_new_status INTO body_text SEPARATED BY space.
APPEND body_text TO ltext.
document = cl_document_bcs=>create_document(
i_type = ‘RAW’
i_text = ltext
i_length = ‘510’
i_subject = ‘Work Item processing confirmation’ ).
* 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.
sender = cl_sapuser_bcs=>create( ‘ECCOFFLINE’ ).
CALL METHOD send_request->set_sender
EXPORTING
i_sender = sender.
* ——— Add recipient (e-mail address) ———————–
* Create recipient – passing the receipient e-mail ID
recipient = cl_cam_address_bcs=>create_internet_address( lv_email ).
* 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 = sent_to_all ).
COMMIT WORK.
CATCH cx_bcs INTO bcs_exception.
ENDTRY.
ELSE.
* This means the work item is in ERROR or some exception status, NOTIFY!!!!!
* Here you can reply back to the user if they send invalid e-mails to ECCOFFLINE other then clicking on the Processing Links
TRY.
* ——– create persistent send request ————————
send_request = cl_bcs=>create_persistent( ).
* ——– create and set document ——————————-
* Build the e-mail Body based on the Work Item ID
IF lv_wid = ‘INVALID WID’.
* Build E-Mail for Invalid WID
CLEAR: body_text.
CONCATENATE ‘This system e-mail is meant only for OFFLINE WORKFLOW Processing.’
‘Please do not send any e-mails to this ID other then via Workflow Processing Offline Links.’ INTO body_text SEPARATED BY space.
APPEND body_text TO ltext.
CLEAR: body_text.
CONCATENATE ‘This is a system generated auto e-mail ‘
‘Please do not reply to this ID.’ INTO body_text SEPARATED BY space.
APPEND body_text TO ltext.
document = cl_document_bcs=>create_document(
i_type = ‘RAW’
i_text = ltext
i_length = ‘510’
i_subject = ‘System ID – Please do not reply or send E-Mail’ ).
ELSE.
* Build E-Mail body for Valid WID gone in exception status
CLEAR: body_text.
CONCATENATE ‘WORK ITEM ID ‘
lv_wid
‘might not have processed as desired.’ INTO body_text SEPARATED BY space.
APPEND body_text TO ltext.
CLEAR: body_text.
CONCATENATE ‘Please forward this e-mail to the ‘
‘System / Workflow Administrator to help you and analyze / solve it.’ INTO body_text SEPARATED BY space.
APPEND body_text TO ltext.
document = cl_document_bcs=>create_document(
i_type = ‘RAW’
i_text = ltext
i_length = ‘510’
i_subject = ‘Work Item exception might have occured’ ).
ENDIF.
* 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.
sender = cl_sapuser_bcs=>create( ‘ECCOFFLINE’ ).
CALL METHOD send_request->set_sender
EXPORTING
i_sender = sender.
* ——— Add recipient (e-mail address) ———————–
* Create recipient – passing the receipient e-mail ID
recipient = cl_cam_address_bcs=>create_internet_address( lv_email ).
* 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 = sent_to_all ).
COMMIT WORK.
CATCH cx_bcs INTO bcs_exception.
ENDTRY.
ENDIF.
* End the IF for checking valid E-Mail
ENDIF.
ENDMETHOD.
Creation of Workflow will be continued in Part-2. Kindly let me know if anything need to be added here or I missed.
Cheers
Pradyp
Hello thanks for sharing your knowledge about the Offline Mail Approval Process. Im trying to implement it but im having some troubles and some questions too:
1. The riploffline@eccdev.yourdomain.com must exist in the mail server or its not necessary to create this id email?
2. How do you create the eccdev sub domain?
3. Right now im using a fake email wfbatch@yourdomain.com, but my method PROCESS_INBOUND is not being called, is there any error with the email or do i need to create the email id and subdomain so my method is called?
4. I created a ZTEST table that is populated in both methods CREATE_INSTANCE (with a 'This is a Test Create Instance" text) and PROCESS_INBOUND (with a 'This is a Test Process Inbound" text). With the email used in point 3, somehow the ZTEST table has the 'This is a Test Create Instance" text and it looks that the class is being called but only the CREATE_INSTANCE method, and the PROCESS_INBOUND method is not being called.
Thanks for your help and sorry for my english
Hello.
Did you this Mail Approval?
I read this clause and don't understand, why need to create the new user and not use wf-batch user?
Could you share your opinion or experience about this theme please?
Thx.
Hi Cesar,
Im getting same set of issues, please let me know how you got resolved for this offline approvals.
Regards
goudham
For remaining parts.
http://scn.sap.com/docs/DOC-50457
http://scn.sap.com/docs/DOC-50458
http://scn.sap.com/docs/DOC-50532
For me the SMTP service is not getting activate after changing the port to 25 in SMICM
I have created a mail id as eccoffline@domain.co.in,
Do we need to edit something in the above programs..?
I ve tried so many times but its not working...
HiĀ vigneshwar reddy,
We have followed the complete proccess, and we are getting the mails in our outlook mail box.
Also, upon approval we get a new window with to address and subject.
but, after sending this mail to the ID, we can not see any incoming mails to SOIN T-code in SAP.
Also, my workflow is also not progressed ahead.
so, my question here is how will mail come in SAP inbound process ?
Kindly help.
Hi Pradyp,
I have the same requirment but In this code, when user going to approve the document, at that time a mail will generatedĀ then user need to click on "SEND" button.
But user just want to click approve button user dont want to click on SEND button.
i found so many artical but not able to find any solution...
Please Help!!!!!!!!!!!!!!!!!!
Regards,
Himanshu