none
DotNetMethodException error on $mail.SendAndSaveCopy() RRS feed

  • Question

  • Keep getting this error on my Exchange 2010 SP1 Lab. I am tring to run the script below to send email via powershell:

    Error:

    [PS] C:\Mailgen>.\test.ps1
    Exception calling "SendAndSaveCopy" with "0" argument(s): "The request failed. The underlying connection was closed: An unexpected error occurred on a send." At C:\Mailgen\test.ps1:32 char:22
    + $mail.SendAndSaveCopy <<<< ()
        + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
        + FullyQualifiedErrorId : DotNetMethodException

    Script:

    #Script references
    #
    #Mike Pfeiffer
    #URL: http://www.mikepfeiffer.net/2010/04/sending-email-with-powershell-and-the-ews-managed-api/
    #

    #EWS Managed API
    #URL: http://www.microsoft.com/downloads/details.aspx?FamilyID=C3342FB3-FBCC-4127-BECF-872C746840E1&amp;displaylang=en&displaylang=en

    $dllfolderpath = "C:\Program Files\Microsoft\Exchange\Web Services\1.2\Microsoft.Exchange.WebServices.dll"

    Add-Type -Path $dllfolderpath

    $sid = [System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value
    $user = [ADSI]"LDAP://<SID=$sid>"

    $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService
    $service.AutodiscoverUrl($user.Properties.mail)

    $PrimarySmtpAddress = "user@test.com"

    if($PrimarySmtpAddress.GetType().fullname -eq "Microsoft.Exchange.Data.SmtpAddress") {
        $Recipient = $PrimarySmtpAddress.ToString()
    }
    else {
        $Recipient = $PrimarySmtpAddress
    }
    $mail = New-Object Microsoft.Exchange.WebServices.Data.EmailMessage($service)
    $mail.Subject = "Test"
    $mail.Body = "Test"
    [Void] $mail.ToRecipients.Add($Recipient)
    $mail.SendAndSaveCopy()



    Stephane Favre

    Monday, May 28, 2012 2:20 PM

Answers

  • To get more information on the error try using this after you run the script

    $error[0] | fl -force

    I would say what you will probably see in the detail of the error is "There is no Runspace available to run scripts in this thread". Something was changed between version 1.1 and 1.2 of the managed api that seems to affect delegates in Powershell so if you want to run this in an environment where you don't have proper registered SSL certs you need to use a v1 workaround for delegates like this.

    ## 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
    
    $dllfolderpath = "C:\Program Files\Microsoft\Exchange\Web Services\1.2\Microsoft.Exchange.WebServices.dll"
     
    Add-Type -Path $dllfolderpath
     
    $sid = [System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value
     $user = [ADSI]"LDAP://<SID=$sid>"
     
    $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService
     $service.AutodiscoverUrl($user.Properties.mail)
     
    $PrimarySmtpAddress = "user@test.com"
     
    if($PrimarySmtpAddress.GetType().fullname -eq "Microsoft.Exchange.Data.SmtpAddress") {
         $Recipient = $PrimarySmtpAddress.ToString()
     }
     else {
         $Recipient = $PrimarySmtpAddress
     }
     $mail = New-Object Microsoft.Exchange.WebServices.Data.EmailMessage($service)
     $mail.Subject = "Test"
     $mail.Body = "Test"
     [Void] $mail.ToRecipients.Add($Recipient)
     $mail.SendAndSaveCopy()
    Cheers
    Glen

    • Marked as answer by stephanef Tuesday, May 29, 2012 9:11 AM
    Tuesday, May 29, 2012 6:38 AM
  • If you haven't got SP2 you need to make sure you specify the version where you create the service object eg

    ## Set Exchange Version  
    $ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP1  
      
    ## Create Exchange Service Object  
    $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion)  
    Cheers
    Glen
    • Marked as answer by stephanef Tuesday, May 29, 2012 9:11 AM
    Tuesday, May 29, 2012 7:35 AM

All replies

  • Hi Stephane,

    Have you verified that the EWS url you receive by the autodiscover service is correct and you can access it?

    "$service.url" should show you the endpoint url your script will use. Try to access the url with IE and check if certificate errors appear etc.

    Best Regards

    Timo

    Monday, May 28, 2012 3:04 PM
  • ok checked the certs, corrected it by adding the exchange cert to the Trusted Root Certificate Autohority on the Exchange server.

    Tested with test-webservicesconnectivity PS CMDlet... get the following:

    [PS] C:\Mailgen>Test-WebServicesConnectivity

    CasServer  LocalSite     Scenario        Result  Latency(MS) Error
    ---------  ---------     --------        ------  ----------- -----
    cptex001   Default-Fi... GetFolder       Success       15.62
    cptex001   Default-Fi... SyncFolderItems Success       31.25
    cptex001   Default-Fi... CreateItem      Success       31.25
    cptex001   Default-Fi... SyncFolderItems Success       15.62
    cptex001   Default-Fi... DeleteItem      Success       31.25
    cptex001   Default-Fi... SyncFolderItems Success       31.25

    However still get the same error.

    [PS] C:\Mailgen>.\test.ps1
    Exception calling "SendAndSaveCopy" with "0" argument(s): "The request failed. The underlying connection was closed: An unexpected error occurred on a send."
    At C:\Mailgen\test.ps1:32 char:22
    + $mail.SendAndSaveCopy <<<< ()

        + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
        + FullyQualifiedErrorId : DotNetMethodException

    Thanks


    Stephane Favre

    Monday, May 28, 2012 6:31 PM
  • To get more information on the error try using this after you run the script

    $error[0] | fl -force

    I would say what you will probably see in the detail of the error is "There is no Runspace available to run scripts in this thread". Something was changed between version 1.1 and 1.2 of the managed api that seems to affect delegates in Powershell so if you want to run this in an environment where you don't have proper registered SSL certs you need to use a v1 workaround for delegates like this.

    ## 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
    
    $dllfolderpath = "C:\Program Files\Microsoft\Exchange\Web Services\1.2\Microsoft.Exchange.WebServices.dll"
     
    Add-Type -Path $dllfolderpath
     
    $sid = [System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value
     $user = [ADSI]"LDAP://<SID=$sid>"
     
    $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService
     $service.AutodiscoverUrl($user.Properties.mail)
     
    $PrimarySmtpAddress = "user@test.com"
     
    if($PrimarySmtpAddress.GetType().fullname -eq "Microsoft.Exchange.Data.SmtpAddress") {
         $Recipient = $PrimarySmtpAddress.ToString()
     }
     else {
         $Recipient = $PrimarySmtpAddress
     }
     $mail = New-Object Microsoft.Exchange.WebServices.Data.EmailMessage($service)
     $mail.Subject = "Test"
     $mail.Body = "Test"
     [Void] $mail.ToRecipients.Add($Recipient)
     $mail.SendAndSaveCopy()
    Cheers
    Glen

    • Marked as answer by stephanef Tuesday, May 29, 2012 9:11 AM
    Tuesday, May 29, 2012 6:38 AM
  • now I get this:

    [PS] C:\Mailgen>.\testnew.ps1At
    Exception calling "SendAndSaveCopy" with "0" argument(s): "Exchange Server doesn't support the requested version."
    C:\Mailgen\testnew.ps1:55 char:23
    +  $mail.SendAndSaveCopy <<<< ()
        + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
        + FullyQualifiedErrorId : DotNetMethodException


    Stephane Favre

    Tuesday, May 29, 2012 7:31 AM
  • If you haven't got SP2 you need to make sure you specify the version where you create the service object eg

    ## Set Exchange Version  
    $ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP1  
      
    ## Create Exchange Service Object  
    $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion)  
    Cheers
    Glen
    • Marked as answer by stephanef Tuesday, May 29, 2012 9:11 AM
    Tuesday, May 29, 2012 7:35 AM
  • YAY its workinging!! so the solution was 2 fold, firstly the run environment and then the exchange version for service object

    Stephane Favre

    Tuesday, May 29, 2012 9:11 AM