使用 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()?)。然后你正在寻找回到文件的开头,但是由于你没有读或写任何东西,你已经已经在文件的开头,所以这是没有意义的。
我实际上已经为 .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()?)。然后你正在寻找回到文件的开头,但是由于你没有读或写任何东西,你已经已经在文件的开头,所以这是没有意义的。