Introduction
I have created an Exchange Mail Integration Pack for Opalis. This integration pack is built on the Microsoft.Exchange.Webservices (EWS) Managed API 1.1. As such it requires no additional dependencies. This project is hosted on Codeplex and is being released under the CDDL so feel free to take the code and modify / contribute! No warranties are given, either expressed or implied, look at the code and test it for yourself! The main purpose of this integration pack is mail manipulation (reading, searching, moving, deleting etc). This integration pack will work with Exchange 2007 SP1, Exchange 2010, and Exchange 2010 SP1.

http://opalisexchangemail.codeplex.com/
Objects
The project includes objects for the following actions
- Delete Mail
- Read Mail
- Monitor Mailbox
- Move Mail
- Read Mail from Folder
- Create Folder
- Delete Folder
- Empty Folder
- Find Folder
- Get Attachments
- Send Email
Delete Mail

Inputs
- Email ID: The id of the email you would like to delete. This can be found using the ‘Find Mail’ object. The Monitor Mailbox and Read Mail from Folders also return the ID of all email messages they return.
-
Delete Mode
- Hard Delete
- Soft Delete
- Move to Deleted Items
Actions
- Does a delete on the email
Find Mail


Inputs
-
Search Field (what email field would you like to search on)
- Subject
- From
-
Search Algorithm (what criteria you would like to match on)
- Equals
- Contains String
- Does not Equal
- Search String (the string you would like to search the select field for based on your selected algorithm)
Outputs
- Attachments – Boolean, if there is an attachment or not
- From
- Subject
- Body
- ReceivedDate
- ID – Unique exchange ID for this email. Use for passing to other workflows that need this
Monitor Mailbox


Inputs
- Folder Name: The name of the folder in the mailbox you would like to monitor
- Polling Interval: How often to poll your exchange server for new emails. I would suggest doing this no more often than every minute
Outputs
-
This monitor checks every defined interval for newly modified emails in the supplied folder and returns the following information
- Body
- From
- Subject
- Id
- Received Date
- Attachments
- Number of Emails: The number of emails found
Move Mail

Inputs
- Email ID: The id of the email you would like to delete. This can be found using the ‘Find Mail’ object. The Monitor Mailbox and Read Mail from Folders also return the ID of all email messages they return.
- Destination Folder: The name of the folder you would like to move the email to.
Actions
- Moves the Email ID to the Destination Folder
Read Mail


Inputs
- Folder Name: The name of a specific folder in the mailbox to monitor.
- Number of Emails: The maximum number of emails to return. (Optional Property, will return all mail in folder by default)
Outputs
-
This monitor will return the first X number of emails in the folder where X is the “Number of Emails” supplied in the input. The following information is returned
- Body
- From
- Subject
- Id
- Received Date
- Attachments
- Number of Emails: The number of returned Emails
Get Attachments

Inputs
- Email ID: The ID of the email to download the attachments from
- Save Location: The location to save the file to. I suggest a network share. Must be somewhere your action servers can all access
Outputs
- File Name: Name of the Attachment downloaded
- File Location: Path to the file (Save location)
Actions
- Downloads all attachments of a given email to the Save Location
Send Email

Inputs
- Subject
-
Recipients
- Separate multiple Recipients with ;
- Joe.User@Contoso.com;Jim.User@Contoso.com
- Body
-
Importance Level
- Normal
- High
- Low
-
Attachment File Locations
- Path to file to attach. Separate multiple attachements with ;
- \\constoso.com\share\this.txt;\\contoso.com\share\that.txt
Actions
- Sends the email to the destination.
Find Folder

Inputs
-
Search Field
- Folder Name
- Folder ID
- Search String
Outputs
- Folder Name
- Folder ID
- Parent Folder ID
Create Folder
Inputs
- Folder Name: Name of the new Folder
- Parent Folder Name: Name of the folder you would like to put this folder under. Not required (defaults to inbox)
- Parent Folder ID: The ID of the folder you would like to put this folder under. Overrides Parent Folder Name if both are present. Not required
Actions
- Creates a new folder
Delete Folder

Inputs
- Folder Name
- Folder ID: Optional (Overrides Folder Name if present)
Actions
- Deletes the first folder found matching Folder Name. If Folder ID was used deletes that specific folder
Empty Folder

Inputs
- Folder Name
- Folder ID: Optional (Overrides Folder Name if present)
Actions
- Deletes all contents of the first folder found matching Folder Name. If Folder ID was used it deletes all contents of that specific folder
- Very efficient if it is an Exchange 2010 SP1 mailbox (one action). Otherwise this loops and deletes all individual items one by one
Pingback: Welcome, Opalis! « PowerShell и другие скрипты
Does Microsoft.Exchange.Webservices (EWS) Managed API 1.1. need to be installed on the exchange server, the opalis server??. I downloaded and installed the OIP, see the objects, but when I click on the … in the configuration section of the monitor mailbox I get nothing.
Hey Scott,
You need to setup a mailbox configuration first. Go up to Opalis menu bar and click Options -> Exchange Mail and add a new mailbox configuration. Then when you use an object you will be able to select that mailbox configuration using the …
Thanks – getting closer I think. I am getting this error.
The Autodiscover service couldn’t be located when I use the Read Mail task.
For the configuration what is the username, my networkid or my email address (i.e. scott.sisson@mydomain.com)
For password I am using my network password
For domain I am using mydomain.
Finally got it. I used my network id & password, got the correct exchange version and then it all worked.
If you want to build another OIP – FTP would be useful. I hear the current FTP OIP from 6.2.2 is not available in 6.3. I use FTP a lot to push files around.
Hi scott, i am trying to use the get attachment feature with no luck. I placed a monitor mailbox and pass the ID of the incoming message to the get attachment task. But the attachment is always saved with 0 bytes.
I tried changing the extension and content of the file with the same result. Any ideas?
best regards
Leandro
Hey Leandro,
What version of the IP are you using? The most up to date version is v1.4. What version of exchange? The save location for the object should be a path to an existing folder that all attachments of the specified email will be downloaded to. Make sure that this path makes sense to your actions servers (network paths / shares are best). I just tested this with exchange 2007 sp1 and the latest version of the IP and had success.
I did not do anything fancy. Like you did, I have a monitor mailbox (every 2 minutes) and use the email id property which is the “ID from Monitor mailbox) and save location is “c:\test\exchange”. I left the link from monitor mailbox to Get attachments at the default. Ultimately, I will add a condition to the link i.e. if attachments from monitor = true the get the attachment and then do something the attachment. The final work flow will be to move the email body & attachments to a sharepoint list based on the domain of the sender. Not sure if I need a seperate app to do this or if I can just use the web service task.
Hi Guys,
What do i need to configure this pack in Opalis. I installedd the pack but it keeps stopping when i create a Monitor Mailbox Policy.
What do i need to install on teh Opalis Server.
Do i need to isntall the Exchange Client ?
Please help.
MD
randorfer response on
March 10, 2011 at 4:16 pm
above. I think I was having the same issue prior to this. I think you need to have a value in the configuration box of the task.
Hello,
i have configured the settings “Options”->”Exchange”.
Username : windows Username
Password and Domain (Netbios Domain Name).
Also selceted Exchange 2010SP1.
After that created policy. I get an error by “Read Mail”, see below.
I have tested Autodiscovery with my local Outlook, everything seems to be ok.
We are using german exchange version.
Can you help us?
Thank you
Regards
———-Error:
The Autodiscover service returned an error.
Exception: AutodiscoverRemoteException
Target site: AutodiscoverService.InternalGetLegacyUserSettings
Stack trace:
bei Microsoft.Exchange.WebServices.Autodiscover.AutodiscoverService.InternalGetLegacyUserSettings[TSettings](String emailAddress, List`1 redirectionEmailAddresses, Int32& currentHop)
bei Microsoft.Exchange.WebServices.Autodiscover.AutodiscoverService.GetLegacyUserSettings[TSettings](String emailAddress)
bei Microsoft.Exchange.WebServices.Autodiscover.AutodiscoverService.InternalGetLegacyUserSettings(String emailAddress, List`1 requestedSettings)
bei Microsoft.Exchange.WebServices.Autodiscover.AutodiscoverService.GetUserSettings(String userSmtpAddress, UserSettingName[] userSettingNames)
bei Microsoft.Exchange.WebServices.Data.ExchangeService.GetAutodiscoverUrl(String emailAddress, ExchangeVersion requestedServerVersion, AutodiscoverRedirectionUrlValidationCallback validateRedirectionUrlCallback)
bei Microsoft.Exchange.WebServices.Data.ExchangeService.AutodiscoverUrl(String emailAddress, AutodiscoverRedirectionUrlValidationCallback validateRedirectionUrlCallback)
bei Microsoft.Exchange.WebServices.Data.ExchangeService.AutodiscoverUrl(String emailAddress)
bei ExchangeMail.ReadMail.Execute(IOpalisRequest request, IOpalisResponse response)
Hey,
I should be able to take a quick look at this over the weekend, its been pretty crazy around here since MMS
Hello,
I have run into a bug in your Get Attachments task. I need to reference a saved attachment in a child policy, but when I try to operate on the file, it says it is in use by another process. In your getAttachments method (below), please ensure that the filestream is closed so that it can be used in another process.
Thanks!
private IEnumerable getAttachments(EmailMessage message)
{
foreach (FileAttachment iteratorVariable0 in message.Attachments)
{
iteratorVariable0.Load();
new FileStream(this.SaveLocation + @”\” + iteratorVariable0.Name.ToString(), FileMode.Create).Write(iteratorVariable0.Content, 0, iteratorVariable0.Content.Length);
yield return new SavedAttachment(iteratorVariable0.Name.ToString(), this.SaveLocation);
}
}
Thanks for the heads up. Updated the code
private IEnumerable getAttachments(EmailMessage message)
{
foreach(FileAttachment attach in message.Attachments)
{
attach.Load();
FileStream fs = new FileStream(SaveLocation + "\\" + attach.Name.ToString(),FileMode.Create);
fs.Write(attach.Content, 0, attach.Content.Length);
fs.Close();
fs.Dispose();
yield return new SavedAttachment(attach.Name.ToString(), SaveLocation);
}
}
I will test and wrap / update the integration pack on codeplex on Monday.
codeplex updated with new version (v1.5) of the IP. http://opalisexchangemail.codeplex.com/releases/view/65954
Thanks for the quick turn around. Is there any way you can issue a patch to the OIP instead of releasing a brand new OIP? After installing 1.5, I now need to replace all of the tasks that use the 1.4 OIP, and that is a ton of work.
Ryan,
I’ve ran into another bug with GetAttachments. This time is because message.Attachments can be of type FileAttachment or ItemAttachment. If an email is attached to an email, there will be an invalid cast exception.
I have the solution coded and tested, but don’t want to deviate from your code train. Feel free to reach out to me at ak “at” interclick “dot” com and I can share the code with you.
Thanks,
Andrew
Hello
I try to connect to my Exchange mailbox
all the time an error
The request failed. The remote server returned an error: (440) Login Timeout.
Exception: ServiceRequestException
Target site: ServiceRequestBase.ValidateAndEmitRequest
Stack trace:
at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.ValidateAndEmitRequest(HttpWebRequest& request)
at Microsoft.Exchange.WebServices.Data.SimpleServiceRequestBase.InternalExecute()
at Microsoft.Exchange.WebServices.Data.MultiResponseServiceRequest`1.Execute()
at Microsoft.Exchange.WebServices.Data.ExchangeService.CreateFolder(Folder folder, FolderId parentFolderId)
at Microsoft.Exchange.WebServices.Data.Folder.Save(FolderId parentFolderId)
at ExchangeMail.CreateFolder.Execute(IOpalisRequest request, IOpalisResponse response)
Profile Configuration:
user name: domain user
exchange version: exchange 2007 sp1
pass: my pass
domain: mydomain
service url: https://mail.mydomain.com/owa
Hey Viktor,
The problem (as you probably have figured out) has to do with the profile you are connecting with. To clarify a bit I will spell out what I expect for the different config fields.
User Name: The sAMAccount Name of the mailbox user you are connecting as. For example if you had a user with a UPN of “abc12345@mydomain.com” I would expect “abc12345″ to be entered into this field
Exchange Version: Choose one of the options from the list provided. “Exchange2007_SP1″ looks like what you want
Password: The password of the user provided
Domain: The domain of the User specified. Using the above user I would expect “mydomain.com” here
ServiceUrl: Here you have two options. Autodiscover or specifying the path to your CAS server directly. The url for your CAS server should be in the following form https://mail.Contoso.com/EWS/Exchange.asmx. You should only specify your CAS server directly if Autodiscover does not work correctly (Autodiscover is the supported way from MS of connecting to your exchange environment)
hi guys !
i need to save all attachments from exchange e-mail
but how can i get mail ID ???
Hey,
This integration pack revolves around the ‘monitor mailbox’ and ‘read email’ for doing things with email. Both of those objects will output the email id you need for downloading attachments
so if i made policy with “monitoring email” + “get attachments” all be correct ?
“get attachments” in row E-mail ID: {ID from “monitoring email”} needed ?
or what i must type in that row
Yep that is the idea! You subscribe to the published data (the email id property) from the ‘monitor email’ object in your ‘download attachments’ object.
I’ve read through documentation and comments, but haven’t seen anything about security. Everyone using the IP sees/has access to all configurations. Is there a was to secure/restrict configurations with permissions?
This is true and is true of all global configuration objects inside of Opalis and Orchestrator (not a limitation to this IP). Every global configuration is available to everyone who has authoring rights inside of Opalis. This has caused us internally to segment our environments highly. Each team has its own development environment, all dev environments roll up to a central QA environment that only the Opalis Admin team has access to and only things from that QA environment are pushed on to production. This (ability to controll who has access to what global configurations) is one of the DCRs we have open against orchestrator https://connect.microsoft.com/Opalis/feedback/details/674458/designer-cannot-assign-security-rights-to-options-menu-items please get behind this so it gets fixed and we can all simplify our Opalis environments.
Done. Too bad there’s only 3 of us so far.
Hi, i think you changed “find mail” with “read mail”.
Should Find Folder work with Public Folders? Trying to come up with some layers of abstraction in the absence of per client security. Current plan: Use and pull/parse emails from public folder, making contents available to Opalis via file system which can be secured on a per user basis. Trying to avoid creating a new ad entry/inbox for everyone that wants to parse mail.
Hey,
Right now the IP does not support the opening of public folders (not related to any one user). Can you post this request on the IP’s codeplex site so I make sure to wrap in into the version for orchestrator 2012?
-Ryan
Added: http://opalisexchangemail.codeplex.com/workitem/345
Thanks for this great OIP!
In our current setup we check a mailbox every 3 minutes for new emails in batches of 10 (and move mails for further processing). The problem is, if there are hundreds of new mails the object only picks up the 10 newest emails! So there is a theoretical possibility the first mails (in time) will never be processed if there is a continuously flow of mail.
Is there somehow a possibility to retrieve mail according to the First In, First Out principle?
Hey Jac,
I have some ideas around this let me do some testing and I will get back to you.
Thanks for the quick reply!
Great news! Thanks again for all the effort!
Just out of curiosity, Are you using the read mail object? Why doesn’t the Monitor Mailbox object handle this for you?
My current setup is in a policy that run constantly, uses the default 60 sec interval and grabs everything as it comes into the inbox. As a side note, this is not a High Volume inbox as it was created specifically for this processing and I have a requirement to save the email as well as the attachment .
The monitor mailbox object is the correct object to be using from this IP for the use case you have outlined (as Donoho pointed out). This object had a bit of a logic flaw in it that I just corrected (this change has NOT been rolled up into any integration pack yet, but will be included in future releases). Currently the monitor mailbox object will return AT MOST 100 objects (we query exchange and ask for a view that contains 100 objects in it), I have updated the object code so that it now will pull back AT MOST the largest integer value — see the change set below. I need to test this to ensure it does not adversly affect exchange.
http://opalisexchangemail.codeplex.com/SourceControl/diff/file/view/13296?fileId=40864&olderChangeSetId=6978
Good question.
Because there is a schedule in front of the read mailbox object. And behind the object are some processes which are not allowed to process the mail (service request) during evening hours and weekends (Not all (external) systems are available).
The monitor object doesn’t handle mail First In First Out either (the mailbox will receive considerable amounts of mail).
On top of that; a mail needs to be fully processed (automated back-office processes) before the next one can be handled. The process outcome of the first mail can change the way a next one should be handled.
e.g. A customer changes his address (through mail), after this he makes his order during the weekend. If the order mail is processed first on Monday morning, it is send to the wrong address