locked
[2007][EWS] Target folder not found when copying emails from one mailbox to another RRS feed

  • Question

  • I've written some code to clone a mailbox via EWS on Exchange 2007 SP3.  The code establishes connections to the source and destination mailboxes and then walks the source mailbox folders to copy each email to the corresponding folders in the destination mailbox.   I do this by calling the Copy method on each email.

    The strange thing is that the copy step can't find the target folder on some of the mailboxes I'm testing with, even though the folder does exist.  Cloning anedza@prodigysys.com to andyqa@prodigysys.com works, but anedza@prodigysys.com to andyqa2@infotek-consulting.com doesn't.  Cloning may@infotek-consulting.com to andyqa2@infotek-consulting.com also doesn't work.  We only have one exchange server which hosts the two mail sub domains.  I believe each subdomain is stored in its own SQL database.  Both domains belong to the same active directory domain, and when you add a new user to active directory a mailbox is generate under @infgrp.local.  Such a mailbox is then manually changed into an infotek-consulting.com or prodigysys.com mailbox.

    The code runs on an IIS service account setup for Exchange impersonation to every mailbox.  The credentials passed into each mailbox are those of the impersonation service account.  The appropriate @infotek-consulting.com or @prodigysys.com email addresses of each mailbox is passed to the auto discovery service to connect to it.  I suspect the problem is happening because the mailboxes are in different mail domains.  But that doesn't account for why folders for mailboxes in the same sub domain sometimes can't be found.

    How can I diagnose if this is a permissions problem, or how can I import/export emails between mailboxes in different mail domains using EWS 2007?

    Here's the code, with the captured error below:

    //connect to exchange for the source mailbox
    ExchangeService SRCservice = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
    SRCservice.Credentials = new WebCredentials(strSRCaccount, strSRCpassword, strDomain);
    SRCservice.AutodiscoverUrl(strSRCmailbox);//connect to the exchange server by mailbox
    if (blnImpersonate == true) SRCservice.ImpersonatedUserId =
                           new ImpersonatedUserId(ConnectingIdType.SmtpAddress, strSRCmailbox);

    //connect to exchange for the destination mailbox
    ExchangeService DSTservice = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
    DSTservice.Credentials = new WebCredentials(strDSTaccount, strDSTpassword, strDomain);
    DSTservice.AutodiscoverUrl(strDSTmailbox);//connect to the exchange server by mailbox
    if (blnImpersonate == true) DSTservice.ImpersonatedUserId =
                              new ImpersonatedUserId(ConnectingIdType.SmtpAddress, strDSTmailbox);

    //get references to the folders
    SearchFilter.IsEqualTo sfFolder;
    sfFolder = new SearchFilter.IsEqualTo();
    sfFolder.PropertyDefinition = FolderSchema.DisplayName; //field to search on

    sfFolder.Value = strSRCemailFolder;
    FindFoldersResults SRCfolderItems = SRCservice.FindFolders(SRCparentFolderID,
                                                               sfFolder,
                                                               new FolderView(int.MaxValue)
                                                               { Traversal = FolderTraversal.Deep });

    sfFolder.Value = strDSTemailFolder;
    FindFoldersResults DSTfolderItems = DSTservice.FindFolders(DSTparentFolderID,
                                                               sfFolder,
                                                               new FolderView(int.MaxValue)
                                                               { Traversal = FolderTraversal.Deep });

    Folder SRCemailFolder = SRCfolderItems.Folders[0];// verified as inbox in source mailbox
    Folder DSTemailFolder = DSTfolderItems.Folders[0];// verified as inbox in destination mailbox

    //copy the emails from the current source to the current destination folders
    FindItemsResults<Item> SRCitems = SRCservice.FindItems(SRCemailFolder.Id,
                                                           new ItemView(int.MaxValue));//what we want to copy

    //copy over items from the source to the target
    foreach (Item item in SRCitems)                                                                                                               
    {                                                                                                                                                                                                                                 
        if (item is EmailMessage)                                                                                    
       {                                                                                                                                                                                     
            email = EmailMessage.Bind(SRCservice, item.Id);    
            email.Copy(DSTemailFolder.Id);                   <== target folder could not be found (line 3868)
        }
    }                        


    Service response exception:
    The specified target folder could not be found.
       at Microsoft.Exchange.WebServices.Data.ServiceResponse.InternalThrowIfNecessary()
       at Microsoft.Exchange.WebServices.Data.MultiResponseServiceRequest`1.Execute()
       at Microsoft.Exchange.WebServices.Data.ExchangeService.InternalCopyItems(IEnumerable`1 itemIds, FolderId destinationFolderId, Nullable`1 returnNewItemIds, ServiceErrorHandling errorHandling)
       at Microsoft.Exchange.WebServices.Data.ExchangeService.CopyItem(ItemId itemId, FolderId destinationFolderId)
       at Microsoft.Exchange.WebServices.Data.Item.Copy(FolderId destinationFolderId)
       at ExBook.ExBook.cloneFolder(Folder& SRCparentFolder, Folder& DSTparentFolder, ExchangeService& SRCservice, ExchangeService& DSTservice, Int32 nCopyLimit) in C:\_EXBOOK\ExBook\ExBook.svc.cs:line 3868
                                                                                      
      

     

    Wednesday, November 21, 2012 6:36 PM

All replies

  • So you say your creating a new mailbox ? The one thing that EWS won't do is initialize the default folders in a Mailbox. Eg when you create a new mailbox you have to at least send one message to it or connect via Outlook or OWA to initialize the mailbox folders.

    If your using Powershell to create the Mailbox you can add a Test-MapiConnectivity on that new mailbox which will also force creation of the default mailbox folders.  http://technet.microsoft.com/en-us/library/bb123681(v=exchg.80).aspx after you create the mailbox. (Or just send a message to it).

    Cheers
    Glen

    Thursday, November 22, 2012 6:05 AM
  • Hi Glen,

    I appreciate your response and your excellent blog.  Your posts have helped out a lot in how to use EWS.

    I think the mailboxes are initialized, as I've sent email between all of them and the EWS code is able to bind to the folders that the EWS copy methods (on items and emails) can't find.  The folder.bind method, however, references the folderid through the service objects of each mailbox (which are connected to different email domains mailbox1@infotek-consulting.com and mailbox2@prodigysys.com on the same exchange server).  The copy method, on the other hand, tries to reference the folderids using ONLY the source mailbox's service object.

    Is the service object of mailbox1 supposed to be able to reference folderids that belong to the service object of mailbox2 when its in a different email domain?

    Or, are the EWS copy commands limited to targeting folderids that only exist in the same email domain as the mailbox the copy command originates from?

    I also checked the folder.EffectiveRights flags on the target folder.  It shows the account being used has FULL CREATE, READ, MODIFY, DELETE, and mysteriously NONE rights.  None means the user has no access rights on the item or folder.  This seems to be in contradiction to the other reported rights the account seems to have (see http://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.effectiverights(v=exchg.80).aspx)

    This is confusing, Andy

    Thursday, November 22, 2012 2:17 PM
  • I think I know what's happening...

    The impersonation account I'm using is taking on the permissions of the source mailbox's user account during impersonation.  This user's mailbox account only has permissions to access their own mailbox and nobody elses.  So, when the copy happens under the impersonation account on the source mailbox, it tries to access the destination mailbox using the user's permissions which have no access rights to the target folder, even though the impersonation account on its own actually does.

    Could this be what is going wrong?  I'm in the process of testing this hypothisis, waiting to have permissions to access the target mailbox assigned to the regular user's mailbox account.

    Andy

    Thursday, November 22, 2012 3:28 PM
  • Yes the Impersonated account will need access to both source and destination to make the copy successful. The same as if you connect to Outlook as that user and tried the copy.

    Cheers
    Glen

    Friday, November 23, 2012 9:59 AM
  • Hello Glen,

    I have a similar situation. Is it even possible to copy items from one mailbox to other using a service account?

    I don't want to grant the sourcemailbox access to destination. I want to do this through a service account. 

    Monday, January 7, 2013 10:18 PM
  • >> I have a similar situation. Is it even possible to copy items from one mailbox to other using a service account?

    Yes just make sure the service account has a Mailbox and as long as you then give that account access to the source and destination mailboxes it should work okay. Or as above give it impersonation rights.

    Cheers
    Glen

    Tuesday, January 8, 2013 5:40 AM
  • My service account has a mailbox and it has impersonation permissions on both source and destination mailboxes but it still fails to copy because of the reasons mentioned above (copy happens under the impersonation account on the source mailbox, it tries to access the destination mailbox using the user's permissions which have no access rights to the target folder, even though the impersonation account on its own actually does)

    I do not want source mailbox to have access to destination mailbox. Want to do this through a service account.

    Tuesday, January 8, 2013 1:47 PM
  • In that case you will need to explicitly grant the service account rights to both the Source and Destination Mailbox.

    Cheers
    Glen

    Wednesday, January 9, 2013 5:14 AM
  • What do you mean by explicit rights? is it full mailbox access
    Wednesday, January 9, 2013 3:02 PM
  • I am also facing the same issue with copying email from one mailbox to another.

    In my case I am trying to copy the emailMessage from service account's mailbox to another user's mailbox folder (same exchange server and same domain)

    I use the following command to setup impersonation for serviceAccount

    New-ManagementRoleAssignment –Name:impersonationAssignmentName –Role:ApplicationImpersonation –User:serviceAccount

    According to MSDN http://msdn.microsoft.com/en-us/library/exchange/bb204095(v=exchg.140).aspx, this command should enable serviceAccount to impersonate all other users.

    But when I attempt to copy emailMessage from serviceAccount mailbox to destination, I get the exception

    "The specified target folder could not be found."

    Code:

    var message = EmailMessage.Bind(sourceService, messageId);

    impersonationService.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, destinationSmtpAddress);

    Folder destinationFolder = Folder.Bind(impersonationService, WellKnownFolderName....);                 
    var item = message.Copy(destinationFolder.Id);

    Any help to resolve this issue would be great.

    Or Any other alternative to copy an emailmessage from one mailbox to another using EWS would also do.

    Thanks

    Manish

    Monday, August 26, 2013 3:45 AM
  • What your doing isn't working because your still using two different user security contexts and the Copy Operation is only going to use the Security context of the user that executes it.

    For example you have User A and UserB and your trying to copy a message from UserA's Inbox to UserB Inbox. If your using Impersonation and impersonating User B then the Copy Operation is going to be working under the security context of UserB. This means user B needs to have granted Full Access (or at least Read Access to the Inbox Folder) of UserA mailbox (eg add-mailboxFolderPermission, delegation etc).

    Cheers
    Glen


    Monday, August 26, 2013 4:40 AM
  • Hi,

    the "message" variable holds a reference to its ExchangeService. when you try to make a copy to a folder in another mailbox, it uses information from the source service.

    So message.Copy(destinationFolder.Id) looks for the target id in the source mailbox.

    Regards,


    Désiré GOVIN, Refresh IT Solutions.com

    Monday, August 26, 2013 6:38 AM
  • "Target folder could not be found" is the typical message returned for security access violations.  If you are trying to access an email folder (or item) with an account that doesn't have the proper permissions, exchange will report that item as non-existant to the eyes of that account rather than tell you there was a security violation.  This is done to prevent giving hackers a way to indirectly "map" the contents of a mailbox just via security messages.

    When you use impersonation, the account you are using loses all of its own permissions and takes on the permission set of the account normally assigned to the mailbox.  When  you are copying items from one mailbox to another, the source mailbox's regular account NEEDS to have access permissions to the target mailbox, because it is this permission set that will be given to the impersonation account.

    Monday, August 26, 2013 1:11 PM
  • Glen, As Désiré GOVIN pointed out that the message.copy would work under UserA's security context as it is bound to ExchangeServiceInstance without userB impersonation.

    UserB impersonation is only used to get the destination folder ID in User B's mailbox.

    But actual copy should be done with User A as message is bound to userA mailbox.

    Let me know if I am mis-interpreting it?

    Monday, August 26, 2013 11:48 PM
  • Thank Andy.

    But the UserA (source account) is the serviceAccount which has full permissions to all the mailboxes on the exchange server.

    I had run the following to give access to serviceAccount.

    New-ManagementRoleAssignment –Name:impersonationAssignmentName –Role:ApplicationImpersonation –User:serviceAccount

    Monday, August 26, 2013 11:52 PM
  • Impersonation doesn't mean full access to all Mailboxes it means you can Impersonate a particular User (or all users) but you only do this one user at a time. So the Move/Copy will run under the Security Context of the user you're impersonating. If you're trying to copy between mailboxes the users your impersonating will need FullAccess to both mailboxes. They will have Full Access to their own Mailbox but will need to granted Access via Add-MailboxPermission or Add-MailboxFolderPermission to the other mailbox.

    Alternatively create a third account and grant that full rights to both mailboxes and use delegation 

    Cheers
    Glen

    Tuesday, August 27, 2013 8:15 AM