locked
Issue with adding multiple attachments RRS feed

  • Question

  • Hi Folks -

    Per reccomend from jrv, I have developed an email utility script in PowerShell.  Everything is working except when adding attachments.

    I'm trying to add ALL files from hte specific directory but it's giving me "Missing ) in method call" error. Seems odd to me because if I put that syntax in a variable and echo the variable it works fine. Do I need to add anything additionally when leveraged in an Attactent.Add command?

    Here is my script, thank you!

    #--:: Set Email Details ::--#
    
    $emailSmtpServer = $args[0]
    $emailFrom = $args[1]
    $emailTo = $args[2]
    $emailSmtpServerPort = $args[3]
    $emailSmtpUser = $args[1]
    $emailSmtpPass = $args[4]
    
    #--:: Build Email Message ::--#
    $emailMessage = New-Object System.Net.Mail.MailMessage( $emailFrom , $emailTo )
    $ParentScript = $Env:PLOGPATH -replace ".{6}$"
    
    If($Env:ERR -ne "T") {
    	$emailMessage.Subject = "ATTENTION : $ParentScript.cmd completed successfully"
    	} Else {
    	$emailMessage.Subject = "WARNING : $ParentScript.cmd failed to complete successfully"
    }
    
    #--:: Check to see if ERR variable is defined from the batch script :--#
    If($Env:ERR -ne "T") {
    	$emailMessage.Body = "The process completed successfully.  Please the check log file(s) for additional details."
    	} Else {
    	$emailMessage.Body = "The process failed to complete successfully.  Please the check log file(s) for additional details."
    }
    
    $emailMessage.Attachments.Add(Get-ChildItem "C:\Hyperion_Batch\Scripts\Utilities"| Where {-NOT $_.PSIsContainer} | foreach {$_.fullname})
    
    #--:: SMTP Client Detail ::--#
    $SMTPClient = New-Object System.Net.Mail.SmtpClient( $emailSmtpServer , $emailSmtpServerPort )
    $SMTPClient.EnableSsl = If($args[4] -eq $Null) {$false} Else {$False}
    $SMTPClient.Credentials = New-Object System.Net.NetworkCredential( $emailSmtpUser , $emailSmtpPass );
    $SMTPClient.Send( $emailMessage )

    Sunday, March 29, 2020 1:37 PM

All replies

  • Please use Send-MailMesssage as it will solve all of your problems in one simple command and it will eliminate more than half of your code.

    help send-mailmesage -online

    If you would take the time to actually learn basic PowerShell y9ou would know how to solve these problems and you would write less code.  Copying from the Internet without any knowledge of basic PowerShell will lead you to copying bad code and gaining an incorrect understanding of PowerShell.

    All of your code can be written in one CmdLet with this CmdLet.


    \_(ツ)_/


    • Edited by jrv Sunday, March 29, 2020 2:05 PM
    Sunday, March 29, 2020 2:04 PM
  • I"m unable to get sendmail to work if I need to authenticate for 0365 relay.  Even with Usessl etc. The above worked for me.
    Sunday, March 29, 2020 2:11 PM
  • Send-MailMessage works with O365.  The code you copied is exactly what is inside or Send-MailMessage.  Your failure to use it is likely because you are not aware of how to use the mail system and its parameters.  You copied something that works which didn't fix your issue it just went around it.

    Here is an \example of how to write a Power5Shell script.  All of your methods show that you have copied an extremely old script that is inflexible and will teach you nothing useful.

    param(
        [string]$From,
        [string]$To,
        [string]$UserName,
        [string]$Password,
        [string]$SmtpServer,
        [int]$Port = 587,
        [switch]$UseSsl
    )
    
    $secpass = ConvertTo-SecureString $Password -AsPlainText -Force
    $mailparams = @{
        From = $From
        To = $To
        Subject = $null
        Body = $null
        Attachments = (Get-ChildItem C:\Hyperion_Batch\Scripts\Utilities -File).Fullname
        SmtpServer = $SmtpServer
        Port = $Port
        UseSsl = $UseSsl
        Credentials = [System.Net.NetworkCredential]::New($UserName,$secpass)
    }
    
    if(env:ERR -ne 'T'){
        $mailparams.Body = 'The process completed successfully.  Please the check log file(s) for additional details.'
    	$mailparams.Subject = "ATTENTION : $ParentScript.cmd completed successfully"
    }else {
    	$mailparams.Body = 'The process failed to complete successfully.  Please the check log file(s) for additional details.'
    	$mailparams.Subject = "WARNING : $ParentScript.cmd failed to complete successfully"
    }
    
    Send-MailMessage @mailparams


    \_(ツ)_/


    • Edited by jrv Sunday, March 29, 2020 2:29 PM
    Sunday, March 29, 2020 2:28 PM
  • Send-MailMessage works with O365.  The code you copied is exactly what is inside or Send-MailMessage.  Your failure to use it is likely because you are not aware of how to use the mail system and its parameters.  You copied something that works which didn't fix your issue it just went around it.

    Here is an \example of how to write a Power5Shell script.  All of your methods show that you have copied an extremely old script that is inflexible and will teach you nothing useful.

    param(
        [string]$From,
        [string]$To,
        [string]$UserName,
        [string]$Password,
        [string]$SmtpServer,
        [int]$Port = 587,
        [switch]$UseSsl
    )
    
    $secpass = ConvertTo-SecureString $Password -AsPlainText -Force
    $mailparams = @{
        From = $From
        To = $To
        Subject = $null
        Body = $null
        Attachments = (Get-ChildItem C:\Hyperion_Batch\Scripts\Utilities -File).Fullname
        SmtpServer = $SmtpServer
        Port = $Port
        UseSsl = $UseSsl
        Credentials = [System.Net.NetworkCredential]::New($UserName,$secpass)
    }
    
    if(env:ERR -ne 'T'){
        $mailparams.Body = 'The process completed successfully.  Please the check log file(s) for additional details.'
    	$mailparams.Subject = "ATTENTION : $ParentScript.cmd completed successfully"
    }else {
    	$mailparams.Body = 'The process failed to complete successfully.  Please the check log file(s) for additional details.'
    	$mailparams.Subject = "WARNING : $ParentScript.cmd failed to complete successfully"
    }
    
    Send-MailMessage @mailparams


    \_(ツ)_/


    Thank you, jrv! I am trying to use your above code but running into some issues.

    Batch:

    POWERSHELL -file "emailpowerfinal.ps1" ^
    	"<from email>" ^
    	"<to email>" ^
    	"<user>" ^
    	"<password>" ^
    	"SMTP.Office365.com"
    
    pause

    Getting the following error:

    Method invocation failed because [System.Net.NetworkCredential] does not 
    contain a method named 'New'.
    At D:\Cloud_Automation\Utilities\SwithMail\emailpowerfinal.ps1:12 char:1
    + $mailparams = @{
    + ~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
        + FullyQualifiedErrorId : MethodNotFound
     
    Send-MailMessage : Cannot validate argument on parameter 'To'. The argument is 
    null or empty. Provide an argument that is not null or empty, and then try the 
    command again.
    At D:\Cloud_Automation\Utilities\SwithMail\emailpowerfinal.ps1:24 char:18
    + Send-MailMessage @mailparams
    +                  ~~~~~~~~~~~
        + CategoryInfo          : InvalidData: (:) [Send-MailMessage], ParameterBi 
       ndingValidationException
        + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.Power 
       Shell.Commands.SendMailMessage
     
    

    ps1:

    param(
        [string]$From,
        [string]$To,
        [string]$UserName,
        [string]$Password,
        [string]$SmtpServer,
        [int]$Port = 587,
        [switch]$UseSsl
    )
    
    $secpass = ConvertTo-SecureString $Password -AsPlainText -Force
    $mailparams = @{
        From = $From
        To = $To
        Subject = $null
        Body = $null
        Attachments = (Get-ChildItem D:\Cloud_Automation\Utilities\SwithMail -File).Fullname
        SmtpServer = $SmtpServer
        Port = $Port
        UseSsl = $UseSsl
        Credentials = [System.Net.NetworkCredential]::New($UserName,$secpass)
    }
    
    Send-MailMessage @mailparams

    Thank you!

    Sunday, March 29, 2020 3:04 PM
  • What version of PowerShell are you running?  We are at 5.1 or later.

    \_(ツ)_/

    Sunday, March 29, 2020 3:17 PM
  • What version of PowerShell are you running?  We are at 5.1 or later.

    \_(ツ)_/

    I was on 4.0. i upgraded to 5.1 and it helped, but still getting this error now only:


    Send-MailMessage : A parameter cannot be found that matches parameter name 
    'Credentials'.
    At D:\Cloud_Automation\Utilities\SwithMail\emailpowerfinal.ps1:32 char:18
    + Send-MailMessage @mailparams
    +                  ~~~~~~~~~~~
        + CategoryInfo          : InvalidArgument: (:) [Send-MailMessage], Paramet 
       erBindingException
        + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Comm 
       ands.SendMailMessage
     
    

    Thank you!


    Sunday, March 29, 2020 4:36 PM
  • help send-mailmessage -online

    Remove the "S".


    \_(ツ)_/

    Sunday, March 29, 2020 5:14 PM
  • help send-mailmessage -online

    Remove the "S".


    \_(ツ)_/

    Okay.  Getting this error now:

    Send-MailMessage : Cannot process argument transformation on parameter 
    'Credential'. userName
    At D:\Cloud_Automation\Utilities\SwithMail\emailpowerfinal.ps1:34 char:18
    + Send-MailMessage @mailparams
    +                  ~~~~~~~~~~~
        + CategoryInfo          : InvalidData: (:) [Send-MailMessage], ParameterBi 
       ndingArgumentTransformationException
        + FullyQualifiedErrorId : ParameterArgumentTransformationError,Microsoft.P 
       owerShell.Commands.SendMailMessage
     
    

    Thank you for all your help, jrv!

    Sunday, March 29, 2020 5:31 PM
  • Got it and it's working now...Here is the updated code.

    $secpasswd = ConvertTo-SecureString "password" -AsPlainText -Force
    $mycreds = New-Object System.Management.Automation.PSCredential ("FIN_IQalerts@client.com", $secpasswd)
    
    $mailparams = @{
        From = $EmailFrom
        To = $EmailTo
        Subject = $Null
        Body = $Null
        Attachments = (Get-ChildItem "D:\Cloud_Automation\Utilities\SwithMail\*txt" -File).Fullname
        SmtpServer = $EmailSMTPServer
        Port = $Port
    	UseSsl = $true
    	credential = $mycreds
    }

    Is there a way to put the password in the file and call the file instead?

    Sunday, March 29, 2020 6:13 PM
  • Username is not correct as the error message says.

    You need to stop guessing.  Without some knowledge of PowerShell it is very hard for us to guess at what you are doing.

    The first question to ask is why?  Why would you call a PowerShell script from a batch file?

    First test the code from PowerShell.  Until it works in PowerShell the batch file is just causing you  more confusion.


    \_(ツ)_/

    Sunday, March 29, 2020 6:14 PM
  • Got it and it's working now...Here is the updated code.

    $secpasswd = ConvertTo-SecureString "password" -AsPlainText -Force
    $mycreds = New-Object System.Management.Automation.PSCredential ("FIN_IQalerts@client.com", $secpasswd)
    
    $mailparams = @{
        From = $EmailFrom
        To = $EmailTo
        Subject = $Null
        Body = $Null
        Attachments = (Get-ChildItem "D:\Cloud_Automation\Utilities\SwithMail\*txt" -File).Fullname
        SmtpServer = $EmailSMTPServer
        Port = $Port
    	UseSsl = $true
    	credential = $mycreds
    }

    Is there a way to put the password in the file and call the file instead?

    Again - if you take the time to learn the very basic things about PowerShell al of your issues would be gone.  YOu are basically asking othe5rs to write your code one line at a time.  That is the purpose of a professional forum.

    Start with this free book.  Read it until you understand what PowerShell is.  It is not a batch file and it is not a VBScript file.  Power4shell is something that you haven't even heard of.  You have just copied bad ideas and code from the Internet,  You need to learn this correctly or you will waste a huge amount of yours and other's time.



    \_(ツ)_/

    Sunday, March 29, 2020 6:21 PM
  • Why was your code failing on the 'Credential' though? but my edits worked?
    Sunday, March 29, 2020 6:50 PM
  • Why was your code failing on the 'Credential' though? but my edits worked?

    Because you took off the S.  Your code is no different than mine except it is much more unnecessary code.  This is why you need to learn PS.  What you are doing is guesswork based on bad or unnecessary infomat5ion. It will mak3e it much harder for you to learn PowerShell or to use it easily.

    When someone is working with you to resolve an issue it is critical that you do no more than what is asked until the issue is resolved.  Customers who make changes while a tech is trying to help them only make it harder for a tech to help them.  This is something that all techs learn how to work with and we usually assume that someone asking a question knows this.  Lately I see most techs have not been formally trained and do not understand how to ask for help or how to work with a tech to obtain help and under4standing of what was wrong.


    \_(ツ)_/

    Sunday, March 29, 2020 7:02 PM
  • Why was your code failing on the 'Credential' though? but my edits worked?

    Because you took off the S.  Your code is no different than mine except it is much more unnecessary code.  This is why you need to learn PS.  What you are doing is guesswork based on bad or unnecessary infomat5ion. It will mak3e it much harder for you to learn PowerShell or to use it easily.

    When someone is working with you to resolve an issue it is critical that you do no more than what is asked until the issue is resolved.  Customers who make changes while a tech is trying to help them only make it harder for a tech to help them.  This is something that all techs learn how to work with and we usually assume that someone asking a question knows this.  Lately I see most techs have not been formally trained and do not understand how to ask for help or how to work with a tech to obtain help and under4standing of what was wrong.


    \_(ツ)_/

    Taking off the S didn't work. It still gave me the same error.  I needed to add the following lines and it worked.

    $secpasswd = ConvertTo-SecureString "password" -AsPlainText -Force
    $mycreds = New-Object System.Management.Automation.PSCredential ("FIN_IQalerts@client.com", $secpasswd)
    

    Why though?

    Sunday, March 29, 2020 7:15 PM
  • No.  That is not what was wrong.  You just fudged teh name to add a hard coded name which tells me that what you pass3ed was wrong.

    If you would follow my instructions instead of doing your own guessing you would ahve learned what you were doing wrong.  It is too late for that now.

    Good luck -  learn PowerShell before you get more confused.


    \_(ツ)_/

    Sunday, March 29, 2020 7:21 PM
  • No.  That is not what was wrong.  You just fudged teh name to add a hard coded name which tells me that what you pass3ed was wrong.

    If you would follow my instructions instead of doing your own guessing you would ahve learned what you were doing wrong.  It is too late for that now.

    Good luck -  learn PowerShell before you get more confused.


    \_(ツ)_/

    The password was being passed in fine. I was able to echo it and see it. 
    Sunday, March 29, 2020 7:35 PM