2016年3月8日 星期二

利用 Webdav 取得Exchange Serivce Mail 資訊

工作時遇到一個需求希望程式能自動連線到Exchange Server 取得指定帳號的Mail 資料

並依據收到的信件標題作相對應的動作

當時是用一個老前輩開發的物件完成這個需求但是對其運行原理很好奇因此針對該物件作分析

發現他是使用Webdav 協定與Exchange Server 做連線的

WebDAV 相關文件

http://technet.microsoft.com/zh-tw/library/ms876446.aspx

下面就介紹我是如何使用的

使用方式

在實地介紹時請先按照下列步驟進行前置作業

l 請先找一個Exchange Server 下的一個Mail Account

l 確認該Exchange Server 支援Webdav

l 請根據您實際的帳號資訊於TestFixtureSetUp 下填寫對應的帳號設定

使用程式碼

using System;

using System.Collections.Generic;

using System.Linq;

using System.Windows.Forms;

using System.IO;

using System.Net;

using System.Text;

using System.Web;

using System.Xml;

using NUnit.Framework;

namespace Webdav_Test

{

[TestFixture]

public class WebDAV_Test

{

private string _domain;

private string _mailAccount;

private string _password;

private string _server;

private string _userName;

private string _mailFolder;

[TestFixtureSetUp]

public void TestFixtureSetup()

{

//Domain 名稱

_domain = "Domain Name";

//Mail 帳號

_mailAccount = "Mail Account";

//AD Server 主機名稱 (IP 也可以)

_server = "Mail Server";

//使用者 帳號

_userName = "User Name";

//使用者 密碼

_password = "User Password";

//要讀取的郵件資料夾

_mailFolder = "Mail Folder";

//求ReceivedDate以後的信件資料

_receivedDate = Convert.ToDateTime("2012/09/20");

}

[Test]

//利用WebDAV 取得Exchange 的Mail 資料夾並 取得 2012/09/20 以後送到的信件資料

//列出搜尋到Mail 的 Tile 與 檔案名稱 與 顯示該Mail 是否有夾帶檔案

public void WebDAV_GetMails_Test()

{

List<MailItem> mails = new List<MailItem>();

// Variables.

string strRootURI = string.Format("http://{0}/exchange/{1}/{2}", _server, _mailAccount, _mailFolder);

// Build the SQL query.

string strQuery = " "

+ " "

+ " SELECT \"urn:schemas:httpmail:subject\", \"urn:schemas:httpmail:hasattachment\",\"urn:schemas:httpmail:datereceived\" "

+ "FROM scope('shallow traversal of \"" + strRootURI +"\"') "

+ " WHERE \"DAV:ishidden\"=False AND \"DAV:isfolder\"=False ORDER BY \"urn:schemas:httpmail:datereceived\" DESC ";

// Create a new CredentialCache object and fill it with the network

// credentials required to access the server.

CredentialCache MyCredentialCache = new CredentialCache();

MyCredentialCache.Add(new Uri(strRootURI),

"NTLM",

new NetworkCredential(_userName, _password, _domain)

);

// Create the HttpWebRequest object.

HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(strRootURI);

// Add the network credentials to the request.

Request.Credentials = MyCredentialCache;

// Specify the method.

Request.Method = "SEARCH";

// Encode the body using UTF-8.

byte[] bytes = Encoding.UTF8.GetBytes(strQuery);

// Set the content header length. This must be

// done before writing data to the request stream.

Request.ContentLength = bytes.Length;

// Get a reference to the request stream.

Stream RequestStream = Request.GetRequestStream();

// Write the SQL query to the request stream.

RequestStream.Write(bytes, 0, bytes.Length);

// Close the Stream object to release the connection

// for further use.

RequestStream.Close();

// Set the content type header.

Request.ContentType = "text/xml";

// Send the SEARCH method request and get the

// response from the server.

WebResponse Response = Request.GetResponse();

// Get the XML response stream.

Stream ResponseStream = Response.GetResponseStream();

// Create the XmlTextReader object from the XML

// response stream.

XmlTextReader XmlReader = new XmlTextReader(ResponseStream);

// Read through the XML response, node by node.

while (XmlReader.Read())

{

// Console.WriteLine("{0}, {1}", XmlReader.Name, XmlReader.Value);

// Look for the opening DAV:href node. The DAV: namespace is

//typically assigned the a: prefix in the XML response body.

if (XmlReader.Name == "a:href")

{

// Advance the reader to the text node.

XmlReader.Read();

// Console.WriteLine("{0}, {1}", XmlReader.Name, XmlReader.Value);

string path = XmlReader.Value;

string title = "";

string hasAttachment = "0";

DateTime dateReceived = DateTime.MinValue;

//ahref close tag

XmlReader.Read();

// Console.WriteLine("{0}, {1}", XmlReader.Name, XmlReader.Value);

while (XmlReader.Name != "a:prop")

{

XmlReader.Read();

// Console.WriteLine("{0}, {1}", XmlReader.Name, XmlReader.Value);

}

XmlReader.Read();

// Console.WriteLine("{0}, {1}", XmlReader.Name, XmlReader.Value);

while (XmlReader.Name != "a:prop")

{

switch (XmlReader.Name)

{

case "d:subject":

XmlReader.Read();

title = XmlReader.Value;

XmlReader.Read();

break;

case "d:hasattachment":

XmlReader.Read();

hasAttachment = XmlReader.Value;

XmlReader.Read();

break;

case "d:datereceived":

XmlReader.Read();

dateReceived = Convert.ToDateTime(XmlReader.Value);

XmlReader.Read();

break;

}

XmlReader.Read();

}

if (dateReceived < _receivedDate)

{

break;

}

MailItem item = new MailItem(title, path);

item.HasAttachment = hasAttachment == "1";

mails.Add(item);

//Advance the reader to the closing DAV:href node.

XmlReader.Read();

// Console.WriteLine("{0}, {1}", XmlReader.Name, XmlReader.Value);

}

}

// Clean up.

XmlReader.Close();

ResponseStream.Close();

Response.Close();

Console.WriteLine("以下為信箱所有Mial的標題與檔案名稱");

foreach (var mail in mails)

{

Console.WriteLine("Mail Title:" + mail.Title);

Console.WriteLine("Mail Path:" + mail.Path);

Console.WriteLine("Mail have Attachment :" + mail.HasAttachment.ToString());

}

}

}

}

------ Test started: Assembly: IonicZipProject.dll ------

以下為信箱所有Mial的標題與檔案名稱

Mail Title: TEST Mail From Robin

Mail Path: http:// Domain /exchange/Feng.Robin/ TEST%20Mail%20From%20Robin.EML

Mail have Attachment :True

程式細部說明

連線前請將Domain 名稱 , Mail 帳號 , AD Server 主機名稱 (IP 也可以), 使用者 帳號, 使用者 密碼, 要讀取的郵件資料夾 , ReceivedDate設定好

Mail 帳號 只要取Mail帳號@之前的名稱及可

ReceivedDate 的設定主要是要跟程式說你只要收到日期大於ReceivedDate 的Mail

範例程式使用的設定為了保護個資用的都是假的 如果直接照抄程式碼的話那我保障跑到死都跑不出來

以下為信箱所有Mial的標題與檔案名稱

當設定部分都沒問題了 程式就會列出所有的信件資料

包含信件的標題 , 信件放置的檔案位置 , 以及判定Mail 是否有夾帶檔案

P.S.我測試都是使用NUnit 配合 TestDriven.NET 來測試結果因此沒有裝的人可以參考我網站的 簡介與使用> 和簡介與使用>

進行安裝 在此不贅述了~~~~

以上教學歡迎轉載但是請註明源頭來自

胖雀鳥的妄想天地http://tw.myblog.yahoo.com/big-suzume

沒有留言: