Powershell: Send-MailMessage $Subject Mandatory=$true

Created on 18 Jun 2017  路  12Comments  路  Source: PowerShell/PowerShell

Not a bug, but a request for "Send-MailMessage" cmdlet

 $From = $email
    $To = $Number
    $Body = "Something"
    $Subject = $null
    $SMTPServer = "smtp.gmail.com"
    $SMTPPort = "587"
    Send-MailMessage -From $From -to $To -Subject $Subject `
        -Body $Body -SmtpServer $SMTPServer -port $SMTPPort -UseSsl `
    -Credential $Cred

RESULT:

Send-MailMessage : Cannot validate argument on parameter 'Subject'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
At line:8 char:52
+       -Body $Body -SmtpServer $SMTPServer -Subject $Subject -port $SM ...
+                                                    ~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Send-MailMessage], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.SendMailMessage

CAUSE:

[Parameter(Mandatory=$true, Position=1)]
        [Alias('sub')]
        [ValidateNotNullOrEmpty()]
        [string]
        ${Subject},

Emails do not require subjects to be present. However, in the Send-MailMessage cmdlet, the $subject parameter is set to "Mandatory=$true". Since an email does not require a subject, this should really be set to "$false".

I've created my own workaround this, but I feel that this should be changed since a subject is not imperative for an email to be sent.

Area-Cmdlets-Utility Committee-Reviewed First-Time-Issue Hacktoberfest Issue-Discussion Up-for-Grabs

Most helpful comment

@ece-jacob-scott Tests for Send-MailMessage cmdlet don't run on CI, since there is no SMTP server installed on the CI agents.
See PR #8859 which would allow testing the cmdlet on the CI agents. PR is ready but yet to be merged.

All 12 comments

Seems reasonable. Cc @joeyaiello

Missing Subject is a bad practice. By default, we must ask for it to present. Maybe add -IgnoreSubject?

I would like to try this one.

Most information is gathered from PR #4044, which was closed due to non-addressed comments.

The easiest way to implement the option to make -Subject always mandatory, unless the user explicitly states to send the mail without a subject is to use ParameterSetName as stated by @dantraMSFT.

Though I would like to go with the -Force switch, due to consistency with other cmdlets as suggested by @SteveL-MSFT.
Based on community feedback (Thx for the feedback) the -NoSubject switch will be used in its own parameter set. This will therefore exclude the parameter -Subject completely from the proposed ParameterSetName "NoSubject".

ParameterSetName "Default": This would prompt for missing parameter -Subject due to being a mandatory parameter

Send-MailMessage -From [email protected] -To [email protected] -Body 'Test Mail Body' ...

ParameterSetName "Force": This would not prompt for missing parameter -Subject
ParameterSetName "NoSubject": This will exclude the parameter -Subject from the parameter set. No error or prompt will be shown due to missing email subject.

Send-MailMessage -From [email protected] -To [email protected] -Body 'Test Mail Body' -NoSubject ...

One problem is, that Send-Mail uses positional parameters, where -Subject is at position 1. Two options would be available:

  1. ParameterSetName "NoSubject": Don't use positional parameters at all.
  2. ParameterSetName "NoSubject": Make -Body positional parameter at 1 instead of 2 and -SmtpServer 2 instead of 3.
    Example for solution 2:
Send-MailMessage [email protected] 'Test Mail Body' smtp.server.com -NoSubject...

TODOs

  • [ ] Submit PR to Powershell repository with suggested modifications.

    • [ ] Implement -NoSubject switch.

    • [ ] Include test case which uses -NoSubject switch.

  • [ ] Submit PR to Powershell-Docs repository to reflect alternative parameter set.

Any feedback is highly appreciated. Thx.


EDIT 2018-08-21

  • Change switch parameter -Force to -NoSubject.
  • Change ParameterSetName "Force" to "NoSubject".
  • Change Send-Mail to correct Send-MailMessage cmdlet name.

Sounds good to me. I like solution 2 馃憤

@ThreeFive-O thanks for taking this up! The one concern I have is that the proposal forces -Force to always apply to no-subject. Perhaps it would be better to have a -NoSubject switch thereby having a specific parameter set for that scenario.

Personally, I think we're overloading -Force here. Consider potential help text

'-Force: sends the mail message without a subject'.

I personally favor your other suggestion, -NoSubject.

'-NoSubject: sends the mail message without a subject.'

Changing the parameter order for the new parameter set should be fine since it requires an opt-in and won't break existing scripts.

Two more questions:

  1. Strange case: Using the switch -NoSubject would exclude -Subject from this parameter set. What if someone uses a pipeline or splatting where both parameters -NoSubject and -Subject are passed through? This would result in an error, since -Subject is not available. My other suggestion with the -Force parameter would have allowed still to include -Subject, but to ignore the mandatory prompt.

  2. Send-MailMessage is not available in the version 6 Powershell-Docs repository. Am I missing something?

@ThreeFive-O Please open new issue in PowerShell-Docs repo https://github.com/PowerShell/PowerShell-Docs

@PowerShell/powershell-committee reviewed this, making a parameter that was mandatory no longer mandatory is not a breaking change. Recommendation is to make mandatory=false, remove validation for nullorempty and set default to empty string.

Hack Illinois Competition participant.
Working with Dan and Tyler

I can take this one on.

Tested with Tyler's own smtp server.
The test when run in CI just don't run.

We used this code to test on my local environment and confirmed that it works.

PS /home/jacob/Documents/Powershell> $a = @{
>> From = "[email protected]"
>> To = "[email protected]"
>> Body = "adsfsdafsfda"
>> SMTPServer = "smtp.mailgun.org"
>> Port = "587"
>> Credential = (Get-Credential)
>> }

PowerShell credential request
Enter your credentials.
User: [email protected]
Password for user [email protected]: **************************************************

PS /home/jacob/Documents/Powershell> Send-MailMessage @a -UseSsl
PS /home/jacob/Documents/Powershell> 

@ece-jacob-scott Tests for Send-MailMessage cmdlet don't run on CI, since there is no SMTP server installed on the CI agents.
See PR #8859 which would allow testing the cmdlet on the CI agents. PR is ready but yet to be merged.

Was this page helpful?
0 / 5 - 0 ratings