none
Using Exchange webservice API to save sent email on local drive RRS feed

  • Question

  • Currently i have used exchange2010 to save the incoming email on my local drive with specified search criteria as soon as they arrive with the  "connection.OnNotificationEvent" even and i have used "EventType.NewMail:" for new emails.

    The new email whatever arrive saved successfully to my local drive into specific folder and now my requirement is to save the sent emails and i struggled a lot and could not find any event which will be fired as soon as any email sent from the mailbox.

    Code as below to save incoming emails:

     ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010_SP1);
                //service1.Credentials = new NetworkCredential("{Active Directory ID}", "{Password}", "{Domain Name}");
                service1.Credentials = new NetworkCredential(strUsername, strPassword, strDomain);
                service1.AutodiscoverUrl(strAutodiscoverUrl);


                //Mailbox mb = new Mailbox("artur.kedzior@ext.oami.europa.eu");
                Mailbox mb = new Mailbox(strAutodiscoverUrl);
                FolderId fid1 = new FolderId(WellKnownFolderName.Inbox, mb);

     foreach (NotificationEvent notification in args.Events)
                {

                    switch (notification.EventType)
                    {
                        case EventType.NewMail:
                            
                            foreach (EmailMessage message in service1.FindItems(fid1, searchFilter, new                       ItemView(int.MaxValue)))
                            {
                                if (message.ToRecipients.Count > 0)
                                {
                                    strToRecepient = message.ToRecipients[0].Name;
                                }

                                    message.Load(new PropertySet(ItemSchema.MimeContent));
                                    MimeContent mc = message.MimeContent;
                                    path = folderdrive + folderName + "\\" + strFileName;
                                    FileStream fs = new FileStream(path, FileMode.Create);
                                    fs.Write(mc.Content, 0, mc.Content.Length);
                                    fs.Close();

                                }
                            }
                            break;
                      }

               }

    Please let me know what is the way to save sent email with EWS or any alternative aproach with sample code to do so.Thanks a million in advance.

    Sunday, February 24, 2013 5:44 AM

All replies

  • The NewMail event will only work for new mail submitted by the store to the inbox. For Sent email you should be able to subscribe to the CreatedEvent on the SentItems folder. You can test this easliy using EWSEditor http://ewseditor.codeplex.com/ and the Streaming Notifications Viewer.

    Cheers
    Glen

    Monday, February 25, 2013 4:39 AM
  • >> ,i did checked for created event and it dont work for sent emails from the Inbox

    That would be the first mistake messages are never sent from the Inbox, When you send a message (and specify the save a copy) then a copy would get saved to the SentItems folder. So you need to monitor events on the SentItems Folder not the Inbox.

    (You not showing your subscription code either that's what needs to be modified)

    Cheers
    Glen

    Tuesday, February 26, 2013 6:17 AM
  • Hi Glen,

    Appreciate your help till now.And yes you are right for inbox it will never work .

    Able to get my created event fired after changing the subscription from SubscribeToStreamingNotifications to SubscribeToStreamingNotificationsOnAllFolders.Correct me if i am worng .

    Now what is happening when i get email in Indbox than also first create event fired and than NewEmail and i think Create events should not fired.And when i sent an email than it goes to create event only.

    Further to add related to sent email , when i try to extract the sent message its looping through all the sent messages,ofcourse since the whole Sent folder has been included .I want to get the latest sent message.Please if you can tell me what condition i should use to retrieve the sent message as soon as its sent by the user.Since my requirement is to save sent email to local drive folder with some specific criteria.

    My Code below:

    private void SetSubscription()
            {
                if (service == null)
                {
                    SetService();
                }

                // Subscribe to streaming notifications on the Inbox folder, and listen 
                // for "NewMail", "Created", and "Deleted" events. 
               streamingsubscription = service.SubscribeToStreamingNotificationsOnAllFolders(
                    EventType.NewMail,
                    EventType.Created,
                    EventType.Deleted);

                StreamingSubscriptionConnection connection = new StreamingSubscriptionConnection(service, 30);

                connection.AddSubscription(streamingsubscription);

                // Delegate event handlers. 
                connection.OnNotificationEvent +=
                    new StreamingSubscriptionConnection.NotificationEventDelegate(OnEvent);
                connection.OnSubscriptionError +=
                    new StreamingSubscriptionConnection.SubscriptionErrorDelegate(OnError);
                connection.OnDisconnect +=
                    new StreamingSubscriptionConnection.SubscriptionErrorDelegate(OnDisconnect);
                connection.Open();

            }


     void OnEvent(object sender, NotificationEventArgs args)
            {

                string path = string.Empty;
                StreamingSubscription subscription = args.Subscription;

                ExchangeService service1 = new ExchangeService(ExchangeVersion.Exchange2010_SP1);
                service1.Credentials = new NetworkCredential(strUsername, strPassword, strDomain);
                service1.AutodiscoverUrl(strAutodiscoverUrl);

                Mailbox mb = new Mailbox(strAutodiscoverUrl);
               

                // Loop through all item-related events. 
                foreach (NotificationEvent notification in args.Events)
                {
                    switch (notification.EventType)
                    {
                        case EventType.NewMail:


                            FolderId fid1 = new FolderId(WellKnownFolderName.Inbox, mb);
                            if (folderdrive == string.Empty)
                            {
                                folderdrive = ConfigurationManager.AppSettings["FolderDrive"];
                            }

                            SearchFilter.SearchFilterCollection searchFilter = new SearchFilter.SearchFilterCollection();
                            searchFilter.Add(new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false));
                            //foreach (EmailMessage message in service1.FindItems(WellKnownFolderName.Inbox, searchFilter, new ItemView(int.MaxValue)))
                            foreach (EmailMessage message in service1.FindItems(fid1, searchFilter, new ItemView(int.MaxValue)))
                            {
                                if (message.ToRecipients.Count > 0)
                                {
                                    strToRecepient = message.ToRecipients[0].Name;
                                }

                                    message.Load(new PropertySet(ItemSchema.MimeContent));
                                    MimeContent mc = message.MimeContent;
                                    
                                }
                            }
                            break;
                        case EventType.Created:


                            FolderId fid2 = new FolderId(WellKnownFolderName.SentItems, mb);

                            if (folderdrive == string.Empty)
                            {
                                folderdrive = ConfigurationManager.AppSettings["FolderDrive"];
                            }

                            SearchFilter.SearchFilterCollection searchFilter2 = new SearchFilter.SearchFilterCollection();
                            
                            
                            foreach (EmailMessage message in service1.FindItems(fid2,  new ItemView(int.MaxValue)))
                            {
                                if (message.ToRecipients.Count > 0)
                                {
                                    strToRecepient = message.ToRecipients[0].Name;
                                }

                                    message.Load(new PropertySet(ItemSchema.MimeContent));
                                    MimeContent mc = message.MimeContent;
                                 }
                            }
                            break;
                        case EventType.Deleted:
                            Console.WriteLine("\n-------------Item or folder deleted:-------------");
                            break;
                    }


    Thanks







    • Edited by MehulGupta Wednesday, February 27, 2013 10:13 AM
    Tuesday, February 26, 2013 6:58 AM
  • No that's correct the Create event will get fired also, if your using notifications you will get multiple notifications for the same item for a number of reasons, the best approach is just to deal with it. Notifications are just that an async service to tell you something has changed (but no real specific details on what other then then ItemId) they are not something you can create very tight logic around for this you should use the SyncFolderItems operation etc.

    Easiest way to get the last sent item is just set the ItemView to 1 EWS will always return the latest item unless you give it a sort order or searchfilter.

    Cheers
    Glen

    Wednesday, February 27, 2013 5:35 AM
  • Thanks Glen.

    Ok now problem i am facing is Create event always fired and i want to avoid it when email is received.

    The reason is i have done coding for SentItem on Created event and it gets fired both on Inbound and outbound emails and looking for someway i could avoid its call while receiving email.

    Also another issue when i fetch the latest sent email as per your instruction sometimes it misses the latest one since the email may take time to deliver.How to tackle that scenerio.

    I am building this to save emails all received and sent emails on exchange server.I have admin account and though there could be way to make is discovery email and when i hit this email it will fetch all the emails whatever sent received on multiple mailboxes ,is there any limitaion in EWS or do i need to go for Transport Agent as the only option.


    Appreciate all your help.

    Wednesday, February 27, 2013 9:48 AM
  • >> Ok now problem i am facing is Create event always fired and i want to avoid it when email is received.

    You can't avoid an Notification you can ignore it or don't subscribe to it eg create two subscriptions one for the Inbox for New Mail and one for the Sent Items for Create.

    >Also another issue when i fetch the latest sent email as per your instruction sometimes it misses the latest one since the >email may take time to deliver.How to tackle that scenario.

    That question doesn't really make sense, my suggestion is look at your application logic eg write the flow on a whiteboard etc. You should treat Sent Mailbox and Received mail as different things.

    >> I am building this to save emails all received and sent emails on exchange server

    A transport Agent is a much better idea as anything that is client based can never be guaranteed to catch everything (eg notifications can be missed etc). You might want to look a journaling which does exactly this and you don't need to write any code.(if you want them exported to disk you can just use the Export cmdlets).

    Cheers
    Glen

    Thursday, February 28, 2013 5:10 AM
  • Thanks Glen 

    I think for second question i did not explained you properly .The query is if i do subcription on sentitems and when the create event fires the email that is sent dont come and it shows the old sent email but if i wait for sometime and backtrack my debugger than it comes.Which means until the email stays in the outbox that email is not captured and misses out.Should i use outbox folder instead of sentitems or is there any way around for this.

    Apreciated all your help till now.
    • Edited by MehulGupta Thursday, February 28, 2013 9:59 AM correction
    Thursday, February 28, 2013 9:58 AM
  • In the notification you get there is the Id of the Item that caused the notification why don't you bind to this Id rather then making a FindItem query ? (in theory what you reporting can't happen because notifications are Async so the notification will always fire after the message has been committed to the store. There would be a time difference before it maybe available in Outlook because of Cache mode etc).

    I'd ignore the Outbox as its just a folder where things are spooled and no email should be stored there permanently.

    Cheers
    Glen

    Friday, March 1, 2013 5:39 AM
  • Hi Glen,

    After all your support and help i have developed and successfully deployed my exchange service and everything working as expected.Now there is some issue the service keep working but saving of emails locally stops after some time.Its something service stop responding to subscription and does nothing and after restart of the service everything starts working again.

    I have handled all the exceptions and dont see anything related to to failed subscription or any other error reported.

    Please need your help here as is this something to do with the Microsoft bug or do we require some setting for EWS at exchange server level also.

    Thanks a millions in advance.

    Monday, April 15, 2013 5:52 AM
  • Its doesn't sound like its a Microsoft or Exchange bug to me but its sounds more like your code isn't dealing with the subscription maintenance properly. You can't reliability count on just dealing with exceptions to ensure that you will maintain a subscription over a long period of time. You should have a background maintenance procedure that runs in the background and recreates the Subscription if you have had no response from the server within a specific timeframe. (My suggestion would be to set the timeout to 15 minutes and then recreate your subscriptions every 15 minutes, you then have manageable time period to work your logic around).

    The other thing to check maybe is if your creating a large number of subscriptions on a large number of mailboxes and using one service account then you maybe hitting the throttling limits.

    Cheers
    Glen

    Monday, April 15, 2013 6:58 AM