關於我自己

shih-chih huang
台北市, 萬華(家);內湖(公), Taiwan
在外人面前喜歡裝禮貌,在朋友面前喜歡說屁話;以前喜歡搞笑,現在傾向低調
檢視我的完整簡介

huge

huge
@ 慶修院

2008年3月28日 星期五

ASP.NET 取得 MSN 的聯絡人清單 (Get MSN Mail Contacts)


ASP.NET 取得 GMAIL 的聯絡人清單 (Get Google Contacts List)
以及
ASP.NET 取得 Yahoo! 的聯絡人清單 (Get Yahoo Mail Contacts)
兩篇文章之後,這一篇則是針對大家常用的Windows Live! Messenger取得所有連絡人的資訊。
其實跟Google及Yahoo都是類似的做法,主要都是使用HTTP protocol中的Request及Response取得瀏覽器以及伺服器往來的資訊。最後取得連絡人的資料後(通常是csv,或是通用xml格式)。

而這次要取得Windows Live Messenger連絡人的方式,老實說比以往還要複雜一些,因為要自己包裝SOAP envelope作為server response file(srf檔),最後再取得伺服器的回傳值(ticket)。這邊有個小問題跟Yahoo是一樣的,回傳的ticket開頭最前面的2個字元是 "t=",與當初取得Yahoo!聯絡人清單類似,只是Yahoo所得到的token前面有 "Y=" 兩個字元必須移除罷了。感謝SourceForge上讓我找到了OpenContacts.NET,否則我大概要多花一倍以上的時間去研讀各家的API。以下直接把取得ticket及擷取MSN連絡人的方法直接貼出來,這部份我有修改了一些OpenContacts.NET的內容,不過內容上並沒有什麼差異,主要是差在輸出的格式罷了 : )

WindowsLiveTicketAcquirer : 取得MSN伺服器回傳的ticket(認證)



internal class WindowsLiveTicketAcquirer {
private const string applicationId = "10"; // An arbitrary value that will be defined in the next non-alpha release

/// <summary>
/// generate SOAP envelope
/// </summary>
/// <param name="userName">user name</param>
/// <param name="password">password</param>
/// <returns>ticket</returns>
public String GetTicket(String userName, String password) {
string soapEnvelope =
@"<s:Envelope
xmlns:s = "
"http://www.w3.org/2003/05/soap-envelope""
xmlns:wsse = "
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd""
xmlns:saml = "
"urn:oasis:names:tc:SAML:1.0:assertion""
xmlns:wsp = "
"http://schemas.xmlsoap.org/ws/2004/09/policy""
xmlns:wsu = "
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd""
xmlns:wsa = "
"http://www.w3.org/2005/08/addressing""
xmlns:wssc = "
"http://schemas.xmlsoap.org/ws/2005/02/sc""
xmlns:wst = "
"http://schemas.xmlsoap.org/ws/2005/02/trust"">
<s:Header>
<wlid:ClientInfo xmlns:wlid = "
"http://schemas.microsoft.com/wlid"">
<wlid:ApplicationID>"
+ applicationId + @"</wlid:ApplicationID>
</wlid:ClientInfo>
<wsa:Action s:mustUnderstand = "
"1"">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</wsa:Action>
<wsa:To s:mustUnderstand = "
"1"">https://dev.login.live.com/wstlogin.srf</wsa:To>
<wsse:Security>
<wsse:UsernameToken wsu:Id = "
"user"">
<wsse:Username>"
+ userName + @"</wsse:Username>
<wsse:Password>"
+ password + @"</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</s:Header>
<s:Body>
<wst:RequestSecurityToken Id = "
"RST0"">
<wst:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</wst:RequestType>
<wsp:AppliesTo>
<wsa:EndpointReference>
<wsa:Address>http://live.com</wsa:Address>
</wsa:EndpointReference>
</wsp:AppliesTo>
<wsp:PolicyReference URI = "
"MBI""></wsp:PolicyReference>
</wst:RequestSecurityToken>
</s:Body>
</s:Envelope>"
;

const string url = @"https://dev.login.live.com/wstlogin.srf";
WebRequest request = WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/soap+xml; charset=UTF-8";
request.Timeout = 10 * 1000; // Wait for at most 10 seconds
byte[] bytes = Encoding.UTF8.GetBytes(soapEnvelope);
request.GetRequestStream().Write(bytes, 0, bytes.Length);
request.GetRequestStream().Close();
WebResponse response;
response = request.GetResponse();
string xml;
using (StreamReader reader = new StreamReader(response.GetResponseStream())) {
xml = reader.ReadToEnd();
}
response.Close();
XmlDocument document = new XmlDocument();
document.LoadXml(xml);
XmlNamespaceManager nsManager = new XmlNamespaceManager(document.NameTable);
nsManager.AddNamespace("wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
XmlNode node = document.SelectSingleNode(@"//wsse:BinarySecurityToken/text()", nsManager);
if (node == null) {
return null; // The wsse:BinarySecurityToken element is missing. Examine the xml for error information
}
else {
return node.Value;
}
}
}


LiveExtract : 取得MSN連絡人的主程式


WindowsLiveTicketAcquirer ticketAcq = new WindowsLiveTicketAcquirer();
String ticket = ticketAcq.GetTicket(userName, password).Substring(2);
UriBuilder urib = new UriBuilder();
urib.Scheme = SCHEME;
urib.Path = String.Format("/{0}/LiveContacts", userName);
urib.Host = HOST;
urib.Port = PORT;
HttpWebRequest req = WebRequest.Create(urib.Uri) as HttpWebRequest;
req.Headers.Add(HttpRequestHeader.Authorization, String.Format("WLID1.0 t=\"{0}\"", ticket));
WebResponse response = req.GetResponse();

if (response.ContentLength != 0) {
XmlDocument doc = new XmlDocument();
doc.Load(response.GetResponseStream());

#region 取得所有的 Contacts 並依結果建立 WindowsLiveContact 類別

XmlNodeList contacts = doc.SelectNodes("/LiveContacts/Contacts/Contact");
this.liveContactList = new List<WindowsLiveContact>();
XmlNode firstName, lastName, nickName, uniqueName, sortName, displayName, email, windowsLiveID, groupName;
foreach (XmlNode node in contacts) {
firstName = node.SelectSingleNode("Profiles/Personal/FirstName");
lastName = node.SelectSingleNode("Profiles/Personal/LastName");
nickName = node.SelectSingleNode("Profiles/Personal/NickName");
uniqueName = node.SelectSingleNode("Profiles/Personal/UniqueName");
sortName = node.SelectSingleNode("Profiles/Personal/SortName");
displayName = node.SelectSingleNode("Profiles/Personal/DisplayName");
email = node.SelectSingleNode("Emails/Email/Address");
windowsLiveID = node.SelectSingleNode("WindowsLiveID");
//groupName = node.SelectSingleNode("Tags/Tag");

WindowsLiveContact lc = new WindowsLiveContact();
lc.FirstName = firstName == null ? string.Empty : firstName.InnerText;
lc.LastName = lastName == null ? string.Empty : lastName.InnerText;
lc.NickName = nickName == null ? string.Empty : nickName.InnerText;
lc.UniqueName = uniqueName == null ? string.Empty : uniqueName.InnerText;
lc.SortName = sortName == null ? string.Empty : sortName.InnerText;
lc.DisplayName = displayName == null ? string.Empty : displayName.InnerText;
lc.Email = email == null ? string.Empty : email.InnerText;
lc.WindowsLiveID = windowsLiveID == null ? string.Empty : windowsLiveID.InnerText;
lc.GroupName = string.Empty;
this.liveContactList.Add(lc);
}

this.sourceTable = new DataTable();
this.sourceTable.Columns.Add(new DataColumn(ContactColumn.DisplayName));
this.sourceTable.Columns.Add(new DataColumn(ContactColumn.Email));
this.sourceTable.Columns.Add(new DataColumn(ContactColumn.FirstName));
this.sourceTable.Columns.Add(new DataColumn(ContactColumn.FullName));
this.sourceTable.Columns.Add(new DataColumn(ContactColumn.GroupName));
this.sourceTable.Columns.Add(new DataColumn(ContactColumn.LastName));
this.sourceTable.Columns.Add(new DataColumn(ContactColumn.NickName));
this.sourceTable.Columns.Add(new DataColumn(ContactColumn.SortName));
this.sourceTable.Columns.Add(new DataColumn(ContactColumn.UniqueName));
this.sourceTable.Columns.Add(new DataColumn(ContactColumn.WindowsLiveID));
DataRow row = null;
foreach (WindowsLiveContact lc in this.liveContactList) {
row = this.sourceTable.NewRow();
row[ContactColumn.DisplayName] = lc.DisplayName;
row[ContactColumn.Email] = lc.Email;
row[ContactColumn.FirstName] = lc.FirstName;
row[ContactColumn.FullName] = lc.FullName;
row[ContactColumn.GroupName] = lc.GroupName;
row[ContactColumn.LastName] = lc.LastName;
row[ContactColumn.NickName] = lc.NickName;
row[ContactColumn.SortName] = lc.SortName;
row[ContactColumn.UniqueName] = lc.UniqueName;
row[ContactColumn.WindowsLiveID] = lc.WindowsLiveID;
this.sourceTable.Rows.Add(row);
}

this.sourceTable.AcceptChanges();

#endregion

}

1 意見:

匿名 提到...

你好:
我在写一个关于windows live contacts的程序。有些问题想请教你

我的email/msn:knyanyan@hotmail.com

方便的话能否和我联系。谢谢

阎彦