上一篇說明完「使用 Gmail API 寄信簡易管道」流程,接著要實作利用 Gmail API 在郵件中插入圖片。
其實處理純文字郵件就已經挺複雜麻煩了,然而跟本篇相比,還算是小巫見大巫。啃了大量的郵件通訊格式資訊後,結果發現就算是使用完全正確的格式,Gmail API 也不見得就能相容,測試過程相當痛苦。不過最終總算找出一個可行的作法,請見本篇心得整理。
(圖片出處: stocksnap.io)
要在郵件中插入圖片(非附件),可使用 IMG 標籤,也代表要使用 HTML 語法,那麼需要先理解郵件的格式規範如何加入 HTML 內容。
1. MIME 郵件架構
要在郵件中使用純文字以外的內容,必須使用 MIME 架構,首先請先看這篇「MIME中的Multipart/mixed」瞭解原理,根據不同的架構類型,可分成三種:
這三種架構使用巢狀方式嵌套,必須符合嚴謹的嵌套邏輯,一層層包覆,這篇「Multi-Part MIME Messages」提供了圖解,借用下面這張圖可以一眼就非常清楚地理解:
這篇也提供了詳細的範例程式碼,搭配圖片可以快速理解如何製作 MIME 郵件內容。
2. Multipart/Alternative 架構
要在郵件中插入 HTML,至少需使用 Multipart/Alternative 架構,以下提供一個完整的郵件內容範例,同時包含純文字與 HTML 的部分:
3. Multipart/Related 架構
要在郵件中插入行內(inline)圖片,至少需使用 Multipart/Related 架構,以下提供一個完整的郵件內容範例:
前面的郵件範例都是合法的格式,但餵給 Gmail API 後會有很多問題需要注意:
1. 雙引號問題
前面「Multipart/Alternative」的範例請注意這一行:
boundary 的參數使用雙引號 "" 是標準作法,如果不小心使用了單引號 '',會導致整封 MIME 郵件無法被 Gmail 解析,全部變成純文字,這是很大的坑需注意。
為了避免麻煩,MIME 格式的郵件,需要使用參數時可全部省略雙引號,例如參考「Multipart/Related」的範例,全部移除了雙引號,郵件仍可被解析。
2. 換行次數的問題
這也是超級大的坑,換行符號使用的次數若不對,Gmail 就無法正確解讀郵件內容。
同樣是這一行,後面必須使用 2 次換行符號,如果只使用 1 次會導致郵件寄不出去。
在郵件開始文字內容的前一行,也就是上面這行內容,後面必須使用 2 次換行符號,如果只使用 1 次會看不到郵件內容。
3. Multipart/Alternative 問題
雖然 MIME 郵件允許純文字、HTML 格式並存,但似乎 Gmail 無法同時接收這兩種格式,來看實例,試著將前面「Multipart/Alternative」的範例內容寄出:
收到郵件後,只有第二個部分 HTML 內容可顯示。
然而檢視郵件原始內容後,會發現純文字內容是有被 Gmail 接收到的,但就是無法顯示。
經交叉測試可發現,若將兩個部分位置交換,則郵件會顯示純文字內容,而 HTML 內容無法顯示。
這也代表說,「Multipart/Alternative」郵件有多個部分時,只會顯示最後一個部分的內容。
瞭解以上所有相關知識及資訊後,以下來看 Google Apps Script 的範例程式碼:
下面是收到範例程式碼寄出的郵件畫面:
可成功顯示插入的文件及 HTML 語法!
其實處理純文字郵件就已經挺複雜麻煩了,然而跟本篇相比,還算是小巫見大巫。啃了大量的郵件通訊格式資訊後,結果發現就算是使用完全正確的格式,Gmail API 也不見得就能相容,測試過程相當痛苦。不過最終總算找出一個可行的作法,請見本篇心得整理。
(圖片出處: stocksnap.io)
一、MIME 郵件規範
要在郵件中插入圖片(非附件),可使用 IMG 標籤,也代表要使用 HTML 語法,那麼需要先理解郵件的格式規範如何加入 HTML 內容。
1. MIME 郵件架構
要在郵件中使用純文字以外的內容,必須使用 MIME 架構,首先請先看這篇「MIME中的Multipart/mixed」瞭解原理,根據不同的架構類型,可分成三種:
- multipart/alternative:可使用純文字、HTML 語法
- multipart/related:前一種再加上內嵌物件(例如圖片)
- multipart/mixed:前一種再加上附件
這三種架構使用巢狀方式嵌套,必須符合嚴謹的嵌套邏輯,一層層包覆,這篇「Multi-Part MIME Messages」提供了圖解,借用下面這張圖可以一眼就非常清楚地理解:
這篇也提供了詳細的範例程式碼,搭配圖片可以快速理解如何製作 MIME 郵件內容。
2. Multipart/Alternative 架構
要在郵件中插入 HTML,至少需使用 Multipart/Alternative 架構,以下提供一個完整的郵件內容範例,同時包含純文字與 HTML 的部分:
To: waynefu.g@gmail.com
Subject: 測試郵件主旨
Mime-Version: 1.0
Content-Type: multipart/alternative; boundary="wfublog"
--wfublog
Content-Type: text/plain; charset="utf-8"
這裡是純文字內容!!!
--wfublog
Content-Type: text/html; charset="utf-8"
welcome to WFU BLOG
這裡是 HTML 內容文字可以上色
--wfublog--
3. Multipart/Related 架構
要在郵件中插入行內(inline)圖片,至少需使用 Multipart/Related 架構,以下提供一個完整的郵件內容範例:
To: waynefu.g@gmail.com
Subject: 測試郵件主旨
Mime-Version: 1.0
Content-Type: multipart/related; boundary=wfublog1
--wfublog1
Content-Type: multipart/alternative; boundary=wfublog2
--wfublog2
Content-Type: text/html; charset=utf-8
<p>這封完全是 HTML 郵件</p>
<img src='cid:wfublog_img'/>
<p>在兩行文字間插入圖片</p>
--wfublog2--
--wfublog1
Content-Type: image/jpeg; name=flag.jpg
Content-Disposition: inline; filename=flag.jpg
Content-Transfer-Encoding: base64
Content-ID: <wfublog_img>
/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAsICAoIBwsKCQoNDAsNERwSEQ8PESIZGhQcKSQrKigkJyctMkA3LTA9MCcnOEw5PUNFSElIKzZPVU5GVEBHSEX/2wBDAQwNDREPESESEiFFLicuRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUX/wAARCAAVACADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDm7qJL74g31rd3bwW73sgZt5GBuNR+M7C00bVFg0u/kniK5J8wnBqz4h0+2fxFqTtGSzXMhJ3H+8azTp1sxyUJPqWNdyzjDxkm+bRWtZf5nsx4fxU4qScdfN/5FxJ5fLX94/QfxGp7aaU3MX7x/vj+I+tVgMAAdBUtt/x9Rf74/nXy7d5XPtuRKFrdD0e++HSX1/cXR1JkM0jSbfJBxk5x1qv/AMKwj/6Cjf8Afgf/ABVFFer9XpvWx8BHN8bFKKnovJf5B/wrCP8A6Cjf9+B/8VTo/hnHHIr/ANpsdpBx5A/+KoopfV6XYf8AbGNentPwX+R//9k=
--wfublog1--
二、Gmail API 會遇到的問題
前面的郵件範例都是合法的格式,但餵給 Gmail API 後會有很多問題需要注意:
1. 雙引號問題
前面「Multipart/Alternative」的範例請注意這一行:
Content-Type: multipart/alternative; boundary="wfublog"
boundary 的參數使用雙引號 "" 是標準作法,如果不小心使用了單引號 '',會導致整封 MIME 郵件無法被 Gmail 解析,全部變成純文字,這是很大的坑需注意。
為了避免麻煩,MIME 格式的郵件,需要使用參數時可全部省略雙引號,例如參考「Multipart/Related」的範例,全部移除了雙引號,郵件仍可被解析。
2. 換行次數的問題
這也是超級大的坑,換行符號使用的次數若不對,Gmail 就無法正確解讀郵件內容。
Content-Type: multipart/alternative; boundary="wfublog"
同樣是這一行,後面必須使用 2 次換行符號,如果只使用 1 次會導致郵件寄不出去。
Content-Type: text/plain; charset="utf-8"
在郵件開始文字內容的前一行,也就是上面這行內容,後面必須使用 2 次換行符號,如果只使用 1 次會看不到郵件內容。
3. Multipart/Alternative 問題
雖然 MIME 郵件允許純文字、HTML 格式並存,但似乎 Gmail 無法同時接收這兩種格式,來看實例,試著將前面「Multipart/Alternative」的範例內容寄出:
收到郵件後,只有第二個部分 HTML 內容可顯示。
然而檢視郵件原始內容後,會發現純文字內容是有被 Gmail 接收到的,但就是無法顯示。
經交叉測試可發現,若將兩個部分位置交換,則郵件會顯示純文字內容,而 HTML 內容無法顯示。
這也代表說,「Multipart/Alternative」郵件有多個部分時,只會顯示最後一個部分的內容。
三、GAS 範例程式碼
瞭解以上所有相關知識及資訊後,以下來看 Google Apps Script 的範例程式碼:
- 以上範例碼,比較基本的原理請直接參照「使用 Gmail API 寄信簡易管道」,本篇省略說明。
- 本篇比較重要、需要注意的地方,直接用註解提醒
- 例如所有需要使用兩次換行的地方
- 為了避免麻煩,MIME 郵件所有等於 "=" 後面的參數都可省略雙引號
下面是收到範例程式碼寄出的郵件畫面:
可成功顯示插入的文件及 HTML 語法!
更多 Gmail 相關文章: