Andrei Karcheuski
Andrei Karcheuski

Reputation: 3306

Download attachment from email directly to ftp server

I developed method that successfully downloading email attachments to local pc.
And I have to download them from email directly to ftp server too.
I tried to implement functionality that I was thinking should work.
As I successfully obtained FileAttachment object I tried to use its property ContentLocation to get the attachment URL
And then I pass that URL to webClient.DownloadString() method.
But unfortunately property ContentLocation is always null.
So I've got an exception in this row of code.
Here is complete listing of my method with comments:

    var service = new ExchangeService(ExchangeVersion.Exchange2013);
    service.Credentials = new NetworkCredential(serviceUserName, servicePassword);

    service.Url = new Uri(serviceUrl);
    ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
    var path = System.IO.Directory.CreateDirectory(Path.Combine(applicationPath, name));

    //Filters
    List<SearchFilter> searchANDFilterCollection = new List<SearchFilter>();
    searchANDFilterCollection.Add(new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false));
    searchANDFilterCollection.Add(new SearchFilter.IsEqualTo(EmailMessageSchema.From, new EmailAddress(email)));
    SearchFilter sf =
        new SearchFilter.SearchFilterCollection(LogicalOperator.And, searchANDFilterCollection.ToArray());
    FindItemsResults<Item> findResults;
    ItemView view = new ItemView(10);
    do
    {
        findResults = service.FindItems(WellKnownFolderName.Inbox, sf, view);
        if (findResults != null && findResults.Items != null && findResults.Items.Count > 0)
            foreach (EmailMessage item in findResults)
            {
                var message = EmailMessage.Bind(service, item.Id, new PropertySet(BasePropertySet.IdOnly, ItemSchema.Attachments, ItemSchema.HasAttachments));
                foreach (Attachment attachment in message.Attachments)
                {
                    if (attachment is FileAttachment)
                    {
                        if (attachment.Name.Contains(".xlsx") || attachment.Name.Contains(".xlsb") || attachment.Name.Contains(".xls") || attachment.Name.Contains(".csv"))
                        {
                            var fileAttachment = attachment as FileAttachment;

                            //Download to ftp
                            if (isSaveToFTP)
                            {
                                var webClient = new WebClient();
                                string readHtml = webClient.DownloadString(fileAttachment.ContentLocation);
                                byte[] buffer = Encoding.Default.GetBytes(readHtml);

                                WebRequest makeDirectory = WebRequest.Create(Path.Combine(ftpAddress, name));
                                makeDirectory.Method = WebRequestMethods.Ftp.MakeDirectory;
                                makeDirectory.Credentials = new NetworkCredential(username, password);
                                WebRequest uploadFile = WebRequest.Create(ftpAddress + name + "/" + fileAttachment.Name);
                                uploadFile.Method = WebRequestMethods.Ftp.UploadFile;
                                uploadFile.Credentials = new NetworkCredential(username, password);
                                Stream reqStream = uploadFile.GetRequestStream();
                                reqStream.Write(buffer, 0, buffer.Length);
                                reqStream.Close();
                            }
                            //Download to pc
                            else fileAttachment.Load(String.Format(@"{0}\{1}", path, fileAttachment.Name));
                        }
                    }
                    //fileAttachment.Load(path.Name);
                }
            }


        // mark email as read
        item.IsRead = true;
        item.Update(ConflictResolutionMode.AlwaysOverwrite);
      }
    }
    while (findResults.MoreAvailable); 

What should I change to get this work?
Or is there any another solution?

Upvotes: 2

Views: 1797

Answers (2)

Andrei Karcheuski
Andrei Karcheuski

Reputation: 3306

Here is the solution based on richrdsonmarkj's answer:

 if (isSaveToFTP)
        {
            using (WebClient webClient = new WebClient())
            {
                Stream stream = new MemoryStream();
                fileAttachment.Load(stream);
                using (var reader = new StreamReader(stream))
                {
                    byte[] buffer = Encoding.Default.GetBytes(reader.ReadToEnd());
                    WebRequest uploadFile = WebRequest.Create(ftpAddress + name + "/" + fileAttachment.Name);
                    uploadFile.Method = WebRequestMethods.Ftp.UploadFile;
                    uploadFile.Credentials = new NetworkCredential(username, password);
                    Stream reqStream = uploadFile.GetRequestStream();
                    reqStream.Write(buffer, 0, buffer.Length);
                    reqStream.Close();
                }
            }

Upvotes: 1

richardsonmarkj
richardsonmarkj

Reputation: 121

I think ContentLocation is dependent on the message creator. I think what you want to do instead is to use Load(Stream) to pull the content into a Stream and then choose where to write that Stream based on the isSaveToFTP flag.

Upvotes: 2

Related Questions