[Tips] 以圖片作為郵件讀取紀錄的發送管道

透過電子郵件中的圖片作為電子郵件讀取紀錄的發送管道。

前言


當企業在發送重要通知給內部員工時,後台會需要了解通知成效為何,因此希望在員工讀取郵件當下回傳訊息給伺服端,作為通知達成率的統計依據;筆者最近就是接收到這項任務,BUT 電子郵件當然不會允許我們直接插入一段 JavaScript 來送出訊息,因此我們可以透過一張圖片間接地完成這項任務。以下介紹。

 

 

切入既有系統


在企業中對於發送郵件/簡訊之類的服務通常都會有一張資料表記錄這些資訊,然後透過排程或服務定期掃那張資料表,將未發送的資料依據發送型態執行發送任務,最後將執行結果回寫回資料表中。

通知編號 發送目標 發送內容 發送時間 發送狀態 讀取時間
1020114 emp01@gmail.com <p>通知晉升</p> 2018/01/10 11:11:11 成功  
1020115 emp02@gmail.com <p>請假代理</p>      

 

我們只要針對實際執行發送郵件的那隻程式動手就好,不需要動到所有寫入資料表的程式邏輯;因為既然可以發送資料,必定可以獲得「通知編號」及「發送內容」這兩個最重要的東西,而取得這兩項資訊的目的如下。

  • 通知編號:作為讀取項目的識別碼 Key
  • 發送內容:補上一張看不見的 img 標籤,在下載 img 過程中將「通知編號」向後傳遞

 

 

圖片來源


在郵件中出現一張圖是在合理不過的事情了,我們可以透過讀取郵件圖片的當下來傳遞「發送編號」給伺服端,好讓系統在取得這個編號後去註記該則郵件已被讀取。

以下 img 為例,在讀取這張照片的時候會向 http://xx.xx.xx.xx/log/readMail/ 發出一個包含參數動作為 Get 的 HTTP Request,而在 Web API 端就可以獲得 1020114 這個參數值來註記該則郵件已被讀取。

<img src="http://xx.xx.xx.xx/log/readMail/1020114" >

 

最後只要在發送郵件的那支程式做調整,在郵件發送前於內容加入 img 標籤,讓每一封郵件 img 標籤擁有自己的通知編號;當收到郵件的用戶開啟後讀取圖片時,就可以將該郵件專屬的編號送出讓後端識別。

 

 

建立 Web API


萬事俱備只欠東風,因此依據先前的需求開發一隻 Web API 就搞定了。

[Route("readMail/{pushNoticeSerilNo}")]
[HttpGet]
public HttpResponseMessage GetReadMail(int pushNoticeSerilNo)
{
    // 依據 pushNoticeSerilNo 註記該則 Mail 通知已被讀取
    service.PushService.UpdatePushMailRead(pushNoticeSerilNo);

    // 回傳圖片
    var imagePath = HttpContext.Current.Server.MapPath($@"~/image/transparent.png");
    FileStream file = new FileStream(imagePath, FileMode.Open, FileAccess.Read);
    HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
    response.Content = new StreamContent(file);
    response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/png");
    return response;
}
回傳的圖片可選用原本企業郵件內含的圖示 (ex. logo),若無圖片顯示需求可考慮直接附上一張 1x1 pixel 透明圖,或者乾脆用 CSS 隱藏處理掉也行 (需要注意郵件所支援的 CSS 語法限制,尤其是 Outlook 最 ... )。

 

 

Outlook 限制


筆者測試過這個機制在 Web Mail - Gmail 或手持式裝置都是可以正常運作 (相信其他 Web Mail 也是相同),但面對 Outlook 預設不自動下載圖片的安全性設定下,那就真的沒辦法了。

通常企業內 Outlook 都會信任來源是自家安全網域內的圖片,因此開啟郵件後都可自動下載。

 

 


希望此篇文章可以幫助到需要的人

若內容有誤或有其他建議請不吝留言給筆者喔 !