2017年6月9日 星期五
2016年11月24日 星期四
SMTP–send mail by Telnet
1.開啟命令列(CMD)
2.Telnet your_server_ip 25 <Enter>
連線後會出現mail主機相關訊息
-
開啟 telnet 工作階段:在命令提示字元中,輸入 telnet,然後按 ENTER。
-
在執行 Microsoft Windows® 2000 Server 的電腦上輸入 set local_echo,或在執行 Windows Server™ 2003 或 Windows XP 的電腦上輸入 SET LOCALECHO,然後按 ENTER。此命令可讓您檢視命令的回應。
附註:如需可用的 telnet 命令的清單,請輸入 set ?。 -
輸入 o <您的郵件伺服器網域> 25,然後按 ENTER。
-
輸入 EHLO <您的郵件伺服器網域>,然後按 ENTER。
-
輸入 AUTH LOGIN。伺服器會回應您使用者名稱的加密提示。
-
輸入您以 base 64 加密的使用者名稱。您可以使用任一種可用來將使用者名稱編碼的工具。
例: 網域\使用者名稱(以下方工具編碼成base64貼上後按<Enter>
(工具:http://www.convertstring.com/zh_TW/EncodeDecode/Base64Encode) -
伺服器會回應您密碼的 base 64 加密提示。請輸入以 base 64 加密的密碼。
-
輸入 MAIL FROM:<sender@domain.com>,然後按 ENTER。如果不允許寄件者傳送郵件,則 SMTP 伺服器會傳回錯誤。
-
輸入 RCPT TO:<recipient@remotedomain.com>,然後按 ENTER。如果收件者不是有效的收件者或伺服器未接受此網域的郵件,則 SMTP 伺服器會傳回錯誤。
-
輸入 DATA。
-
您可以視需要輸入郵件文字、按 ENTER、輸入句點 (.),然後再次按 ENTER。
-
如果郵件運作正常,您應該會看到與下列類似的回應,指出該郵件已在佇列中等待傳遞:
2016年4月25日 星期一
防止我公司的 MAIL 不會被設定為 垃圾郵件(SPAM)
公司的業務和主管向你抱怨,
Mail 寄出給國外客戶和廠商都收不到(跑倒垃圾信件匣)
甚至被當成垃圾郵件退回來?!
這一篇是寫給公司 IT/MIS 人員參考
1. 維護好公司的 smtp relay 安全
1.1 假設貴公司開放 SMTP ports 讓外部可以透過 smtp 發信
則要做好權限控管,沒有透過認證者 or IP 不再安全清單一律不許使用 SMTP 發信。
(也可考慮 VPN)
1.2 定期檢查使用者是否濫用 SMTP 寄送非公司相關信件
1.3 定期檢查使用者電腦是否中毒、中木馬成為發送廣告信的跳板
1.4 教育使用者足夠的資訊安全概念
1.5 請主要客戶、廠商幫忙,設定從公司來的郵件為「非垃圾郵件」
e.g.
Google Gmail 篩選器 (Filter) -> 不要將它傳送到垃圾郵件
http://mail.google.com/support/bin/answer.py?hl=b5&answer=6579
Yahoo奇摩 信箱的 「自動分類」
http://tw.promo.yahoo.com/tutorial/mail20/cg_filter1.html
Microsoft Outlook 的 「安全的收件者」
http://office.microsoft.com/zh-tw/outlook/HP052433571028.aspx
1.6 安裝相關的 Antivirus Mail Gateway or Mail-Server AntiVirus
1.7 定期檢查 Delivery Failures 的信件,
看看是否有定期寄給客戶、廠商的 mail address 已經失效,sent failed
請聯絡他們更換 address,減少 send/deliver failures。
2. 設定 DNS SPF TXT (Sender Policy Framework)記錄
詳細請看官網 http://www.openspf.org/
2.1 如何檢查 SPF TXT 記錄?
=> 使用 SPF 官網提供的 Tools
http://www.openspf.org/Why
http://www.kitterman.com/spf/validate.html
=> 或者用 dig 來查詢 Google & Hinet's public DNS
代碼:
dig @8.8.8.8 -t TXT your-company-org-school.com
dig @168.95.1.1 -t TXT your-company-org-school.com
2.2 或者寄送一封信到 spf-test@openspf.org
然後一分鐘內,你就會收到一個退信,
裡面有 Result="pass" 表示通過 SPF 測試驗證
如果是 Result="none" 那就表示 SPF 還沒有設定完成
2.3 如果你是使用 Google Apps 應用服務 (Google 代管郵件)
你的 SPF 應該長得是這樣子,都在同一行! 有 "double quote"
然後 all 前面是 ~ 波浪符號
代碼:
"v=spf1 include:aspmx.googlemail.com ~all"
2.4 另外記住 TXT 也是 DNS entries 的一部分,DNS 生效需要 24~48 小時。
2.5 舉例,成功的設定 SPF 會讓 Google Mail Gmail 更不會誤判垃圾信件
Example BEFORE-SET-SPF-TXT "NEUTRAL"
未設定之前,判定為「中立」
代碼:
Received-SPF: neutral (google.com: 74.125.82.52 is neither permitted nor denied by domain of XXXXXXXX) client-ip=74.125.82.52;
Authentication-Results: mx.google.com; spf=neutral (google.com: 74.125.82.52 is neither permitted nor denied by domain of XXXXXXXXX) smtp.mail=XXXXXXXXX
Example AFTER-SET-SPF-TXT "PASS"
設定之後,判定為「認證通過」
代碼:
Received-SPF: pass (google.com: domain of XXXXXXXXX designates 74.125.82.52 as permitted sender) client-ip=74.125.82.52;
Authentication-Results: mx.google.com; spf=pass (google.com: domain of XXXXXXXXX designates 74.125.82.52 as permitted sender) smtp.mail=XXXXXXXXXXX
3. 設定反查
相較於正查: Host Name / Domanin --> IP Address
所謂的反查就是 IP Address --> Host Name / Domain Name
有一些 Mail server 會透過檢查反查來判定 SPAM 的分數。
設定反查在某些狀況可以降低被誤判的機率。
如果公司自己有自己的 DNS server,就自己改
(記得 ns1, ns2, ns3 ... 所有 ns 都要改)
如果是請 IDC/ISP 代管,
大部分的 IDC/ISP (Hinet/Seednet) 都可以請工程師幫忙設定反查,應該也免費;
有 IDC/ISP 的和上述 TXT 一樣,提供 DNS manager 介面提供可設定。
4. 減少強制附加「智財權聲明」簽名檔
有一些公司,在 outbound 的 mail 會強制附上
類似下面這種「智財、版權」聲明稿。
英文叫做
legal statement signature
legal declaration signature
copyright statement signature ...
而這個動作,
導致「郵件本文」有時候比「聲明簽名檔」還要小...
如果某一些舊機器判定的公式有這一條,
可能會增加被誤判的機率。
建議:
換成適當大小的圖片、減少字數、或者選擇適當的顏色、適當的字體(例如避免,白底白字)。
引言回覆:
本郵件之資訊可能含有受機密或特殊管制之資訊,僅供指定之收件人使用。若您並非指定之收件人,切勿轉寄、散佈、複製或公開本通訊內容之任何部份,並請即通知寄件人並完全刪除本郵件。
The information transmitted is intended only for the person or entity to which it is addressed and may contain confidential and/or privileged material. If you are not the intended recipient, please contact the sender immediately and destroy the material in its entirety, whether electronic or hard copy. You are notified that any review, retransmission, dissemination or other use of, or taking of any action in reliance upon, this information by persons or entities other than the intended recipient is prohibited. Please consider the environment before printing this email.
5. 時常查詢是否貴公司已經在黑名單
SPAM Black List or Block List Query
http://www.spamhaus.org/
http://www.spamhaus.org/lookup.lasso (SBL, XBL PBL)
http://www.dnsstuff.com/tools
http://www.openrbl.org/
時常檢查,或者寫一個簡單的 script 照三餐檢查。
6. 避免公布貴公司的 Mail,防止 SPOOF
避免 SPAM/Spoof Address Spider
6.1 有 Contact 需求請盡量用 Contact Web-Form or Skype or 電話號碼
6.2 如果真要公布請用 E-Mail 圖片 (e-mail address 用圖片展示)
6.3 盡量減少公布可以 group mail 的 address
7. 考慮使用 DKIM or Domainkey 金鑰簽署郵件
e.g.
使用 Google Apps 提供的 DKIM 功能,
一樣是 DNS TXT FIELD
代碼:
google._domainkey v=DKIM1; k=rsa; p=ABCDEFG.....
DKIM/DomainKeys 參考網址
http://www.dkim.org/
http://support.google.com/a/bin/answer.py?hl=zh-Hant&answer=174124
http://support.google.com/a/bin/answer.py?hl=zh-Hant&answer=180504&topic=2752442&ctx=topic
實作如下圖,多了一個「金鑰簽署者欄位」
DKIM-Signature.jpg

使用 MX Super Tools 檢查 Mail Server 是否被列入黑名單
http://mxtoolbox.com/SuperTool.aspx?action=blacklist:example.com&run=toolpage
把上面的 example.com 字串,
換成你公司的 Mail Server hostname or IP address
在 Windows Server 2003 DNS 設定 SPF 記錄
SPF紀錄格式, 可能要參照網路資料
===============================
1. 到win2003 server的DNS
2. 展開正向對應區域
3. 到要新增的 SPF 記錄的 網域
4. 按右鍵 ->新增其他記錄
5. 選文字 (TXT),然後建立記錄
6. 記錄名稱 方塊保留空白
7. 在 文字 方塊中,輸入v=spf1 a mx ptr ~all
OR
v=spf1 a mx ip4:your 外部 IP ~all
=============================================
參考網址:
設定SPF: http://www.kitterman.com/spf/validate.html
SPF測試: http://www.appmaildev.com/hk/spf/
Q &A
http://forums.devshed.com/mail-server-help-111/gmail-blocks-messages-825511.html
2016年3月8日 星期二
Microsoft Exchange PHP WebDAV Examples
Author: Troy Wolf (troy@troywolf.com)
Modified Date: 2006-04-07
Does your organization use Microsoft Exchange?
Do you have a need to incorporate your Exchange data with your PHP web applications?
Do you NOT want to struggle for 2 days figuring this stuff out like I did?!
.....then these examples are for you. Learn from my pain, grasshopper.
If you are like me, you start this journey with a Google search for something like '"Exchange Server" PHP' or 'PHP "Microsoft Exchange" iterate contacts'. You quickly learn there are several different technologies--all rather cryptic-- to programmatically access your Exchange data. Let me shorten your reading time--WebDAV is the technology you want to use to allow your PHP applications to query Exchange.
Once I learned this technique, I made small tweaks to both my http and xml classes to support WebDAV queries. That's right, these examples incorporate two of my most popular classes. You can learn more about these PHP classes, but you don't need to in order to use these examples.
By far, the most difficult part of querying your Exchange Server will be how exactly to construct the WebDAV request to get the information you want. You'll no doubt end up spending some time looking at the documentation and examples at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/e2k3/e2k3/wss_references_webdav.asp.
You'll also need the reference material that documents all the Exchange object properties and what each one's urn is. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/e2k3/e2k3/_exch2k_urn_content-classes_person.asp
The code examples below will help you see how these are used.
Whenever I personally use this class to accomplish a unique task, I update this page with a generic example of the technique. Currently, these examples are available:
- Iterate the folders in a user's inbox
- Iterate the email items in a user's inbox
- Search for contacts that match a certain criteria
- Grab all properties for an item
- Create a new contact
- Create a new email message
The Code Examples
I'm not going to explain these examples too much--I'll just give a short description of what the code is querying, then show the full code example. Unfortunately, I don't have any publicly-accessible Exchange Servers so I am unable to give you any live, working examples. In all the examples below, I make the assumption that you have at least some programming experience and you'll understand to modify the parts you need to work in your environment. For example, obviously the name of your Exchange Server, the paths to your folders, your username and password will be different than what I show in these examples.Example 1 - Iterate the folders in a user's inbox
This first example will include a lot of comments and examples of how to work with the objects produced after parsing the result XML. Later examples will be less complete.<?php
// Modify the paths to these class files as needed.
require_once("class_http.php");
require_once("class_xml.php");
// Change these values for your Exchange Server.
$exchange_server = "http://NameOfYourExchangeServer";
$exchange_username = "YourExchangeUsername";
$exchange_password = "YourExchangePassword";
// We use Troy's http class object to send the XML-formatted WebDAV request
// to the Exchange Server and to receive the response from the Exchange Server.
// The response is also XML-formatted.
$h = new http();
$h->headers["Content-Type"] = 'text/xml; charset="UTF-8"';
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/e2k3/e2k3/_webdav_depth_header.asp
$h->headers["Depth"] = "0";
$h->headers["Translate"] = "f";
// The trickiest part is forming your WebDAV query. This example shows how to
// find all the folders in the inbox for a user named 'twolf'.
$h->xmlrequest = '<?xml version="1.0"?>';
$h->xmlrequest .= <<<END
<a:searchrequest xmlns:a="DAV:" xmlns:s="http://schemas.microsoft.com/exchange/security/">
<a:sql>
SELECT "DAV:displayname"
FROM SCOPE('hierarchical traversal of "$exchange_server/Exchange/twolf/inbox"')
</a:sql>
</a:searchrequest>
END;
// IMPORTANT -- The END line above must be completely left-aligned. No white-space.
// The 'fetch' method does the work of sending and receiving the request.
// NOTICE the last parameter passed--'SEARCH' in this example. That is the
// HTTP verb that you must correctly set according to the type of WebDAV request
// you are making. The examples on this page use either 'PROPFIND' or 'SEARCH'.
if (!$h->fetch($exchange_server."/Exchange/twolf/inbox", 0, null, $exchange_username, $exchange_password, "SEARCH")) {
echo "<h2>There is a problem with the http request!</h2>";
echo $h->log;
exit();
}
// Note: The following lines can be uncommented to aid in debugging.
#echo "<pre>".$h->log."</pre><hr />\n";
#echo "<pre>".$h->header."</pre><hr />\n";
#echo "<pre>".$h->body."</pre><hr />\n";
#exit();
// Or, these next lines will display the result as an XML doc in the browser.
#header('Content-type: text/xml');
#echo $h->body;
#exit();
// The assumption now is that we've got an XML result back from the Exchange
// Server, so let's parse the XML into an object we can more easily access.
// For this task, we'll use Troy's xml class object.
$x = new xml();
if (!$x->fetch($h->body)) {
echo "<h2>There was a problem parsing your XML!</h2>";
echo "<pre>".$h->log."</pre><hr />\n";
echo "<pre>".$h->header."</pre><hr />\n";
echo "<pre>".$h->body."</pre><hr />\n";
echo "<pre>".$x->log."</pre><hr />\n";
exit();
}
// You should now have an object that is an array of objects and arrays that
// makes it easy to access the parts you need. These next lines can be
// uncommented to make a raw display of the data object.
#echo "<pre>\n";
#print_r($x->data);
#echo "</pre>\n";
#exit();
// And finally, an example of iterating the inbox folder names and url's to
// display in the browser. I also show you 2 methods to link to the folders.
// One uses the href provided in the response which opens the folder using OWA.
// The other is an Outlook style link to open the folder in the Outlook desktop
// client.
echo '<table border="1">';
foreach($x->data->A_MULTISTATUS[0]->A_RESPONSE as $idx=>$item) {
echo '<tr>'
.'<td>'.$item->A_PROPSTAT[0]->A_PROP[0]->A_DISPLAYNAME[0]->_text.'</td>'
.'<td><a href="'.$item->A_HREF[0]->_text.'">Click to open via OWA</a></td>'
.'<td><a href="Outlook:Inbox/'.$item->A_PROPSTAT[0]->A_PROP[0]->A_DISPLAYNAME[0]->_text.'">Click to open via Outlook</a></td>'
."</tr>\n";
}
echo "<table>\n";
?>
Some notes regarding Outlook URL's
By "Outlook URL", I mean the special "outlook:" URLs you can create that open the Outlook Client app to view folders and items. If anyone finds definitive documentation for all the options, please let me know. I found this link helpful. It's really old, but still applicable. http://support.microsoft.com/?kbid=225007If the 'twolf' inbox has a 'Company Picnic' subfolder, the code above would create a link to "Outlook:Inbox/Company Picnic". This link is really only good for twolf unless other users happen to have an Inbox/Company Picnic folder. You can make the link user-specific, but since it is unlikely any users have access to other users' mail folders, it is probably not that useful. But here is how you make that link: "Outlook://Mailbox - Troy Wolf/Inbox/Company Picnic".
I have not completely figured out what characters should be escaped and what should not. For example, it does not matter if you leave spaces as spaces or replace with %20, but you can not replace with a '+'. Other characters seem to break the URL if you urlencode them. Other characters seem to break the URL regardless of whether they are urlencoded or not! (The OWA hrefs seem to always work.)
Notes: You can run web pages in a normal browser or directly within Outlook. There are some caveats to be aware of.
- Links and new windows - When using Outlook: style links in a browser external to Outlook, the Outlook content will always open a new Outlook window regardless of the fact you may already have Outlook open. I see the argument for either way, but would prefer a method to indicate whether to open a new window or navigate the existing Outlook window. I think by default, folders should open in the existing Outlook window and specific items should open a new window--just like they do in Outlook normally. You taking notes, Bill? :) When using links on a web page running directly within Outlook, the content opens as expected. That is, folders navigate the current window to the folder and items pop in a new Outlook window.
- Authorization required content - When accessing content that requires basic authentication, your users will have to login when accessing the content inside Outlook. Then, if you pages pop new IE windows, they'll have to login again in the IE window. My assumption is that IE--the stand-alone browser--and IE running within Outlook use seperate memory space. If somebody has more technical details or workaround options, please send them to me at troy@troywolf.com.
Example 2 - Iterate the email items in a user's inbox
<?php
// Modify the paths to these class files as needed.
require_once("class_http.php");
require_once("class_xml.php");
// Change these values for your Exchange Server.
$exchange_server = "http://NameOfYourExchangeServer";
$exchange_username = "YourExchangeUsername";
$exchange_password = "YourExchangePassword";
// We use Troy's http class object to send the XML-formatted WebDAV request
// to the Exchange Server and to receive the response from the Exchange Server.
// The response is also XML-formatted.
$h = new http();
$h->headers["Content-Type"] = 'text/xml; charset="UTF-8"';
$h->headers["Depth"] = "0";
$h->headers["Translate"] = "f";
// Find all the email items in the inbox for a user named 'twolf'.
$h->xmlrequest = '<?xml version="1.0"?>';
$h->xmlrequest .= <<<END
<a:searchrequest xmlns:a="DAV:" xmlns:s="http://schemas.microsoft.com/exchange/security/">
<a:sql>
SELECT "DAV:displayname"
,"urn:schemas:httpmail:subject"
FROM "$exchange_server/Exchange/twolf/inbox"
</a:sql>
</a:searchrequest>
END;
// IMPORTANT -- The END line above must be completely left-aligned. No white-space.
// The 'fetch' method does the work of sending and receiving the request.
// NOTICE the last parameter passed--'SEARCH' in this example. That is the
// HTTP verb that you must correctly set according to the type of WebDAV request
// you are making. The examples on this page use either 'PROPFIND' or 'SEARCH'.
if (!$h->fetch($exchange_server."/Exchange/twolf/inbox", 0, null, $exchange_username, $exchange_password, "SEARCH")) {
echo "<h2>There is a problem with the http request!</h2>";
echo $h->log;
exit();
}
// The assumption now is that we've got an XML result back from the Exchange
// Server, so let's parse the XML into an object we can more easily access.
// For this task, we'll use Troy's xml class object.
$x = new xml();
if (!$x->fetch($h->body)) {
echo "<h2>There was a problem parsing your XML!</h2>";
echo "<pre>".$h->log."</pre><hr />\n";
echo "<pre>".$h->header."</pre><hr />\n";
echo "<pre>".$h->body."</pre><hr />\n";
echo "<pre>".$x->log."</pre><hr />\n";
exit();
}
// And finally, an example of iterating the email items to display in the
// browser. I also show you 2 methods to link to the items. One uses the href
// provided in the response which opens the folder using OWA. The other is an
// Outlook style link to open the folder in the Outlook desktop client.
echo '<table border="1">';
foreach($x->data->A_MULTISTATUS[0]->A_RESPONSE as $idx=>$item) {
echo '<tr>'
.'<td>'.$item->A_PROPSTAT[0]->A_PROP[0]->D_SUBJECT[0]->_text.'</td>'
.'<td><a href="'.$item->A_HREF[0]->_text.'">Click to open via OWA</a></td>'
.'<td><a href="Outlook:Inbox/~'.$item->A_PROPSTAT[0]->A_PROP[0]->D_SUBJECT[0]->_text.'">Click to open via Outlook</a></td>'
."</tr>\n";
}
echo "<table>\n";
?>
Example 3 - Search for contacts that match a certain criteria
This example can easily be modified to simply iterate all contacts in a folder by simply deleting the WHERE clause in the WebDAV request.<?php
// Modify the paths to these class files as needed.
require_once("class_http.php");
require_once("class_xml.php");
// Change these values for your Exchange Server.
$exchange_server = "http://NameOfYourExchangeServer";
$exchange_username = "YourExchangeUsername";
$exchange_password = "YourExchangePassword";
// We use Troy's http class object to send the XML-formatted WebDAV request
// to the Exchange Server and to receive the response from the Exchange Server.
// The response is also XML-formatted.
$h = new http();
$h->headers["Content-Type"] = 'text/xml; charset="UTF-8"';
$h->headers["Depth"] = "0";
$h->headers["Translate"] = "f";
// Find all the contacts for a specific company in a specific folder.
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/e2k3/e2k3/_exch2k_urn_content-classes_person.asp
$h->xmlrequest = '<?xml version="1.0"?>';
$h->xmlrequest .= <<<END
<a:searchrequest xmlns:a="DAV:">
<a:sql>
SELECT "a:href"
,"urn:schemas:contacts:o"
,"urn:schemas:contacts:cn"
,"urn:schemas:contacts:fileas"
,"urn:schemas:contacts:title"
,"urn:schemas:contacts:email1"
,"urn:schemas:contacts:telephoneNumber"
FROM "$exchange_server/public/Customer%20Contacts/"
WHERE "urn:schemas:contacts:o" = 'XYZ Industries, Inc.'
ORDER BY "urn:schemas:contacts:cn"
</a:sql>
</a:searchrequest>
END;
// IMPORTANT -- The END line above must be completely left-aligned. No white-space.
// The 'fetch' method does the work of sending and receiving the request.
// NOTICE the last parameter passed--'SEARCH' in this example. That is the
// HTTP verb that you must correctly set according to the type of WebDAV request
// you are making. The examples on this page use either 'PROPFIND' or 'SEARCH'.
if (!$h->fetch($exchange_server."/public/Customer%20Contacts", 0, null, $exchange_username, $exchange_password, "SEARCH")) {
echo "<h2>There is a problem with the http request!</h2>";
echo $h->log;
exit();
}
// The assumption now is that we've got an XML result back from the Exchange
// Server, so let's parse the XML into an object we can more easily access.
// For this task, we'll use Troy's xml class object.
$x = new xml();
if (!$x->fetch($h->body)) {
echo "<h2>There was a problem parsing your XML!</h2>";
echo "<pre>".$h->log."</pre><hr />\n";
echo "<pre>".$h->header."</pre><hr />\n";
echo "<pre>".$h->body."</pre><hr />\n";
echo "<pre>".$x->log."</pre><hr />\n";
exit();
}
// And finally, an example of iterating the contact items to display in the browser.
echo '<table border="1">';
echo "<tr><th>Company</th><th>Name</th><th>Title</th><th>Email</th><th>Phone</th></tr>\n";
foreach($x->data->A_MULTISTATUS[0]->A_RESPONSE as $idx=>$contact) {
echo '<tr>'
.'<td>'.$contact->A_PROPSTAT[0]->A_PROP[0]->E_O[0]->_text.'</td>'
.'<td><a href="outlook://Public%20Folders/All%20Public%20Folders/Account_Contacts/~'.str_replace(" ","%20",$contact->A_PROPSTAT[0]->A_PROP[0]->E_CN[0]->_text).'">'
.$contact->A_PROPSTAT[0]->A_PROP[0]->E_CN[0]->_text.'</a></td>'
.'<td>'.$contact->A_PROPSTAT[0]->A_PROP[0]->E_TITLE[0]->_text.'</td>'
.'<td>'.$contact->A_PROPSTAT[0]->A_PROP[0]->E_EMAIL1[0]->_text.'</td>'
.'<td>'.$contact->A_PROPSTAT[0]->A_PROP[0]->E_TELEPHONENUMBER[0]->_text.'</td>'
."</tr>\n";
}
echo "<table>\n";
?>
Example 4 - Grab all properties for an item
This example demonstrates returning all properties for a specific message item. You can use the allprop property to return all properties. This is very useful when you don't know what the property names are.<?php
// Modify the paths to these class files as needed.
require_once("class_http.php");
require_once("class_xml.php");
// Change these values for your Exchange Server.
$exchange_server = "http://NameOfYourExchangeServer";
$exchange_username = "YourExchangeUsername";
$exchange_password = "YourExchangePassword";
// We use Troy's http class object to send the XML-formatted WebDAV request
// to the Exchange Server and to receive the response from the Exchange Server.
// The response is also XML-formatted.
$h = new http();
$h->headers["Content-Type"] = 'text/xml; charset="UTF-8"';
$h->headers["Depth"] = "0";
$h->headers["Translate"] = "f";
// Find all the properties for a specific item.
$h->xmlrequest = '<?xml version="1.0"?>';
$h->xmlrequest .= <<<END
<a:propfind xmlns:a="DAV:">
<a:allprop/>
</a:propfind>
END;
// IMPORTANT -- The END line above must be completely left-aligned. No white-space.
// The 'fetch' method does the work of sending and receiving the request.
// NOTICE the last parameter passed--'PROPFIND' in this example. That is the
// HTTP verb that you must correctly set according to the type of WebDAV request
// you are making. The examples on this page use either 'PROPFIND' or 'SEARCH'.
if (!$h->fetch($exchange_server."/public/Email%20Log/Some%20Message-668992879.EML", 0, null, $exchange_username, $exchange_password, "PROPFIND")) {
echo "<h2>There is a problem with the http request!</h2>";
echo $h->log;
exit();
}
// The assumption now is that we've got an XML result back from the Exchange
// Server, so let's parse the XML into an object we can more easily access.
// For this task, we'll use Troy's xml class object.
$x = new xml();
if (!$x->fetch($h->body)) {
echo "<h2>There was a problem parsing your XML!</h2>";
echo "<pre>".$h->log."</pre><hr />\n";
echo "<pre>".$h->header."</pre><hr />\n";
echo "<pre>".$h->body."</pre><hr />\n";
echo "<pre>".$x->log."</pre><hr />\n";
exit();
}
echo "<pre>";
print_r($x->data);
echo "</pre>";
?>
Example 5 - Create a new contact
This example demonstrates how to programmatically create a new contact in a public contacts folder. We'll use the PROPPATCH WebDAV method. This method will create a new contact if the URL does not exist or update an existing contact. Notice the last 2 properties. Those are custom fields that must be pre-defined for the folder. I show an example where a custom field is a boolean YES/NO. I struggled with how to set this property for a few hours. You're welcome. There are many, many more contact fields available. Use the allprop example #4 above to list an existing contact to see all the fields and schemas available.<?php
// Modify the path to this class file as needed.
require_once("class_http.php");
// Change these values for your Exchange Server.
$exchange_server = "http://NameOfYourExchangeServer";
$exchange_username = "YourExchangeUsername";
$exchange_password = "YourExchangePassword";
// We use Troy's http class object to send the XML-formatted WebDAV request
// to the Exchange Server and to receive the response from the Exchange Server.
// The response is also XML-formatted.
$h = new http();
$h->headers["Content-Type"] = 'text/xml; charset="UTF-8"';
$h->headers["Depth"] = "0";
$h->headers["Translate"] = "f";
// Build the XML request.
// This section must be against the left margin.
$h->xmlrequest = '<?xml version="1.0"?>';
$h->xmlrequest .= <<<END
<g:propertyupdate xmlns:g="DAV:"
xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/"
xmlns:c="urn:schemas:contacts:"
xmlns:e="http://schemas.microsoft.com/exchange/"
xmlns:mapi="http://schemas.microsoft.com/mapi/"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:cust="urn:schemas:customproperty"
xmlns:ed="urn:schemas-microsoft-com:exch-data:"
xmlns:repl="http://schemas.microsoft.com/repl/"
xmlns:x="xml:"
xmlns:cal="urn:schemas:calendar:"
xmlns:mail="urn:schemas:httpmail:"
xmlns:ec="urn:schemas-microsoft-com:exch-data:expected-content-class"
xmlns:j="urn:content-classes:propertydef"
xmlns:mailheader="urn:schemas:mailheader:">
<g:set>
<g:prop>
<g:contentclass>urn:content-classes:person</g:contentclass>
<e:outlookmessageclass>IPM.Contact</e:outlookmessageclass>
<e:keywords-utf8>
<x:v>Buddies</x:v><x:v>Engineers</x:v>
</e:keywords-utf8>
<c:language>US English</c:language>
<c:o>Innotech, Inc.</c:o>
<c:givenName>John</c:givenName>
<c:sn>Doe</c:sn>
<c:cn>John Doe</c:cn>
<c:fileas>Doe, John</c:fileas>
<c:street>100 N. Main</c:street>
<c:postofficebox>PO Box 555</c:postofficebox>
<c:l>Kansas City</c:l>
<c:st>MO</c:st>
<c:postalcode>64118</c:postalcode>
<c:co>USA</c:co>
<c:telephoneNumber>425-555-1110</c:telephoneNumber>
<c:facsimiletelephonenumber>425-555-1112</c:facsimiletelephonenumber>
<c:homePhone>425-555-1113</c:homePhone>
<c:mobile>425-555-1117</c:mobile>
<mapi:email1addrtype>SMTP</mapi:email1addrtype>
<mapi:email1emailaddress>john.doe@hotmail.com</mapi:email1emailaddress>
<mapi:email1originaldisplayname>John Doe</mapi:email1originaldisplayname>
<favoritecolor>Blue</favoritecolor>
<newsletter b:dt="boolean">1</newsletter>
</g:prop>
</g:set>
</g:propertyupdate>
END;
// IMPORTANT -- The END line above must be completely left-aligned. No white-space.
// The http object's 'fetch' method does the work of sending and receiving the
// request. We use the WebDAV PROPPATCH method to create or update Exchange items.
$url = $exchange_server."/public/Company%20Contacts/john%20doe.EML";
if (!$h->fetch($url, 0, null, $exchange_username, $exchange_password, "PROPPATCH")) {
echo "<h2>There is a problem with the http request!</h2>";
echo $h->log;
exit();
}
// You can print out the response to help troubleshoot.
echo "<pre>".$h->header."</pre><hr />\n";
echo "<pre>".$h->body."</pre><hr />\n";
?>
Example 6 - Create a new email message
This example demonstrates how to programmatically create a new email message. In this example, we'll create the example in the user's Drafts folder. The exchange username and password will need privileges to create items in the user's personal folders.<?php
// Modify the path to this class file as needed.
require_once("class_http.php");
// Change these values for your Exchange Server.
$exchange_server = "http://NameOfYourExchangeServer";
$exchange_username = "YourExchangeUsername";
$exchange_password = "YourExchangePassword";
// We use Troy's http class object to send the XML-formatted WebDAV request
// to the Exchange Server and to receive the response from the Exchange Server.
// The response is also XML-formatted.
$h = new http();
$h->headers["Content-Type"] = 'text/xml; charset="UTF-8"';
$h->headers["Depth"] = "0";
$h->headers["Translate"] = "f";
$subject = "Ci@lis CHEAP!";
// Build the XML request.
// This section must be against the left margin.
$h->xmlrequest = '<?xml version="1.0"?>';
$h->xmlrequest .= <<<END
<a:propertyupdate xmlns:a="DAV:"
xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/"
xmlns:g="http://schemas.microsoft.com/mapi/"
xmlns:e="urn:schemas:httpmail:"
xmlns:d="urn:schemas:mailheader:"
xmlns:c="xml:"
xmlns:f="http://schemas.microsoft.com/mapi/proptag/"
xmlns:h="http://schemas.microsoft.com/exchange/"
xmlns:i="urn:schemas-microsoft-com:office:office"
xmlns:k="http://schemas.microsoft.com/repl/"
xmlns:j="urn:schemas:calendar:"
xmlns:l="urn:schemas-microsoft-com:exch-data:">
<a:set>
<a:prop>
<a:contentclass>urn:content-classes:message</a:contentclass>
<h:outlookmessageclass>IPM.Note</h:outlookmessageclass>
<d:to>foo@foobar.com</d:to>
<d:cc>bar@foobar.com</d:cc>
<d:bcc>bob@aol.com</d:bcc>
<g:subject>$subject</g:subject>
<e:htmldescription>This is spam. Please delete this email.</e:htmldescription>
</a:prop>
</a:set>
</a:propertyupdate>
END;
// IMPORTANT -- The END line above must be completely left-aligned. No white-space.
// The http object's 'fetch' method does the work of sending and receiving the
// request. We use the WebDAV PROPPATCH method to create or update Exchange items.
$url = $exchange_server."/Exchange/twolf/Drafts/".urlencode($subject).".EML";
if (!$h->fetch($url, 0, null, $exchange_username, $exchange_password, "PROPPATCH")) {
echo "<h2>There is a problem with the http request!</h2>";
echo $h->log;
exit();
}
// You can print out the response to help troubleshoot.
echo "<pre>".$h->header."</pre><hr />\n";
echo "<pre>".$h->body."</pre><hr />\n";
// Bonus tip! You can automatically open this new draft message for your user by
// formulating an outlook URL. Then either redirect to the URL by uncommenting the
// header line below, or pop the URL in client-side javascript using window.open.
#header("Location: outlook:drafts/~".urlencode($subject));
?>
About the author
Troy Wolf is the author of SnippetEdit--a PHP application providing browser-based website editing that even non-technical people can use. Website editing as easy as it gets. Troy has been a professional Internet and database application developer for over 12 years. He has many years' experience with ASP, VBScript, PHP, Javascript, DHTML, CSS, SQL, and XML on Windows and Linux platforms. Check out Troy's Code Library.利用 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 來測試結果因此沒有裝的人可以參考我網站的 簡介與使用> 和簡介與使用>
進行安裝 在此不贅述了~~~~
以上教學歡迎轉載但是請註明源頭來自