A quick intro
On a recent undertaking to implement email disclosure documents on external communications (i.e. email out of SAP), a problem arose in that emails generated from custom ABAP did not have the expected disclosure documents attached. We had implemented multiple disclosure documents, added conditions to ensure certain users had certain disclosures, but something wasn't working... turns out that while there may be many ways to send email in the SAP development world (FMs, ABAP Objects, Workflow, etc.) there are additional requirements when working with disclosure documents.
Before getting underway, I'd recommend you read up on transaction SODIS and get a few disclosure statements set up. Run through the content at this link:
Right... now that you're familiar with SODIS, let's push on.
As mentioned earlier, there are a few ways of generating emails in your ABAP code. SO_DOCUMENT_SEND_API1 is a popular function module for those procedural ABAPers out there, while the ABAP Objects path would lead you toward Business Communication Services (BCS) and the BCS classes, cl_bcs, cl_document_bcs, cl_send_request_bcs, and so on. As this is 2011, we'll go with ABAP Objects.
...on to the problem at hand!
I have the users 'WF-BATCH' and 'USER_TO', who will be my sender and receiver users respectively (most should be familiar with WF-BATCH already). I have also created a disclosure document in SODIS and applied a rule so that it is appended only to emails from user WF-BATCH. What I'm expecting then, is that the disclosure document is applied to all external communications from WF-BATCH.
Creating the disclosure document in SODIS.
Remeber to activate or we won't see any disclosures.
Code it up
So I created emails in my program in the following manner:
lo_bcs type ref to cl_bcs, lo_sender type ref to cl_cam_address_bcs, lo_recipient type ref to cl_cam_address_bcs, lv_ret type os_boolean. lo_bcs = cl_bcs=>create_persistent( ). lo_sender = cl_cam_address_bcs=>create_user_home_address( i_user = 'WF-BATCH' ). lo_bcs->set_sender( i_sender = lo_sender ). lo_recipient = cl_cam_address_bcs=>create_user_home_address( i_user = 'USER_TO' ). lo_bcs->add_recipient( i_recipient = lo_recipient ). * create document and add to lo_bcs with lo_bcs->set_document( lo_doc ) lv_ret = lo_bcs->send( ).
Now this code will indeed create and send an email (it will be waiting for you in SOST to be released). However, if you have configured a disclosure document for user WF-BATCH, you may be a little disappointed - the disclosure will not be appended. You'll get the standard disclosure document (if you've created one), but alas, the specific disclosure for WF-BATCH is missing in action. What to do then?
Great Scott Marty! To the Deloria... Debugger! For convenience, here are a selection of screens I prepared earlier - I've tracked code execution from the point of releasing the email in SOST, through to the selection and appending of the email disclosure document.
1. Function group SOE2, Function module SO_OBJECT_MIME_GET.
2. Subroutine GET_MIME.
3. Class method cl_bcs_send_request->as_mime_message( ).
4. Class method cl_bcs_send_request->add_disclosure_to_mime( ) [added as part of OSS Note 1086090].
5. Class method cl_disclosure_bcs->get_disclosure( ).
6. Class method cl_disclosure_bcs->resolve( ).
Here we see execution arriving at method cl_disclosure_bcs->resolve( ) where a CASE statement tries to identify the address type of the user sending this email. As you can see, it has arrived at an address type of 'INT' (Internet). Seems correct, makes sense, let's keep rolling.
No disclosure document found - defaults to standard disclosure.
A few more taps of F6 and... whoa! This select statement just executed but it didn't get our disclosure. Yikes, now what? Well, code execution continues and we get... the standard disclosure. What we wanted was WF-BATCH's disclosure. Fail.
Standard disclosure applied to email.
Lifting the fog
So what's going on here? We have configured the disclosure for WF-BATCH and checked the routing rule works in SODIS. Where are we going wrong?
CASE statement in method RESOLVE( ).
We're back in cl_disclosure_bcs->resolve( ) and as you see in the CASE statement above, there is a case condition for l_addr_type being 'B' (SAP User); remebering that just before, ours was 'INT'. So what happens if execution goes into this code block? What if the address type is 'B'? Let's try manipulating variables during debugging. Go ahead and whack a break point in method cl_disclosure_bcs->resolve( ), as I've done below.
Debugging breakpoint - line 19 TRY statement.
- Run our program to generate an email.
- Email is waiting for us in SOST. Good.
- Release said email from SOST. Better.
- We hit the breakpoint and make our switch - the address type (l_addr_type) is changed to B. Brilliant.
- Continue execution (F8).
- Check Outlook and...
WF-BATCH disclosure appended to email.
Hey presto! Our disclosure for 'WF-BATCH' is there!
That suggests then, that in order for email disclosures to be applied the address type of the sender needs to be SAP User, or 'B'.
[A small note - if you change the configuration of disclosure documents in SODIS to apply to email domains, then you can overcome this in part (provided you have different domains) but I like to use the most system-relevant means of identifying a sender, and to me, that's a username. A username is also safest, as it's rare for these to change, whereas an email address is ambiguous, non-identifying and subject to change].
Doing the hard yards
New task: to determine how we go about using SAP User address types to send emails in our ABAP code instead of Internet address types. So firstly, we need to acknowledge the class cl_cam_address_bcs doesn't allow creation of SAP User address types. It only allows the six (6) external communication types INT, X400, RML, PRT, PAG and FAX. No 'B'. Problem.
Here we get to put our OO cunning into practice - bring on the interface class.
Looking a little more closely at the section of code (method cl_disclosure_bcs->resolve) selecting disclosures, we can see that the import paramter ip_sender is an object of type ref if_sender_bcs - an interface class.
Parameter i_sender of type ref to if_sender_bcs.
Right, perfect! Now we just go and find all the other classes that implement this interface! There can't be many right?! Breath a sigh of releif - the digging is done.
Meandering through some ABAP Objects classes, we come across a class cl_sapuser_bcs that implements interface class if_sender_bcs. If my eyes do not deceive me, that class name - cl_sapuser_bcs - looks suspiciously like something we're after (remember, address type 'SAP User').
Interfaces implemented by cl_sapuser_bcs.
Interrogating the class a little further - specifically, the implemented method if_sender_bcs~address_type - we see... adress type... wait-for-it... B.
Address type 'B' returned in class method cl_sapuser_bcs->if_sender_bcs~address_type
B-B-Bingo! It appears then, that we need to be using this class to create our sender address.
Now, to the code:
lo_bcs type ref to cl_bcs, lo_sender type ref to cl_sapuser_bcs, lo_recipient type ref to cl_sapuser_bcs, lv_ret type os_boolean. lo_bcs = cl_bcs=>create_persistent( ). lo_sender = cl_sapuser_bcs=>create( 'WF-BATCH' ). lo_bcs->set_sender( i_sender = lo_sender ). lo_recipient = cl_sapuser_bcs=>create( 'USER_TO' ). lo_bcs->add_recipient( i_recipient = lo_recipient ). * create document and add to lo_bcs with lo_bcs->set_document( lo_doc ) lv_ret = lo_bcs->send( ).
Et voilà! Run our program, release the email from SOST and our email disclosure document is there, in all its glory!
WF-BATCH email disclosure document appended!
So if you find that your disclosure documents aren't being applied correctly in code-generated emails, it may be that you need to change the type of sender and receiver objects you're using.