Search code examples
powershellsmtppowershell-cmdlet

Using powershell function Send-MailMessage getting an error: Cannot find an overload for "PSCredential"


I want to send an email via powershell using function Send-MailMessage.

My smtp server requires UserName and Password.

I am passing it as parameters, however getting an error.

 $CredUser = "123UserPass"
 $CredPassword = "1234/5678/999"
 $Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $CredUser, $CredPassword
 Send-MailMessage -SmtpServer "smtp.amazonaws.com" -Port 587 -Credential $Credential -UseSsl -From 'DBATeam@email.com' -To 'me@email.com' -Subject 'TEST'

Error message:

New-Object : Cannot find an overload for "PSCredential" and the argument count: "2".
At line:3 char:16
+ ... redential = New-Object -TypeName System.Management.Automation.PSCrede ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [New-Object], MethodException
    + FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

Send-MailMessage : Cannot process argument transformation on parameter 'Credential'. userName
At line:4 char:90
+ ... tp.us-east-2.amazonaws.com" -Port 587 -Credential $Credential -UseSsl ...
+                                                       ~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Send-MailMessage], ParameterBindingArgumentTransformationException
    + FullyQualifiedErrorId : ParameterArgumentTransformationError,Microsoft.PowerShell.Commands.SendMailMessage

I tried to use ConvertTo-SecureString -String "mypassword" but also getting a conversion error.


Solution

  • Try:

    $credpassword = ConvertTo-SecureString -AsPlainText "mypassword" -Force
    

    Provided you are using version 5.1 or later you can also use the ::new() static method in place o f New-Object (totally optional).

    $credpassword = ConvertTo-SecureString -AsPlainText "mypassword" -Force
    [System.Management.Automation.PSCredential]::new( $CredUser, $CredPassword )
    Send-MailMessage -SmtpServer "smtp.amazonaws.com" -Port 587 -Credential $Credential -UseSsl -From 'DBATeam@email.com' -To 'me@email.com' -Subject 'TEST'
    

    You can incorporate splatting if you want to add some readability:

    $credpassword = ConvertTo-SecureString -AsPlainText "mypassword" -Force
    [System.Management.Automation.PSCredential]::new( $CredUser, $CredPassword )
    
    $SMTPParams = @{
       SmtpServer = 'smtp.amazonaws.com'
       Port       = 587
       Credential = $Credential
       UseSsl     = $true
       From       = 'DBATeam@email.com'
       To         = 'me@email.com'
       Subject    = 'TEST'
    }
    
    Send-MailMessage @SMTPParams
    

    Note: some may frown on a password being visible. You can store the password securely in a file, then call it back for use. As long as it's by the same user on the same machine.

    $SecurePassword = Read-Host -Prompt "Enter Password" -AsSecureString $SecurePassword | ConvertFrom-SecureString | Out-File C:\temp\SecurePasswword.txt

    $CredPassword = Get-Content C:\temp\SecurePasswword.txt | ConvertTo-SecureString 
    [System.Management.Automation.PSCredential]::new( $CredUser, $CredPassword )
    

    Obviously you'll want to change the path to the file, so as not to advertise it. Establish the password file with the first 2 lines. Then use the second 2 in your current script to set up the creds for your SMTP command...

    Documented here