使用 MailKit IMAP 读取附件并将​​其保存到文件共享。出现 stream.Read、stream.Write 超时错误

Using MailKit IMAP to read and save attachment to file share. Getting stream.Read, stream.Write timeout errors

我实际上已经为 .pdf 个文件工作,但无法让它为 .xls 工作。

现在我似乎无法让以太币工作。请注意,我查看了 jsteadfast 的所有其他 post,这是我想出的代码。

当我阅读消息时,附件中没有任何内容,有 2 个文件,文本正文在 .txt 文件中,附件在 .pdf.xls 中文件都在 message.BodyParts.

我只想将附件保存到文件共享中。这是一个 .NET 工作者服务。 Azure 活动目录。邮箱是outlook.office365.com.

在我的信息流中我得到

"WriteTimeout = {stream.WriteTimeout' threw an exception of type 'System.InvalidOperationException}"

using (var imapclient = new ImapClient())
{
    imapclient.Connect(mailbox, port, SecureSocketOptions.SslOnConnect, stoppingToken);
    imapclient.AuthenticationMechanisms.Remove(authenticationResult.AccessToken);
    imapclient.Authenticate(new SaslMechanismOAuth2(userName, authenticationResult.AccessToken), stoppingToken);
    imapclient.Inbox.Open(FolderAccess.ReadWrite);

    var messages = imapclient.Inbox.Fetch(0, -1, MessageSummaryItems.Full | MessageSummaryItems.UniqueId);
    int unnamed = 0;

    foreach (var message in messages)
    {
        var multipart = message.Body as BodyPartMultipart;
        var basic = message.Body as BodyPartBasic;
        var bodyParts = message.BodyParts.ToList(); //Foreach message.BodyParts bodyParts[0] contains .txt, bodyParts[1] contains .pdf
        var archive = imapclient.GetFolder(_archive);

        if (multipart != null)
        {
            foreach (var attachment in bodyParts)
            {
                if (!string.IsNullOrEmpty(attachment.FileName)) //when it's .pdf it has a FileName 
                {
                    var mime = (MimePart)imapclient.Inbox.GetBodyPart(message.UniqueId, attachment);
                    var fileName = mime.FileName;

                    if (string.IsNullOrEmpty(fileName))
                        fileName = string.Format("unnamed-{0}", ++unnamed);

                    using (var stream = File.Create(fileName))
                    {
                        string[] splitFileName = fileName.Split(".");

                        fileName = splitFileName[0] + string.Format("_{0:MM-dd-yyyy_HH-mm-ss-fff}", DateTime.Now) + "." + splitFileName[1];

                        //SaveStreamToDirectory(stream, fileName, armadaTargetDir);
                        using (var fileStream = new FileStream(Path.Combine(armadaTargetDir, fileName), FileMode.Create, FileAccess.Write))
                        {
                            stream.CopyTo(fileStream);
                        }
                    }

                    //imapclient.Inbox.MoveTo(message.UniqueId, archive);
                }
            }
        }
        else if (basic != null && basic.IsAttachment)
        {
            var mime = (MimePart)imapclient.Inbox.GetBodyPart(message.UniqueId, basic);
            var fileName = mime.FileName;

            if (string.IsNullOrEmpty(fileName))
                fileName = string.Format("unnamed-{0}", ++unnamed);

            using (var stream = File.Create(fileName))
                mime.ContentObject.DecodeTo(stream);
        }
    }
}

我还尝试了以下代码示例,根据 jsteadfast 的说法,它应该也能正常工作。正如您在这里看到的,我正在尝试设置 stream.Position。需要明确的是,文件正在保存到文件共享中。但没有数据。任何帮助将不胜感激。

                        using (var imapclient = new ImapClient())
                    {
                        imapclient.Connect(mailbox, port, SecureSocketOptions.SslOnConnect, stoppingToken);
                        imapclient.AuthenticationMechanisms.Remove(authenticationResult.AccessToken);
                        imapclient.Authenticate(new SaslMechanismOAuth2(userName, authenticationResult.AccessToken), stoppingToken);
                        imapclient.Inbox.Open(FolderAccess.ReadWrite);

                        var messages = imapclient.Inbox.Fetch(0, -1, MessageSummaryItems.Full | MessageSummaryItems.UniqueId);
                        int unnamed = 0;

                        IList<UniqueId> uids = imapclient.Inbox.Search(SearchQuery.All);

                        foreach (UniqueId uid in uids)
                        {
                            MimeMessage message = imapclient.Inbox.GetMessage(uid);

                            foreach (MimeEntity attachment in message.Attachments)
                            {
                                var fileName = attachment.ContentDisposition?.FileName ?? attachment.ContentType.Name;

                                using (var stream = File.Create(fileName))
                                {
                                    stream.Flush();
                                    stream.Seek(0, SeekOrigin.Begin);

                                    if (attachment is MessagePart)
                                    {
                                        var rfc822 = (MessagePart)attachment;

                                        rfc822.Message.WriteTo(stream);
                                    }
                                    else
                                    {
                                        var part = (MimePart)attachment;

                                        part.Content.DecodeTo(stream);

                                    }

                                    SaveStreamToDirectory(stream, fileName, armadaTargetDir);
                                }
                            }
                        }

查看您的代码:

using (var stream = File.Create(fileName))
{
    string[] splitFileName = fileName.Split(".");

    fileName = splitFileName[0] + string.Format("_{0:MM-dd-yyyy_HH-mm-ss-fff}", DateTime.Now) + "." + splitFileName[1];

    //SaveStreamToDirectory(stream, fileName, armadaTargetDir);
    using (var fileStream = new FileStream(Path.Combine(armadaTargetDir, fileName), FileMode.Create, FileAccess.Write))
    {
        stream.CopyTo(fileStream);
    }
}

您正在创建一个名为 stream 的文件流(它将为空)。然后创建第二个文件流,名为 fileStream.

接下来,您要将 stream 的内容复制到 fileStream 中,但是 stream 是空的,因为您刚刚创建它,所以它应该是空的。

在您的第二个代码示例中,方法 SaveStreamToDirectory(stream, fileName, armadaTargetDir); 是什么样子的?我的猜测是您需要倒回 stream(又名回到位置 0)才能从流中读取。

注意:在您的第二个示例中,在创建 stream 之后,您立即调用 stream.Flush();,然后调用 stream.Seek(0, SeekOrigin.Begin);。在创建流后立即执行这些调用都没有任何意义。当您调用 Flush() 时,您是在告诉流将其所有缓冲数据写入文件(但您没有写入任何内容,那么为什么要调用 Flush()?)。然后你正在寻找回到文件的开头,但是由于你没有读或写任何东西,你已经已经在文件的开头,所以这是没有意义的。