Reputation: 3306
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
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
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