Powershell 和 MailKit - 脚本失败

问题描述

我正在尝试在 Powershell 中使用新的 MailKit / Mimekit 而不是 Send-MailMessage。我在 Powershell 库中找到了 Send-MailKitMessage 1.0.1

我的需求很简单,Powershell 将仅用于内部警报,因此我简化了代码以满足我的需求。

    ***using namespace MailKit
       using namespace MimeKit
    
         $emailDLL = "F:\Apps\Email\MailKit.dll"
         $mimeDll = "F:\Apps\Email\MimeKit.dll"
         Add-Type -Path $emailDLL
         [System.Reflection.Assembly]::LoadFile($mimeDll)
              

#extend 类可用于调用脚本(MimeKit 程序集首先从清单文件加载,因此在此模块加载时可用) class MailBoxAddressExtended : MailBoxAddress { #不允许无参数构造 MailBoxAddressExtended([string]$Name,[string]$Address) : base($Name,$Address) { [string]$Name,#可以为空 [string]$Address #不能为空 } }

        class InternetAddressListExtended : InternetAddressList {}
        $List = New-Object InternetAddressListExtended # of type MimeKit.InternetAddress
    
         $smtpClient = New-Object MailKit.Net.Smtp.SmtpClient
     
         $message = [MimeKit.MimeMessage]::new()
         $TextPart = [MimeKit.TextPart]::new("html")
    
     #endregion
    
     [string[]]$recipients = "email@testdomain.com".Split(',').Trim()
     $from = "Dev_Test@testdomain.com"
     $smtpSvr = '190.132.148.22'
     $smtpPort = 25

function sendEmail ($subjectline,$msgbody) {
    $message.From.Add($from)  
    foreach ($address in $recipients) {$List.Add($address)}
    $message.To.AddRange($List)
    $TextPart.Text = $msgbody
    $message.Body = $TextPart
    $message.Subject = $subjectline
    
    if(!$smtpClient.IsConnected) {
    $smtpClient.Connect($smtpSvr)
    }
    if ($smtpClient.IsConnected) {
        $smtpClient.Send($message)
        $smtpClient.disconnect($true)
        
    }***

 }

当我在 PS1 脚本中运行上述代码时,出现错误

无法找到类型 [MailBoxAddress]

我可以在 Powershell 窗口中手动输入相同的代码,它按预期工作。 我使用过 PS5 v5.1、PS7 v7.1,但出现同样的错误。 我使用了上面的代码,因为它允许我向多个个人/团体发送电子邮件。 虽然对 Powershell 相对较新,但我能够解决之前的所有问题,从而得出上述代码

我非常感谢可以提供的任何指导。

解决方法

  1. Send-MailKitMessage 是一个应该安装的完整模块。关注here
  2. [MailboxAddress] ( [MimeKit.MailboxAddress] ) 这样的类型应该从 DLL 文件中加载,但如果您只使用 PSM1 文件,则没有可从中加载的 DLL。
  3. 目前是 3.1.0 版本(至于 2021-03-04)
  4. 它 (v3.1.0) 仅适用于 PowerShell 7+,因为它使用 ternary operator 引入的是 PSv7。我认为它可以轻松修复以移植回 PSv5,但这需要测试。
  5. 如果您不想安装模块,请下载 nupkg 文件,使用 7zip 将其解压缩并尝试如下使用:

Import-Module -Name 'C:\...\send-mailkitmessage.3.1.0\Send-MailKitMessage.psd1'

或者像这样:

[System.Reflection.Assembly]::LoadFile('C:\...\send-mailkitmessage.3.1.0\Libraries\BouncyCastle.Crypto.dll')
[System.Reflection.Assembly]::LoadFile('C:\...\send-mailkitmessage.3.1.0\Libraries\MailKit.dll')
[System.Reflection.Assembly]::LoadFile('C:\...\send-mailkitmessage.3.1.0\Libraries\MimeKit.dll')
Import-Module -Name 'C:\...\send-mailkitmessage.3.1.0\Send-MailKitMessage.psm1'
,

尽管我在尝试合并 Send-MailkitMessage 方面取得了一些进展,但我继续遇到意外错误。我决定回归基础,因为我的需求是基础,我只发送内部警报电子邮件。我创建了这个测试 PS1 文件:

using namespace MailKit 
using namespace MimeKit

     $emailDLL = "F:\Apps\Email\MailKit.dll"
     $mimeDll = "F:\Apps\Email\MimeKit.dll"
     Add-Type -Path $emailDLL
        
     [System.Reflection.Assembly]::LoadFile($mimeDll)
     [System.Reflection.Assembly]::LoadFile($emailDLL)

        class MailboxAddressExtended : MailboxAddress { #does not allow parameterless construction
        MailboxAddressExtended([string]$Name,[string]$Address ) : base($Name,$Address) {
            [string]$Name,#can be null
            [string]$Address    #cannot be null
        }
    } 

    class InternetAddressListExtended : InternetAddressList {}
    $List = New-Object InternetAddressListExtended # of type MimeKit.InternetAddress

     $message = [MimeKit.MimeMessage]::new()
     $TextPart = [MimeKit.TextPart]::new("html")

     [string[]]$recipients = "name@company.net".Split(',').Trim()
     $from = "Dev_Mailkit@company.net"
     $smtpSvr = 'xxx.xxx.xxx.xxx'
     $smtpPort = 25

     $message.From.Add($from)  
       foreach ($address in $recipients) {$List.Add($address)}
       $message.To.AddRange($List)

        $smtpClient = New-Object MailKit.Net.Smtp.SmtpClient

      $TextPart.Text = "Mailkit Test 30000"
      $message.Body = $TextPart
      $message.Subject = "Another Test" 

      if(!$smtpClient.IsConnected) {
    $smtpClient.Connect($smtpSvr)
    }
    if ($smtpClient.IsConnected) {
        $smtpClient.Send($message)
        $smtpClient.Disconnect($true)
        
    }```

@filimonic  I greatly appreciate the feedback,which is how I was able to overcome my initial obstacles.