【问题标题】:Create Folder in other Mailbox with EWS API使用 EWS API 在其他邮箱中创建文件夹
【发布时间】:2015-12-06 10:30:43
【问题描述】:

我尝试在其他邮箱中创建联系人文件夹。由于 Powershell 无法执行此操作,因此我通过此 MSDN 站点下载了一个 c# 示例:

https://code.msdn.microsoft.com/exchange/Exchange-2013-Create-35e4948c/view/Discussions#content

然后我将 createFolder_CS.cs 修改为:

    class Ex15_CreateFolder_CS
    {
    static ExchangeService service = Service.ConnectToService(UserDataFromConsole.GetUserData(), new TraceListener());

    static void Main(string[] args)
        {
        CreateFolder(service, "Test", WellKnownFolderName.MsgFolderRoot);

        Console.WriteLine("\r\n");
        Console.WriteLine("Press or select Enter...");
        Console.Read();
        }

    static void CreateFolder(ExchangeService service, string DisplayName, WellKnownFolderName DestinationFolder)
        {
        // Instantiate the Folder object.
        Folder folder = new ContactsFolder(service);

        // Specify the name of the new folder.
        folder.DisplayName = DisplayName;

        // Create the new folder in the specified destination folder.
        folder.Save(DestinationFolder);

        Console.WriteLine("Folder created:" + folder.DisplayName);
        }
    }

更改后我启动了程序。我输入了我的电子邮件和密码,它在我的邮箱中创建了联系人文件夹。但是当我使用不同的电子邮件地址时,该程序无法运行。

我编译它并以(其他用户)域/交换管理员身份启动 exe 文件,但它仍然无法用于另一个邮箱。

所以我读了一些关于 ImpersonatedUserId 的内容,但这已经包含在程序中。

也许你可以给我一些提示,因为我是 c# 的初学者,如何使它工作?

【问题讨论】:

    标签: c# exchangewebservices impersonation


    【解决方案1】:

    您的代码的问题是您没有告诉它要将新文件夹保存在哪个邮箱中。您需要使用 FolderId 重载来指定它,或者它总是将其保存到其运行的凭据的邮箱中例如修改你的子喜欢

            static void CreateFolder(ExchangeService service, string DisplayName, WellKnownFolderName DestinationFolder,String TargetMailboxSMTPAddress)
        {
        // Instantiate the Folder object.
        Folder folder = new ContactsFolder(service);
    
        // Specify the name of the new folder.
        folder.DisplayName = DisplayName;
    
    
         FolderId ParentFolder = new FolderId(DestinationFolder,TargetMailboxSMTPAddress);
        // Create the new folder in the specified destination folder.
        folder.Save(ParentFolder);
    
        Console.WriteLine("Folder created:" + folder.DisplayName);
        }
    

    如果你想使用模拟,那么你只需要在代码中再添加一行

    service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress,TargetMailboxSMTPAddress);
    

    您需要被分配 ApplicationImpersonation RBAC 角色才能使用此https://msdn.microsoft.com/en-us/library/office/bb204095(v=exchg.140).aspx

    如果您创建一个控制台应用程序以在 poweshell 中运行,我建议您只使用 Powershell 中的托管 API,例如这里的脚本模块将使用托管 API 在邮箱中创建文件夹

    function Connect-Exchange{ 
        param( 
            [Parameter(Position=0, Mandatory=$true)] [string]$MailboxName,
            [Parameter(Position=1, Mandatory=$true)] [PSCredential]$Credentials
        )  
        Begin
             {
            Load-EWSManagedAPI
    
            ## Set Exchange Version  
            $ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2013_SP1
    
            ## Create Exchange Service Object  
            $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion)  
    
            ## Set Credentials to use two options are availible Option1 to use explict credentials or Option 2 use the Default (logged On) credentials  
    
            #Credentials Option 1 using UPN for the windows Account  
            #$psCred = Get-Credential  
            $creds = New-Object System.Net.NetworkCredential($Credentials.UserName.ToString(),$Credentials.GetNetworkCredential().password.ToString())  
            $service.Credentials = $creds      
            #Credentials Option 2  
            #service.UseDefaultCredentials = $true  
             #$service.TraceEnabled = $true
            ## Choose to ignore any SSL Warning issues caused by Self Signed Certificates  
    
            Handle-SSL  
    
            ## Set the URL of the CAS (Client Access Server) to use two options are availbe to use Autodiscover to find the CAS URL or Hardcode the CAS to use  
    
            #CAS URL Option 1 Autodiscover  
            $service.AutodiscoverUrl($MailboxName,{$true})  
            Write-host ("Using CAS Server : " + $Service.url)   
    
            #CAS URL Option 2 Hardcoded  
    
            #$uri=[system.URI] "https://casservername/ews/exchange.asmx"  
            #$service.Url = $uri    
    
            ## Optional section for Exchange Impersonation  
    
            #$service.ImpersonatedUserId = new-object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $MailboxName) 
            if(!$service.URL){
                throw "Error connecting to EWS"
            }
            else
            {       
                return $service
            }
        }
    }
    
    function Load-EWSManagedAPI{
        param( 
        )  
        Begin
        {
            ## Load Managed API dll  
            ###CHECK FOR EWS MANAGED API, IF PRESENT IMPORT THE HIGHEST VERSION EWS DLL, ELSE EXIT
            $EWSDLL = (($(Get-ItemProperty -ErrorAction SilentlyContinue -Path Registry::$(Get-ChildItem -ErrorAction SilentlyContinue -Path 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Exchange\Web Services'|Sort-Object Name -Descending| Select-Object -First 1 -ExpandProperty Name)).'Install Directory') + "Microsoft.Exchange.WebServices.dll")
            if (Test-Path $EWSDLL)
                {
                Import-Module $EWSDLL
                }
            else
                {
                "$(get-date -format yyyyMMddHHmmss):"
                "This script requires the EWS Managed API 1.2 or later."
                "Please download and install the current version of the EWS Managed API from"
                "http://go.microsoft.com/fwlink/?LinkId=255472"
                ""
                "Exiting Script."
                exit
                } 
        }
    }
    
    function Handle-SSL{
        param( 
        )  
        Begin
        {
            ## Code From http://poshcode.org/624
            ## Create a compilation environment
            $Provider=New-Object Microsoft.CSharp.CSharpCodeProvider
            $Compiler=$Provider.CreateCompiler()
            $Params=New-Object System.CodeDom.Compiler.CompilerParameters
            $Params.GenerateExecutable=$False
            $Params.GenerateInMemory=$True
            $Params.IncludeDebugInformation=$False
            $Params.ReferencedAssemblies.Add("System.DLL") | Out-Null
    
    $TASource=@'
      namespace Local.ToolkitExtensions.Net.CertificatePolicy{
        public class TrustAll : System.Net.ICertificatePolicy {
          public TrustAll() { 
          }
          public bool CheckValidationResult(System.Net.ServicePoint sp,
            System.Security.Cryptography.X509Certificates.X509Certificate cert, 
            System.Net.WebRequest req, int problem) {
            return true;
          }
        }
      }
    '@ 
            $TAResults=$Provider.CompileAssemblyFromSource($Params,$TASource)
            $TAAssembly=$TAResults.CompiledAssembly
    
            ## We now create an instance of the TrustAll and attach it to the ServicePointManager
            $TrustAll=$TAAssembly.CreateInstance("Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll")
            [System.Net.ServicePointManager]::CertificatePolicy=$TrustAll
    
            ## end code from http://poshcode.org/624
    
        }
    }
    
    function Get-FolderFromPath{
        param (
                [Parameter(Position=0, Mandatory=$true)] [string]$FolderPath,
                [Parameter(Position=1, Mandatory=$true)] [string]$MailboxName,
                [Parameter(Position=2, Mandatory=$true)] [Microsoft.Exchange.WebServices.Data.ExchangeService]$service,
                [Parameter(Position=3, Mandatory=$false)] [Microsoft.Exchange.WebServices.Data.PropertySet]$PropertySet
              )
        process{
            ## Find and Bind to Folder based on Path  
            #Define the path to search should be seperated with \  
            #Bind to the MSGFolder Root  
            $folderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$MailboxName)   
            $tfTargetFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)  
            #Split the Search path into an array  
            $fldArray = $FolderPath.Split("\") 
             #Loop through the Split Array and do a Search for each level of folder 
            for ($lint = 1; $lint -lt $fldArray.Length; $lint++) { 
                #Perform search based on the displayname of each folder level 
                $fvFolderView = new-object Microsoft.Exchange.WebServices.Data.FolderView(1) 
                if(![string]::IsNullOrEmpty($PropertySet)){
                    $fvFolderView.PropertySet = $PropertySet
                }
                $SfSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName,$fldArray[$lint]) 
                $findFolderResults = $service.FindFolders($tfTargetFolder.Id,$SfSearchFilter,$fvFolderView) 
                if ($findFolderResults.TotalCount -gt 0){ 
                    foreach($folder in $findFolderResults.Folders){ 
                        $tfTargetFolder = $folder                
                    } 
                } 
                else{ 
                    Write-host ("Error Folder Not Found check path and try again")  
                    $tfTargetFolder = $null  
                    break  
                }     
            }  
            if($tfTargetFolder -ne $null){
                return [Microsoft.Exchange.WebServices.Data.Folder]$tfTargetFolder
            }
            else{
                throw ("Folder Not found")
            }
        }
    }
    
    
    ####################### 
    <# 
    .SYNOPSIS 
     Creates a Folder in a Mailbox using the  Exchange Web Services API 
    
    .DESCRIPTION 
      Creates a Folder in a Mailbox using the  Exchange Web Services API 
    
      Requires the EWS Managed API from https://www.microsoft.com/en-us/download/details.aspx?id=42951
    
    .EXAMPLE
        Example 1 To create a Folder named test in the Root of the Mailbox
         Create-Folder -Mailboxname mailbox@domain.com -NewFolderName test
    
        Example 2 To create a Folder as a SubFolder of the Inbox
         Create-Folder -Mailboxname mailbox@domain.com -NewFolderName test -ParentFolder '\Inbox'
    
         Example 3 To create a new Folder Contacts SubFolder of the Contacts Folder
         Create-Folder -Mailboxname mailbox@domain.com -NewFolderName test -ParentFolder '\Contacts' -FolderClass IPF.Contact
    
    #> 
    ########################
    function Create-Folder{
        param( 
            [Parameter(Position=0, Mandatory=$true)] [string]$MailboxName,
            [Parameter(Position=1, Mandatory=$true)] [PSCredential]$Credentials,
            [Parameter(Position=2, Mandatory=$true)] [String]$NewFolderName,
            [Parameter(Position=3, Mandatory=$false)] [String]$ParentFolder,
            [Parameter(Position=4, Mandatory=$false)] [String]$FolderClass
        )  
        Begin
         {
            $service = Connect-Exchange -MailboxName $MailboxName -Credentials $Credentials
            $NewFolder = new-object Microsoft.Exchange.WebServices.Data.Folder($service)  
            $NewFolder.DisplayName = $NewFolderName 
            if(([string]::IsNullOrEmpty($folderClass))){
                $NewFolder.FolderClass = "IPF.Note"
            }
            else{
                $NewFolder.FolderClass = $folderClass
            }
            $EWSParentFolder = $null
            if(([string]::IsNullOrEmpty($ParentFolder))){
                # Bind to the MsgFolderRoot folder  
                $folderid= new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$MailboxName)   
                $EWSParentFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
            }
            else{
                $EWSParentFolder =  Get-FolderFromPath -MailboxName $MailboxName -service $service -FolderPath $ParentFolder
            }
            #Define Folder Veiw Really only want to return one object  
            $fvFolderView = new-object Microsoft.Exchange.WebServices.Data.FolderView(1)  
            #Define a Search folder that is going to do a search based on the DisplayName of the folder  
            $SfSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName,$NewFolderName)  
            #Do the Search  
            $findFolderResults = $service.FindFolders($EWSParentFolder.Id,$SfSearchFilter,$fvFolderView)  
            if ($findFolderResults.TotalCount -eq 0){  
                Write-host ("Folder Doesn't Exist")  
                $NewFolder.Save($EWSParentFolder.Id)  
                Write-host ("Folder Created")  
            }  
            else{  
                Write-error ("Folder already Exist with that Name")  
            }  
    
    
         }
    }
    

    【讨论】:

    • 感谢您的回答,我会尽快尝试您的解决方案。
    • Powershell 脚本真的很酷。我导入了模块,但不幸的是,当我尝试此操作时收到错误:Create-Folder -Mailboxname mailbox@mydomain.com -NewFolderName PStest -ParentFolder '\Contacts' -FolderClass IPF.Contact
    • 这是错误PSCredential : Unable to find type [PSCredential]: make sure that the assembly containing this type is loaded.。好像我必须再加载一个模块?
    • 好的,我终于让它运行起来了。它仅适用于 Powershell(而不是 Exchange Mangement Shell),并且您需要对邮箱具有完全访问权限。还必须修改此行 $ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::ExchangeVERSION-OF-THE-EXCHANGE-SERVER msdn.microsoft.com/en-us/library/… 和行 $uri=[system.URI] "https://owa.URL-TO-THE-SERVER/ews/exchange.asmx"。现在一切正常。再次感谢您的大力帮助。 :)
    • @Glen,这真的很有用。我无法弄清楚这一点,它一直在多个应用程序中引起问题。我几乎希望 EWS 没有默认为主邮箱,并强迫您知道并指定要在哪个邮箱中创建文件夹。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-11
    • 2011-03-31
    相关资源
    最近更新 更多