当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] 安全发送 PowerShell 电子邮件的 5 种替代方法

作者:精品下载站 日期:2024-12-14 13:02:10 浏览:12 分类:玩电脑

安全发送 PowerShell 电子邮件的 5 种替代方法


需要就失败的服务通知您的团队,却发现您的 PowerShell 电子邮件已被退回?未经身份验证的电子邮件在许多邮件系统中变得难以传递。您不想因为依赖过时的 PowerShell cmdlet 而错过重要的电子邮件通知。内置 cmdlet Send-MailMessage 不再涵盖安全发送电子邮件。

尽管这个 cmdlet 很有用,但为什么它不再被认为是安全的呢?在下面,此 PowerShell cmdlet 使用 SmtpClient .NET 类。不幸的是,此类不支持许多现代加密协议,因此无法保证安全连接。问题的关键在于,SmtpClient 不会进一步开发以添加功能,例如 Opportunistic TLS,官方建议不再使用该产品。

可能有点令人困惑的是,即使在最新的 .NET Core 版本中,这些类和方法仍然存在。尽管您可能仍然使用这些方法,但官方建议是改用其他电子邮件发送方法。现在发送Powershell电子邮件通常有两种方法。

  • .NET库
  • 休息API

考虑到这两种方法,让我们开始讨论一些替代方法!

.NET 邮件套件

替代 SmtpClient 和 Send-MailMessage 的最通用方法是推荐的替代方法,即 MailKit。这是一个第三方开源库,但由 Microsoft 员工维护,并在文档中正式推荐使用。这类似于 Newtonsoft.JSON 尽管是开源产品,但成为 .NET 平台核心部分的方式。

安装 MailKit 和 MimeKit

由于 MailKit 及其 MimeKit 的核心依赖项不是 .NET 可用的本机库,因此我们需要首先安装它们。

确保以管理员身份运行Install-Package,否则软件包可能无法正确安装。

使用 Install-Package cmdlet,从 [nuget.org]() 存储库安装 MailKit。如果安装正常,您将看到许多依赖项与 MailKit 一起安装,包括 MimeKit。

Install-Package -Name 'MailKit' -Source 'nuget.org'

[玩转系统] 安全发送 PowerShell 电子邮件的 5 种替代方法

通过 MailKit 发送 PowerShell 电子邮件

下面的示例显示了我们如何使用 Gmail SMTP 服务器但使用 MailKit 发送电子邮件。在此示例中,PowerShell 7.0.1 是底层版本,我们使用最新的 .NET Standard 2.0 版本的 DLL。如果需要,其他 DLL 版本可在父目录中找到。

如您所见,我们需要加载 MailKit DLL 和 MimeKit DLL。如果只加载MailKit,可能不会出现错误,但是这样不行。接下来的步骤与原始 SmtpClient 在设置各种配置方面的工作方式非常相似。

Add-Type -Path "C:\Program Files\PackageManagement\NuGet\Packages\MailKit.2.8.0\lib\netstandard2.0\MailKit.dll"
 Add-Type -Path "C:\Program Files\PackageManagement\NuGet\Packages\MimeKit.2.9.1\lib\netstandard2.0\MimeKit.dll"
 $SMTP     = New-Object MailKit.Net.Smtp.SmtpClient
 $Message  = New-Object MimeKit.MimeMessage
 $TextPart = [MimeKit.TextPart]::new("plain")
 $TextPart.Text = "This is a test."
 $Message.From.Add("[email ")
 $Message.To.Add("[email ")
 $Message.Subject = 'Test Message'
 $Message.Body    = $TextPart
 $SMTP.Connect('smtp.gmail.com', 587, $False)
 $SMTP.Authenticate('[email ', 'appspecificpassword' )
 $SMTP.Send($Message)
 $SMTP.Disconnect($true)
 $SMTP.Dispose()

身份验证步骤的密码显示 appspecificpassword 的原因是,如果您正确使用双因素身份验证,则需要为应用程序生成应用程序特定的密码。

使用 MailKit 模拟 Send-MailMessage

尽管这与 Send-MailMessage 没有直接关联,但如果我们想要创建一个快速且简单的函数,将 MailKit 功能包装到内置 cmdlet 的替代方案中,该怎么办?在此示例中,我们可以创建一个 Send-MailkitMessage 函数来执行一系列类似的步骤。请记住,这不会复制所有功能,并且会被大大简化。

Function Send-MailkitMessage {
  [CmdletBinding(
      SupportsShouldProcess = $true,
      ConfirmImpact = "Low"
  )] # Terminate CmdletBinding

  Param(
    [Parameter( Position = 0, Mandatory = $True )][String]$To,
    [Parameter( Position = 1, Mandatory = $True )][String]$Subject,
    [Parameter( Position = 2, Mandatory = $True )][String]$Body,
    [Parameter( Position = 3 )][Alias("ComputerName")][String]$SmtpServer = $PSEmailServer,
    [Parameter( Mandatory = $True )][String]$From,
    [String]$CC,
    [String]$BCC,
    [Switch]$BodyAsHtml,
    $Credential,
    [Int32]$Port = 25
  )

  Process {
    $SMTP     = New-Object MailKit.Net.Smtp.SmtpClient
    $Message  = New-Object MimeKit.MimeMessage

    If ($BodyAsHtml) {
      $TextPart = [MimeKit.TextPart]::new("html")
    } Else {
      $TextPart = [MimeKit.TextPart]::new("plain")
    }
    
    $TextPart.Text = $Body

    $Message.From.Add($From)
    $Message.To.Add($To)
    
    If ($CC) {
      $Message.CC.Add($CC)
    }
    
    If ($BCC) {
      $Message.BCC.Add($BCC)
    }

    $Message.Subject = $Subject
    $Message.Body    = $TextPart

    $SMTP.Connect($SmtpServer, $Port, $False)

    If ($Credential) {
      $SMTP.Authenticate($Credential.UserName, $Credential.GetNetworkCredential().Password)
    }

    If ($PSCmdlet.ShouldProcess('Send the mail message via MailKit.')) {
      $SMTP.Send($Message)
    }

    $SMTP.Disconnect($true)
    $SMTP.Dispose()
  }
}

发送实际消息就像调用我们刚刚创建的函数并传入正确的参数一样简单。

$Params = @{
  "To"         = '[email '
  "From"       = '[email '
  "Subject"    = 'Test Email'
  "Body"       = 'This is a test.'
  "SmtpServer" = 'smtp.gmail.com'
  "Credential" = $Creds
  "Port"       = 587
}

Send-MailkitMessage @Params

直接发送

为了跟进 MailKit 的使用,以及如何在使用 Office 365 的现代环境中更实际地使用它,我们可以利用 Office 365 用户可用的直接发送功能。原始方法使用, Send-MailMessage 也可以在本文中阅读。不过,这种特定的发送方法有一些注意事项。

  • 不允许外部收件人
  • 使用端口 25 而不是 587
  • 发件人不需要有效邮箱,但如果需要 NDR 或回复,则需要有效邮箱

与我们使用 MailKit 发送到 Gmail 的方式类似,我们将对现有代码进行一项更改。通过 Connect 方法,我们添加 [MailKit.Security.SecureSocketOptions]::StartTls 选项以确保使用 TLS。

Add-Type -Path "C:\Program Files\PackageManagement\NuGet\Packages\MailKit.2.8.0\lib\netstandard2.0\MailKit.dll"
Add-Type -Path "C:\Program Files\PackageManagement\NuGet\Packages\MimeKit.2.9.1\lib\netstandard2.0\MimeKit.dll"

$SMTP     = New-Object MailKit.Net.Smtp.SmtpClient
$Message  = New-Object MimeKit.MimeMessage
$TextPart = [MimeKit.TextPart]::new("plain")
$TextPart.Text = "This is a test."

$Message.From.Add("[email ")
$Message.To.Add("[email ")
$Message.Subject = 'Test Message'
$Message.Body    = $TextPart

$SMTP.Connect('{tenant}.mail.protection.outlook.com', 25, [MailKit.Security.SecureSocketOptions]::StartTls, $False)
$SMTP.Authenticate('[email ', 'mypassword' )

$SMTP.Send($Message)
$SMTP.Disconnect($true)
$SMTP.Dispose()

亚马逊SES

使用 MailKit 发送电子邮件的另一个示例是使用 Amazon SES(简单电子邮件服务)。要了解有关整体设置和配置的更多信息,请阅读本文,但完成后您会发现通过 MailKit 发送电子邮件是多么简单。通过利用正确的端点和 TLS,我们可以简单地通过 MailKit 发送电子邮件。

Add-Type -Path "C:\Program Files\PackageManagement\NuGet\Packages\MailKit.2.8.0\lib\netstandard2.0\MailKit.dll"
Add-Type -Path "C:\Program Files\PackageManagement\NuGet\Packages\MimeKit.2.9.1\lib\netstandard2.0\MimeKit.dll"

$SMTP     = New-Object MailKit.Net.Smtp.SmtpClient
$Message  = New-Object MimeKit.MimeMessage
$TextPart = [MimeKit.TextPart]::new("plain")
$TextPart.Text = "This is a test."

$Message.From.Add("[email ")
$Message.To.Add("[email ")
$Message.Subject = 'Test Message'
$Message.Body    = $TextPart

$SMTP.Connect('email-smtp.ap-southeast-2.amazonaws.com', 587, [MailKit.Security.SecureSocketOptions]::StartTls, $False)
$SMTP.Authenticate('[email ', 'mypassword' )

$SMTP.Send($Message)
$SMTP.Disconnect($true)
$SMTP.Dispose()

.NET MailKit 库非常有用,但许多现代服务现在允许您通过 REST API 发送邮件,如以下示例所示。

Microsoft Graph 电子邮件

Microsoft Graph REST API 正迅速成为 Azure AD 和 Office 365 管理员不可或缺的一部分。考虑到这一点,利用 sendMail REST API 方法,我们可以使用 Invoke-RestMethod API 快速发送消息。

您需要 Mail.Send 权限才能发送电子邮件。

向 Microsoft Graph API 进行身份验证有一些先决条件,您可以在此处阅读相关内容。获得身份验证令牌并分配正确的权限后,请参阅下文了解如何在 Powershell 中发送电子邮件。

$Token = "tokencontent"

$Params = @{
  "URI"         = 'https://graph.microsoft.com/v1.0/me/sendMail'
  "Headers"     = @{
    "Authorization" = ("Bearer {0}" -F $Token)
  }
  "Method"      = "POST"
  "ContentType" = 'application/json'
  "Body" = (@{
    "message" = @{
      "subject" = 'This is a test message.'
      "body"    = @{
        "contentType" = 'Text'
        "content"     = 'This is a test email'
      }
      "toRecipients" = @(
        @{
          "emailAddress" = @{
            "address" = '[email '
          }
        }
      )
    }
  }) | ConvertTo-JSON -Depth 10
}

Invoke-RestMethod @Params

邮件枪

最后,让我们探索使用另一种流行的电子邮件服务 MailGun。使用简单的 API 调用,我们也可以通过此处发送电子邮件。从 MailGun 帐户设置 → API 密钥部分检索私有 API 密钥后,您可以使用它发送到您已配置的域。

$APIKey = 'key-asasdfd7as8fa8dfasdfasdff87sd8f8sa8sd'
 
$Params = @{
  "URI"            = 'https://api.mailgun.net/v3/mail.mydomain.com/messages'
  "Form"           = @{
    "from"    = '[email '
    "to"      = '[email '
    "subject" = 'Test API Sent Email'
    "text"    = 'Test Body Text'
  }
  "Authentication" = 'Basic'
  "Credential"     = (New-Object System.Management.Automation.PSCredential ("api", ($APIKey | ConvertTo-SecureString -AsPlainText)))
  "Method"         = 'POST'
}
 
Invoke-RestMethod @Params

结论

创建 Send-MailKitMessage 以删除底层 .NET 技术 SmtpClient 的使用,从而实现更安全的 PowerShell 电子邮件发送。有许多易于使用且功能更强大的替代方案,可以像内置函数一样轻松工作。根据您的需求以及您的脚本或应用程序可能需要执行的操作,只需替换上面演示的多种方法之一即可!

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯