0

I actually had this working for .pdf files and could not get it to work for .xls.

Now I cannot seem to get ether to work. Note I have looked at all other post from jsteadfast and this is the code I came up with.

When I read the Message I have nothing in Attachments there are 2 files the body of the text in a .txt file and the attachment which is in the .pdf or .xls file both are in message.BodyParts.

I just want to save the attachments to a file share. This is a .NET worker service. Azure Active Directory. Mailbox is outlook.office365.com.

In my stream I get

"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);
        }
    }
}

I have also tried the following code example that should work as well according to jsteadfast. As you can see here I am trying to set the stream.Position. Just to be clear the file is being saved to the file share. but with no data. Any help would be greatly appreciated.

                        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);
                                }
                            }
                        }
tirwin
  • 3
  • 2

1 Answers1

0

Looking at your code:

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);
    }
}

You are creating a file stream called stream (which will be empty). Then you create a second file stream called fileStream.

Next, you are copying the contents of stream into fileStream but stream is empty because you just created it and so it would be empty.

In your second code sample, what does the method SaveStreamToDirectory(stream, fileName, armadaTargetDir); look like? My guess is that you need to rewind stream (aka seek back to position 0) in order to read from the stream.

Note: In your second example, after creating stream, you immediately call stream.Flush(); and then stream.Seek(0, SeekOrigin.Begin);. Neither of these calls make any sense to do right after creating the stream. When you call Flush(), you are telling the stream to write all of its buffered data to the file (but you haven't written anything, so why would you call Flush()?). Then you are seeking back to the beginning of the file, but since you haven't read or written anything, you are already at the beginning of the file, so it is pointless.

jstedfast
  • 35,744
  • 5
  • 97
  • 110