如何在Powershell中编写代码以检查imap帐户上是否有未读邮件?

时间:2019-01-21 13:29:05

标签: powershell email imap

我似乎在这里用措辞不清楚的措辞来表达我的问题:

如何在Powershell中编写脚本代码,该脚本检查第三方imap帐户是否存在未读邮件。 记住的帐户使用具有用户/密码授权的TSL。

1 个答案:

答案 0 :(得分:1)

IMAP不是一个复杂的协议,它是基于行的,并且相关命令的数量是有限的,特别是如果您只想检查收件箱中的未读邮件,则更是如此。

因此,在System.Net.Sockets.TcpClient之上构建IMAP客户端非常简单。 SSL / TLS有点复杂,但还算不错。

与IMAP服务器的对话如下:

Client: A001 command argument argument
Server: * response line 1
        * response line 2
        A001 OK response line 3

其中A001是命令标签,用于标识命令。通常,它采用递增计数器的形式(a1a2a3等),但实际上可以是任何东西。服务器在其响应的最后一行重复命令标签。

与GMail IMAP服务器的示例对话(显然,身份验证失败):

* OK Gimap ready for requests from 213.61.242.253 g189mb36880374lfe
a1 CAPABILITY
* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 XYZZY SASL-IR AUTH=XOAUTH2 AUTH=PLAIN AUTH=PLAIN-CLIENTTOKEN AUTH=OAUTHBEARER AUTH=XOAUTH
a1 OK Thats all she wrote! g189mb36880374lfe
a2 LOGIN test test
a2 NO [AUTHENTICATIONFAILED] Invalid credentials (Failure)
a3 LOGOUT
* BYE Logout Requested g189mb36880374lfe
a3 OK Quoth the raven, nevermore... g189mb36880374lfe

执行此操作的Powershell代码不太复杂:

using namespace System.IO;
using namespace System.Text;
using namespace System.Net.Sockets;
using namespace System.Net.Security;
using namespace System.Security.Cryptography.X509Certificates;

Set-StrictMode -Version 2.0
$DebugPreference = "Continue"   # set to "SilentlyContinue" to hide Write-Debug output

$CRLF = "`r`n"

$server = "imap.gmail.com"
$port = 993
$username = "test"
$password = "test"

# connect to server
$client = [TcpClient]::new($server, $port)
$client.ReceiveTimeout = 2000 #milliseconds

# set up SSL stream, be lenient about the server's certificate
$acceptAnyCertificate = [RemoteCertificateValidationCallback] { $true }
$sslStream = [SslStream]::new($client.GetStream(), $false, $acceptAnyCertificate)
$sslStream.AuthenticateAsClient($server)

function StreamWrite {
    param([Stream]$stream, [string]$command, [Encoding]$enc = [Encoding]::ASCII)
    $data = $enc.GetBytes($command)
    Write-Debug "> $($command.trim())"
    $stream.Write($data, 0, $data.Length)
}
function StreamRead {
    param([Stream]$stream, [int]$bufsize = 4*1KB, [Encoding]$enc = [Encoding]::ASCII)
    $buffer = [byte[]]::new($bufsize)
    $bytecount = $stream.Read($buffer, 0, $bufsize)
    $response = $enc.GetString($buffer, 0, $bytecount)
    Write-Debug "< $($response.trim())"
    $response
}

# read server hello
$response = StreamRead $sslStream

StreamWrite $sslStream ("a1 CAPABILITY" + $CRLF)
$response = StreamRead $sslStream

# log in
StreamWrite $sslStream ("a2 LOGIN $username $password" + $CRLF)
$response = StreamRead $sslStream

# send mailbox commands...

# log out
StreamWrite $sslStream ("a3 LOGOUT" + $CRLF)
$response = StreamRead $sslStream

$sslStream.Close()
$client.Close()

您的邮箱命令可能是一个简单的select inbox,服务器会向其回复一堆信息,包括看不见的电子邮件数量(an example can be seen on the Wikipedia):

C:   a002 select inbox
S:   * 18 EXISTS
S:   * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
S:   * 2 RECENT
S:   * OK [UNSEEN 17] Message 17 is the first unseen message
S:   * OK [UIDVALIDITY 3857529045] UIDs valid
S:   a002 OK [READ-WRITE] SELECT completed

您可能需要对邮件服务器进行一些试验,但是应该很容易弄清楚必要的细节。

如果您的服务器需要这样做,请阅读Connecting to smtp.live.com with the TcpClient class来了解如何执行STARTTLS而不是SSL