【问题标题】:GetMessage id out of range from search scopeGetMessage id 超出搜索范围
【发布时间】:2018-07-31 11:22:09
【问题描述】:

我正在尝试使用 Powershell 中的 MailKit 连接到 IMAP 服务器。 连接到服务器,打开收件箱,搜索子文件夹,选择并打开子文件夹,查询所有消息(SeqrchQuery)并尝试获取最后一条消息。 示例代码:

'BouncyCastle.Crypto', 'mimekit', 'mailkit', 'Microsoft.Extensions.Options', 'cloudscribe.Messaging.Email' | %{Add-Type -Path "$(Join-Path 'D:\Mailkit' ($_ + '.dll'))"}
$mll = New-Object MailKit.Net.Imap.ImapClient
$ctoken = New-Object System.Threading.CancellationToken ($false)
$ssl = [MailKit.Security.SecureSocketOptions]::Auto
$mll.Connect('server.name', 993, $ssl, $ctoken)
$mll.Authenticate(([System.Text.Encoding]::UTF8) , "user@server.name", "pass" , $ctoken)
$inbox = $mll.Inbox
$inbox.Open([MailKit.FolderAccess]::ReadOnly) | Out-Null
$inbox = $inbox.GetSubfolders($false) | ?{$_.Name -eq 'SUBFOLDER'}
$inbox.Open([MailKit.FolderAccess]::ReadOnly) | Out-Null
$src = $inbox.Search([MailKit.Search.SearchQuery]::All) 
$msg = $src | select -Last 1
try {$inbox.GetMessage($msg.Id)}
catch {
$_
}
$inbox.Close()
$mll.Disconnect($true , $ctoken)
Remove-Variable mll,inbox,msg,src,ctoken,ssl

并得到错误:

Exception calling "GetMessage" with "1" argument(s): "Argument value out of range.
Parameter name: index"
At line:23 char:1
+ $inbox.GetMessage($msg.Id)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentOutOfRangeException

【问题讨论】:

  • 我尝试将 \Seen 标志设置为最后收到的消息,将搜索查询更改为 $inbox.Search([MailKit.Search.SearchQuery]::NotSeen) | %{$inbox.GetMessage($_.id)} 并打开内置 MailKit 日志记录。并收到同样的错误。 S: * 476 EXISTS S: * 0 RECENT S: * OK [UNSEEN 476] First unseen. S: * OK [UIDVALIDITY 1415271545] UIDs valid S: * OK [UIDNEXT 477] Predicted next UID S: * OK [HIGHESTMODSEQ 4] Highest S: L00000006 OK [READ-ONLY] Examine completed (0.001 secs). C: L00000007 UID SEARCH RETURN () UNSEEN S: * ESEARCH (TAG "L00000007") UID ALL 476
  • 请不要将您的解决方案添加到您的问题中,将其作为答案发布并标记为已接受。
  • 你不能仅仅减去 1 来使其工作。你在这里很幸运。请参阅我的答案以获得正确的解决方案。

标签: powershell mailkit


【解决方案1】:

您遇到的问题是 MailKit 有两个版本的ImapFolder.GetMessage()

ImapFolder.GetMessage (int index)
ImapFolder.GetMessage (UniqueId uid)

Search() 方法返回UniqueId 值的列表。 UniqueId 结构有一个名为 Id 的成员,它是一个 uint

当您将$msg.Id 传递给GetMessage() 时,它调用的是int 版本的API,而不是UniqueId 版本。

对于 IMAP,有两种访问消息的方式。您可以通过它们的索引访问它们,也可以通过它们的唯一标识符访问它们。

两者看起来都像整数,但不能互换。

您需要使用$inbox.GetMessage ($msg)

【讨论】:

  • 感谢您的回答!但也许可以在 uidid? 之间转换
  • 我必须定义id的类型,比如%{$id = [MailKit.UniqueId]($_.Id) ; $msg = $inbox.GetMessage($id)
  • 不,没有办法在 2 之间正确转换
【解决方案2】:

感谢@jstedfast 的解释。 为了正确工作,我必须在方法调用中定义变量类型。 正确代码:

$mll = New-Object MailKit.Net.Imap.ImapClient
$ctoken = New-Object System.Threading.CancellationToken ($false)
$ssl = [MailKit.Security.SecureSocketOptions]::Auto
$mll.Connect('server.name', 993, $ssl, $ctoken)
$mll.Authenticate(([System.Text.Encoding]::UTF8) , "user@server.name", "pass" , $ctoken)
$inbox = $mll.Inbox
$inbox.Open([MailKit.FolderAccess]::ReadOnly) | Out-Null
$inbox = $inbox.GetSubfolders($false) | ?{$_.Name -eq 'SUBFOLDER'}
$inbox.Open([MailKit.FolderAccess]::ReadOnly) | Out-Null
$src = $inbox.Search([MailKit.Search.SearchQuery]::All) 
$msg = $src | select -Last 1
try { $id = [MailKit.UniqueId]($msg.Id) ; $inbox.GetMessage($id) }
catch { $_ }
$inbox.Close()
$mll.Disconnect($true , $ctoken)

【讨论】:

    【解决方案3】:

    这应该使用您的 Uint 值创建一个 UID:

    $UID = New-Object Mailkit.UniqueId(Msg.Id)
    

    然后使用 $UID 而不是 msg.id 调用您的 inbox.getMessage

    try {
      $inbox.GetMessage($UID)
    } catch { 
      $_ 
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-04
      • 2018-03-01
      • 1970-01-01
      相关资源
      最近更新 更多