Integration Pack: Exchange Mail

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

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

Advertisement
This entry was posted in Integration Pack and tagged , , , , . Bookmark the permalink.

37 Responses to Integration Pack: Exchange Mail

  1. Pingback: Welcome, Opalis! « PowerShell и другие скрипты

  2. Scott says:

    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.

    • randorfer says:

      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 …

      • Scott says:

        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.

      • Scott says:

        Finally got it. I used my network id & password, got the correct exchange version and then it all worked.

  3. Scott says:

    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.

  4. Leandro Amore says:

    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

    • randorfer says:

      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.

    • Scott says:

      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.

  5. M Dawood says:

    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

    • Scott says:

      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.

  6. Marc says:

    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)

  7. Andrew Katz says:

    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);
    }
    }

    • randorfer says:

      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.

  8. Andrew Katz says:

    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.

  9. Andrew Katz says:

    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

  10. Viktor says:

    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

    • randorfer says:

      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)

  11. tester says:

    hi guys !
    i need to save all attachments from exchange e-mail
    but how can i get mail ID ???

    • randorfer says:

      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

      • tester says:

        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

      • randorfer says:

        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.

  12. Donoho says:

    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?

    • randorfer says:

      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.

  13. Yasin says:

    Hi, i think you changed “find mail” with “read mail”.

  14. donoho says:

    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.

  15. Jac Pou says:

    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?

    • randorfer says:

      Hey Jac,

      I have some ideas around this let me do some testing and I will get back to you.

    • donoho says:

      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 .

      • randorfer says:

        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

      • Jac Pou says:

        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 :)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s