首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 存取 Hotmail 完整實作(二):列舉資料夾、解析郵件屬性、接收與發送郵件

     編輯:關於C語言

前言

Hotmail 使用 HTTPMail 協議(基於 WebDAV),非標準 POP3/IMAP。本文為系列第二部分,涵蓋:列舉資料夾內容、XML 解析郵件屬性、接收郵件內容、發送郵件完整流程。

一、列舉資料夾內容:PROPFIND 查詢

查詢 XML(請求郵件基本屬性)

<?xml version="1.0"?>
<D:propfind xmlns:D="DAV:" xmlns:hm="urn:schemas:httpmail:" xmlns:m="urn:schemas:mailheader:">
  <D:prop>
    <D:isfolder/>           <!-- 是否資料夾 -->
    <hm:read/>              <!-- 已讀狀態 -->
    <m:hasattachment/>      <!-- 是否有附件 -->
    <m:to/>                 <!-- 收件人 -->
    <m:from/>               <!-- 寄件人 -->
    <m:subject/>            <!-- 主旨 -->
    <m:date/>               <!-- 日期 -->
    <D:getcontentlength/>  <!-- 大小 -->
  </D:prop>
</D:propfind>

C# 發送請求

using MSXML2; // 需參考 Microsoft XML, v6.0 (MSXML2)

XMLHTTP xmlHttp = new XMLHTTP();
string folderUrl = "https://xxx.oe.hotmail.com/.../Inbox/"; // 從第一步取得

string query = "..."; // 上方 XML 字串

xmlHttp.open("PROPFIND", folderUrl, false, null, null); // 同步,已驗證會話
xmlHttp.send(query);
string responseXml = xmlHttp.responseText;

二、解析回應 XML:XmlTextReader 串流讀取

回應 XML 結構

<D:multistatus>
  <D:response>
    <D:href>https://xxx/Inbox/msg123.eml</D:href>
    <D:propstat>
      <D:prop>
        <hm:read>1</hm:read>
        <m:from>John Doe</m:from>
        <m:subject>Hello</m:subject>
        <m:date>2024-01-15T10:30:00</m:date>
        <D:getcontentlength>2048</D:getcontentlength>
      </D:prop>
    </D:propstat>
  </D:response>
  ...
</D:multistatus>

MailItem 實體類別

public class MailItem
{
    public string Url { get; set; }
    public bool IsRead { get; set; }
    public string From { get; set; }
    public string To { get; set; }
    public string Subject { get; set; }
    public DateTime Date { get; set; }
    public long Size { get; set; }
    public bool HasAttachment { get; set; }
}

XmlTextReader 解析邏輯

var mailItems = new List();
MailItem current = null;

using (var reader = new StringReader(responseXml))
using (var xml = new XmlTextReader(reader))
{
    while (xml.Read())
    {
        string name = xml.Name;
        XmlNodeType nodeType = xml.NodeType;
        
        // 遇到  開始新郵件
        if (name == "D:response" && nodeType == XmlNodeType.Element)
            current = new MailItem();
        
        // 遇到  完成一筆
        if (name == "D:response" && nodeType == XmlNodeType.EndElement)
        {
            if (current != null)
            {
                mailItems.Add(current);
                current = null;
            }
        }
        
        // 元素內容處理
        if (nodeType == XmlNodeType.Element && current != null)
        {
            if (xml.Read()) // 移到內容
            {
                switch (name)
                {
                    case "D:href": current.Url = xml.Value; break;
                    case "hm:read": current.IsRead = xml.Value == "1"; break;
                    case "m:from": current.From = xml.Value; break;
                    case "m:to": current.To = xml.Value; break;
                    case "m:subject": current.Subject = xml.Value; break;
                    case "m:date": DateTime.TryParse(xml.Value, out current.Date); break;
                    case "D:getcontentlength": long.TryParse(xml.Value, out current.Size); break;
                    case "m:hasattachment": current.HasAttachment = xml.Value == "1"; break;
                }
            }
        }
    }
}

三、接收郵件內容:HTTP GET

public string LoadMail(MailItem mail)
{
    xmlHttp.open("GET", mail.Url, false, null, null);
    xmlHttp.send(null);
    return xmlHttp.responseText; // 完整郵件原始內容 (MIME 格式)
}

四、發送郵件:HTTP POST + RFC821 格式

準備郵件內容

public void SendMail(string from, string fromName, string to, string subject, string body)
{
    string quote = "\""; // \u0022
    string timeStamp = DateTime.Now.ToString("ddd, dd MMM yyyy HH:mm:ss");
    
    string postBody = "";
    postBody += $"MAIL FROM:<{from}>\r\n";
    postBody += $"RCPT TO:<{to}>\r\n";
    postBody += "\r\n";
    postBody += $"From: {quote}{fromName}{quote} <{from}>\r\n";
    postBody += $"To: <{to}>\r\n";
    postBody += $"Subject: {subject}\r\n";
    postBody += $"Date: {timeStamp} -0000\r\n";
    postBody += "\r\n";
    postBody += body; // 純文字內容
    
    // 發送
    xmlHttp.open("POST", _sendUrl, false, null, null); // _sendUrl 從第一步取得
    xmlHttp.setRequestHeader("Content-Type", "message/rfc821");
    xmlHttp.send(postBody);
    
    // 檢查結果
    if (xmlHttp.status != 200)
        throw new Exception($"發送失敗: {xmlHttp.status} {xmlHttp.statusText}");
}

五、關鍵技術點總結

XML 命名空間對照

  • D: = DAV: (WebDAV 核心)
  • hm: = urn:schemas:httpmail: (Hotmail 擴展)
  • m: = urn:schemas:mailheader: (郵件標頭)

六、現代替代方案建議

Hotmail/Outlook.com 現已支援標準協議:

  • IMAP/SMTP:標準郵件存取,支援 OAuth2
  • Microsoft Graph API:官方 REST API,功能完整、文件完善
  • EWS (Exchange Web Services):企業環境適用

建議:新專案優先使用 Graph API 或 IMAP/SMTP,僅維護舊系統時參考本文 HTTPMail 實作。

總結

HTTPMail 協議雖非公開標準,但透過 WebDAV PROPFIND/GET/POST 即可實現完整收發功能。核心流程:

  1. 取得資料夾 URL(第一步驟)
  2. PROPFIND 列舉郵件清單 → 解析 XML 產生 MailItem
  3. GET 取得郵件完整內容
  4. POST 發送新郵件(RFC821 格式)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
操作HTTP 方法關鍵 Header資料格式
列舉資料夾PROPFINDContent-Type: text/xmlWebDAV propfind XML
接收郵件GET-MIME (RFC822)
發送郵件POSTContent-Type: message/rfc821RFC821 郵件格式