微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决使用 MailKit IMAP 读取附件并将​​其保存到文件共享获取 stream.Read、stream.Write 超时错误

实际上,我让它适用于 .pdf 文件,但无法让它适用于 .xls

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

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

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

在我的流中我得到

"WriteTimeout = {stream.WriteTimeout' 抛出了一个类型为 '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,stoppingToken);
                        imapclient.AuthenticationMechanisms.Remove(authenticationResult.Accesstoken);
                        imapclient.Authenticate(new SaslMechanismOAuth2(userName,stoppingToken);
                        imapclient.InBox.Open(FolderAccess.ReadWrite);

                        var messages = imapclient.InBox.Fetch(0,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,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,armadaTargetDir); 是什么样的?我的猜测是您需要倒带 stream(也就是返回到位置 0)才能从流中读取数据。

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。