Skip to content

RFC to obsolete Send-MailMessage #160

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Aug 12, 2019
95 changes: 95 additions & 0 deletions 1-Draft/RFCXXXX-Send-MailMessage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
---
RFC: RFCXXXX
Author: Travis Plunk
Status: Draft
SupercededBy: N/A
Version: 1.0
Area: cmdlets
Comments Due: 4/30/2019
Plan to implement: No
---

# Obsoleting `Send-MailMessage`

`Send-MailMessage` does not support many modern protocols leading to the inability to use this with modern secure mail services.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I question this statement. Do we have any numbers to back this up?

Most of the time when I am using Send-MailMessage, I am hitting an internal SMTP server or Office 365 (which doesn't seem to be an issue yet). If the majority of users are hitting these, then this CMDLet has quite a long life left in it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't matter how many there are. Users need a reasonable expectation that what they're doing is secure if it's reporting as secure. If you're using an internal-only server, we can provide some context so that you can decide it's okay to do what you're doing, but we can't create a false expectation of security.

See [DotNet DE0005](https://github.com/dotnet/platform-compat/blob/master/docs/DE0005.md).
Since the protocols it uses are no longer considered secure, the cmdlet as is should not be used.
I recommend that we implement a plan to remove the cmdlet from powershell core and, if needed,
re-implement as a separate module.

## Motivation

### Primary

The underlying API, [`SmtpClient`](https://docs.microsoft.com/dotnet/api/system.net.mail.smtpclient), doesn't support many modern protocols.
It is compat-only.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where was this ever listed as for compatibility only?

It's great for one off emails from tools, but doesn't scale to modern requirements of the protocol.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we expand on how it doesn't scale?


### Secondary

Most major mail platforms now have REST methods to send mail, which allows `Invoke-RestMethod` to allow sending mail messages.

* gmail
* https://developers.google.com/gmail/api/v1/reference/users/messages/send
* https://stackoverflow.com/questions/24460422/how-to-send-a-message-successfully-using-the-new-gmail-rest-api
* Office365
* https://docs.microsoft.com/en-us/previous-versions/office/office-365-api/api/version-2.0/mail-rest-operations#SendMessages

## Obsoletion Plan

### Add a warning to 6.2

In a 6.2, we have added an obsolete warning to `Send-MailMessage` that an alternative method should be found.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As others have mentioned, this should probably be a documentation note and a warning in PSScriptAnalyzer rather than a persistent in-console warning. This will just needlessly clutter logging data for a large portion of use cases for this cmdlet.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe whatever action is taken, any existing script that uses Send-MailMessage should continue to work. A switch like -AllowInsecure or similar measures would break existing scripts as it would require code changes.


**Note:** Adding an obsolete warning should not break compatibility in any way.
Copy link

@kjacobsen kjacobsen Jun 3, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will however cause warning alerts for anyone who runs automation that looks for warnings generated on the warning output stream, IE Azure Automation.

What is the point of a warning if it isn't actionable?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is actionable: you learn about the obsolescence and you can make a decision based on your own environment on whether to continue using it.

And we'll have better documentation in the future about the underlying risk.


### Positive confirmation of issue in 6.3

We will add a switch requiring the user to accept the risk of using older **possibly** less secure implementations.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will simply encourage insecure behavior. We don't want users to simply "add this thing to make email work". That isn't a good security practice and it will not encourage the behavior you think it will.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PowerShell/powershell-committee talked and agreed we don't really need this switch. We're leaning now towards just having the warning message

This switch would be called `-AllowUnsecureConnection` and would be mandatory

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't that be ````-AllowInsecureConnection```. Unsecure isn't a word.


**Note:** The switch name is based on the [DSC Property](https://docs.microsoft.com/en-us/powershell/dsc/managing-nodes/metaconfig#configuration-server-blocks)

### If needed, develop an alternative

If needed, develop a new cmdlet based on the DotNet recommended solution of [MailKit](https://github.com/jstedfast/MailKit).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So now we enter the realms of JavaScript with dependencies all the way down.

PowerShell devs and admins will now need to keep track of a PowerShell version, a SMTP module version and MailKit version to ensure they don't have any security issues.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally that would fall on the maintainer of the cmdlet/module that's redistributing MailKit (we don't have dependency resolution between Nuget.org and the PS Gallery, so it'd have to be packaged as a binary). That might be us, or it might be someone in the community.


## Alternate Proposals and Considerations

### Remove the cmdlet during 6.3

During the development of 6.3, remove the `Send-MailMessage` cmdlet.

Feedback on this option was negative and the RFC has been updated with then next most reasonable option.

### Community replacement

The community could develop a replacement that can could be incorporated back into PowerShell Core.
This has the disadvantage of increasing the size of PowerShell Core and delaying the solution.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could follow a similar path of ThreadJob, where the module is available on the gallery separately and can be updated separately as needed, but also packaged in the box with PowerShell itself.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not use a REST api call for sending email. SMTP has not changed signficantly, and every mail server/mail transport agent supports SMTP. There is no way of guaranteeing that a designated mail server will support the REST API's. If the REST API's are needed to support the more advanced protocols, then I would suggest adding a switch or a parameter to designate the type of email communication.. something like -Protocol SMTP|REST or '-UseRESTor-UseSMTP`.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the REST API's are needed to support the more advanced protocols, then I would suggest adding a switch or a parameter to designate the type of email communication.. something like -Protocol SMTP|REST or '-UseRESTor-UseSMTP`.

I wouldn't even go that far. REST is just a set of APIs specific to an application. It is not a standard or a communication protocol like SMTP. To add it to Send-MailMessage would require multiple implementations of 3rd party APIs which would be hard to mantain.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a alternative module, written by Microsoft or the community, is the selected path. Then it needs to support SMTP as that is still the industry default for sending email.

REST APIs are a platform specific thing (SparkPost, GMail, etc)


### Additional considerations

#### GMail REST API

To use the GMail REST API the following additional items are needed

#### WebSafeBase64

For GMail, a MIME message is required to be encoded in this format.
https://code.google.com/p/stringencoders/wiki/WebSafeBase64

#### Something to compose the MIME message

For GMail, you have to pass the MIME message.

---------------

## PowerShell Committee Decision

### Voting Results

### Majority Decision

### Minority Decision

N/A