Thanks for all my blog readers as I got an overwhelming response for this post asking me for the code to connect using EWS and read email from Exchange Server
For starters, this is the Part 1 which gives a theoretical view of using EWS to read email without having Outlook Client on your AOS
http://daxdilip.blogspot.com/2010/12/how-to-read-email-and-download.html
This is all the code which does the job:
a. Declaration
b. Logic for reading the email for a particular email address and subject and downloading the attachment
As you have seen the code above is very self-explanatory as it calls the Exchange Service proxy to do a FindItems for the mailbox folder (Inbox) and for a particular subject.
The next part in code is where it loops through the item collection and if it finds an attachment for the message item, it will download the attachment to the path supplied.
Limitations:
a. I tried to directly invoke the code from AX by adding the Exchange Service Assembly to the Resources node in AOT, but I'm unable to marshall the complex types and generics between X++ and .Net, Also the class ContainsSubstring is an abstract implementation in .Net which I'm unable to get a handle via X++, so I had to write a custom .Net wrapper and then call this from X++.
b. The X++ code which invokes my custom .Net assembly works fine without any issues if it's run via a job or class or menu item but as soon as I put it in a batch it doesn't work. It just fails without any error log.
[Update] I was able to track the error (CLR Exception: "When making a request as an account that does not have a mailbox, you must specify the mailbox primary SMTP address for any distinguished folder Ids") which was caused due to impersonation as the batch job was running under the AOS Service account and not the mailbox account, once I wrote the impersonation code using System.Net.Credentials in my .Net code, it works now without any issues.
Hi Dilip,
ReplyDeletecool post. it's a shame the generic lists are not supported in AX...
to make your batch work you'd need to check a few thins:
first of all, your dll has to be installed on the AOS (best in GAC) - because the code is being executed there...
to catch your exception (you're not getting any info now) use try/catch construct and add a exception::CLRError. in this exception add code e.g.:
error(AIFUtil::getClrErrorMessage());
then you need to implement all trustworthy computing stuff; assert permission for CLR-Interop everytime you talk to al DLL over CLR. this will look like this:
new InteropPermission(InteropKind::ClrInterop).assert();
//your Code to talk to the dll
CodeAccessPermission::revertAssert();
hope this helps...
cheers
Daniel
Thanks a lot Daniel for your comment. It really helped me in debugging the error, I was not aware of the AIFUtil::getClrErrorMessage(), Once I caught the exception in my try catch block, it displayed the actual error message regarding the impersonation issue. Thanks again.
ReplyDeleteI understand this problem, reason of I ran across like problem couple weeks ago. Then I could solve out it owing to the next tool, which I had found out at one soft forum. Besides it demonstrated all its capabilties for working out almost every issue related to ms exchange - recover stm files.
ReplyDelete
ReplyDeleteKeep me up great work.Thanks for sharing!
IT Support Los Angeles