I’ve been trying to find a good way to download messages from Exchange without using CDO or MAPI as the program was going to run on the server which doesn’t have Outlook installed and admin didn’t want to have it there. I’ve been looking at WebDAV and I sucessfully managed to search emails and extract attachment names. However I failed to download them. I’ve searched a lot on the Internet but I could not find any working solution. I posted qustion on StackOverflow http://stackoverflow.com/questions/2491595/downloading-attachments-from-exchange-with-webdav but I didn’t get any reply so far.
In desperation I tried this library http://www.independentsoft.de/webdavex/index.html and it works pretty well. The only problem is the library is not free.
I ended up using code below.
Exchange version: 2003
Tool: Visual Studio 2008
Language: C#
Important: I have used this code in the program which is accessing Exchange server within Local Network Area.
I have no idea whether it works for remote connections or not. But it should be
public WebDAV(string mailboxURI,string user, string password, string domain)
{
this.strUserName = user;
this.strPassword = password;
this.strDomain = domain;
this.strMailboxURI = mailboxURI;
this.myCred = new NetworkCredential(this.strUserName, this.strPassword, this.strDomain);
}
....
// emlURL - http//server//Exchange/MailboxName/Inbox/SomeMessage.EML/SomeAttachment.xls
// fileName - new filename
// path - local path where file will be saved
// datareceived - optional I normally stick email date here
private void DownloadSingleAttachment(string emlURI, string fileName, string path, string datereceived)
{
// Create our request object
HttpWebRequest Req;
Req = (HttpWebRequest)WebRequest.Create(emlURI);
try
{
// Use Basic Authentication
CredentialCache myCredentialCache = new CredentialCache();
myCredentialCache.Add(new System.Uri(emlURI), "NTLM", myCred);
Req.Credentials = myCredentialCache;</code>
//Add the headers
Req.Headers.Add("Translate", "f");
Req.KeepAlive = true;
Req.AllowAutoRedirect = false;
Req.Method = "GET";
// Get the response for our request
HttpWebResponse Resp = (HttpWebResponse)Req.GetResponse();
switch (Resp.ContentType)
{
// add here whatever you need
case "message/rfc822":
case "application/vnd.ms-excel":
case "application/octet-stream":
case "application/pdf":
case "application/msword":
case "application/zip":
Stream stm = Resp.GetResponseStream();
// create file
FileStream file = new FileStream(path+fileName, System.IO.FileMode.Create);
byte[] buffer = new byte[4096];
int length;
length = smt.Read(buffer, 0, 4096);
while (length > 0)
{
file.Write(buffer, 0, length);
length = stm.Read(buffer, 0, 4096);
}
file.Close();
stm.Close();
break;
case "text/plain":
case "text/xml":
StreamReader sr = new StreamReader(Resp.GetResponseStream());
string strResp = sr.ReadToEnd();
sr.Close();
StreamWriter sw = new StreamWriter(fileName);
sw.Write(strResp);
sw.Close();
break;
}
Resp.Close();
}
catch (Exception)
{
throw;
}
}
Code I have tried and didn’t work for me.
I recieved this error:
The remote server returned an error: Forbidden.
static void Main(string[] args)
{
HttpWebRequest Request;
WebResponse Response;
CredentialCache MyCredentialCache;
string attachment = "http://mailserver/Exchange/Username/Inbox/Test.EML/Test.txt";
string strUserName = "username";
string strPassword = "password";
string strDomain = "domain";
try
{
//using HttpWebRequest
MyCredentialCache = new System.Net.CredentialCache();
MyCredentialCache.Add(new System.Uri(attachment), "NTLM", new NetworkCredential(strUserName, strPassword, strDomain));
Request = (HttpWebRequest)HttpWebRequest.Create(attachment);
Request.Credentials = MyCredentialCache;
Request.Method = "GET";
Response = (HttpWebResponse)Request.GetResponse();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message.ToString());
}
try
{
//using Web Client
string downloadPath = "D:\\Downloads";
WebClient wcClient = new WebClient();
wcClient.Credentials = new NetworkCredential(strUserName, strPassword, strDomain);
string file = Path.GetFileName(attachment);
string filename = Path.Combine(downloadPath, file);
wcClient.DownloadFile(attachment, filename);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message.ToString());
}
Console.ReadLine();
}
If anyone would like to see the rest of this class, which searches emails and scans for attachements I can post it here but it is pretty much the same code as in documentation on Microsoft website.
Hope that someone will find it useful.
CJ 5:08 pm on August 10, 2010 Permalink |
Hi,
Thanks for this posting. I had a request from a client of mine. They wanted to filter the attached email by the subject line. Which is the itemAttachment.Item.subject in your code. Then load the file attachment based on the subject line of the attached email to a folder that was named after the subject line. Since the email that they received could have multiple emails attached to them, and each attached email could have multiple attached files asscoiated. I am trying to figure out a way to link the item attachment with the file attachment in the attached email and group them by the item attachment subject.
Would you please give me some pointers on how to implement this?
Thanks in advance,
- CJ
arturito 4:39 pm on August 11, 2010 Permalink |
To be honest I’ve never had a need to do it.
But you could possibly compare the FileAttachment.ContentId with ItemAttachment.ContentId.
http://msdn.microsoft.com/en-us/library/dd636130(v=EXCHG.80).aspx
http://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.fileattachment_members(v=EXCHG.80).aspx
Hope this helps!