郵件模板開發


項目需求:開發一個郵件模板,用於向海外客戶郵箱推送各種消息,需要根據消息類型,展示不同的內容。比如:異常告警的時候呈現的是一種形式,注冊及忘記密碼又是另一種形式。除此之外,同一個模板還需要兼容移動端和PC端。UI大致如下:

因此,需要考慮眾多因素來實現這個需求。首先是郵件模板,經查閱資料及實踐,發現網頁郵箱借助於瀏覽器強大的渲染能力還是很好兼容的,但是郵箱客戶端由於安全性及渲染能力的制約,並不能很好的渲染html文件,編寫兼容性良好的html郵件模板,需要使用15年前的網頁制作方法。主要經驗總結如下:

1.Doctype

兼容性最好的Doctype是XHTML 1.0,所以我們常用的HTML5文件頭不能使用,需要換上以下這種文件頭Doctype,使用這種Doctype就意味着不能使用HTML5的語言。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <title>HTML Email編寫指南</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
 </head>
</html>

2.布局

由於不能使用HTML5的語法,並且郵箱客戶端對CSS的支持情況不盡相同,所以布局要使用古老的table布局,且必須使用table布局,就不要使用div p等標簽了。首先在最外層放置一個大表格,用來設置背景。

<body style="margin: 0; padding: 0;">
 <table border="1" cellpadding="0" cellspacing="0" width="100%">
  <tr>
   <td> Hello! </td>
  </tr>
 </table>
</body>

3.圖片

圖片是唯一可以引用的外部資源,鑒於安全性考慮,外部資源比如樣式表文件、字體文件、視頻文件等一律不能引用。

<img border="0" style="display:block;outline:none;text-decoration:none,-ms-interpolation-mode:bicubic;border:none;">

因為在有些郵箱里,圖片不是默認加載的,往往加載前需要用戶的許可。那么高寬的指定可以使郵件在沒有圖片撐出樣子前也能保持良好的大小結構,加上 alt 屬性更可以明確告知圖片的內容讓用戶選擇是否下載它們。

如果因為項目需要(比如需要適配 Retina 高分屏),width 和 height 屬性更是必不可少的,並且由於一些 outlook 版本的奇葩表現,width 和 height 屬性一定不要加上單位!一定不要加上單位!一定不要加上單位!重要的事情說三遍。

因為加上單位會使一些版本的 OutLook 無法正確識別,導致圖片顯示使用實際的寬高而非我們設置的。

<img width="10px" height="10px" src="*.png" />

style 內容里面 background 可以設置 color,但是 image 會被過濾,就是說不能通過 CSS 來設置背景圖片了。但是有一個很有意思的元素屬性,也叫 background,里面可以定義一個圖片路徑,但是功能有限,比如無法定位背景圖片等。

例如要給一個單元格加一個背景,必須這樣寫:

<td background="*.png">
    <!-- ... -->
</td>

Outlook 2007-2013 不支持圖片的 margin 與 padding 樣式,必要的時候可以嘗試 hspace 和 vspace 屬性:

<img vspace="10" hspace="10" src="*.png" />

4.文本相關

所有的CSS規則,都需要采用行內樣式。因為放置在網頁頭部的樣式,會被Gmail客戶端過濾掉。而我們面向海外的主要客戶群使用的正式Gmail郵箱。

在 HTML 郵件中,font-family 只支持系統字體,不支持自定義字體,也不支持 font 簡寫,color 盡可能也不要使用簡寫。對於加粗字體,可以使用b標簽而不要使用font-weight,前文介紹過,能用html標簽和屬性解決的樣式問題就不要使用CSS樣式。

5.行高

在 OutLook 中會有個默認的行高最小值,特別是當設置 font-family 為微軟雅黑時,默認的行高差不多為 Word 中的兩倍行距,如果 line-height 設置的值小於默認的行高,無論你設置的是多少,則始終使用默認值,在很多情況下這是不能忍的,好在有個神奇的 mso-line-height-rule,使用行高時添加 mso-line-height-rule:exactly; 就能使行高始終等於我們所設置的值。

<td style="mso-line-height-rule: exactly; line-height: 36px;">
    <!-- ... -->
</td>

這只是微軟的CSS屬性,對其他客戶端沒影響。並且該屬性只在這塊元素上有效。

整體總結

1.頁面寬度請設定在550到650px以內。

2.使用table表格來布局。

3.如果需要郵件居中顯示,請在table里設定align="center"。

4、不要寫<style>標簽、不要寫class,所有CSS都用style屬性,什么元素需要什么樣式就用style寫內聯的CSS。

5、不要使用外鏈的css樣式定義文字和圖片(外鏈的css樣式在郵件里將不能被讀取,所以發送出去的郵件因為沒有鏈接到樣式,將會使你的郵件內容樣式丟失),正確的寫法:<td style="font-family:arial;font-size:12px;color:black">文字</td>。

6、不使用flash、java、javascript、frames、iframe、activeX以及DHTML,如果頁面中的圖片一定要動態的,請將flash文件轉換成gif動畫使用,但在outlook2007里,gif將不能正常顯示,因為outlook2007限制gif動畫。

7、不要使用<table></table>以外的body、meta和html之類的標簽,部分郵箱系統會把這些過濾掉。

8、背景圖片代碼寫法如下:<table background="background.gif" cellspacing="0" cellpadding="0"></table>,但請注意,outlook對背景圖片不識別。

9.font-family屬性不能為空,否則會被QQ屏蔽為垃圾郵件。

10.若郵件模板內側邊或者上下有空白間距,不要用 padding,必須得用標准的 td 來設定空白間距,否則會導致各個郵箱解析不同。

11、在 yahoo 郵箱里定義 line-height 的注意事項:需在塊級元素里定義 line-height。如果 td 里有 p 標簽,則 line-height 也必須在 p 中定義。無論是 td 還是 p,如果有超鏈接,則都必須在 a 標簽里定義 line-height。如果只是在 td 或者 p 里面定義 line-height 的話,那 yahoo 郵箱將無法識別 a 里面的行高。

12.少用float, margin,padding. 絕對定位不能用,清除浮動用<table style="clear:both"></table>

13.如果 td 和 td 之間有間隔,使用<td style="border-bottom:10px solid #fff"></td>,這樣寫的話 td 之間是不會有間隔的。使用<td style="margin-bottom: 10px"></td>也是不會有空格的。如果 td 之間有間隙,必須用<td></td><td height="10px">&nbsp;</td><td></td>來隔開。但是如果是 table,則<table style="border-top:10px solid #ffffff; border-bottom:20px solid #ffffff"></table>里面的內容會在上下有空行。

14.少用圖片,郵箱不會過濾你的img標簽,但是系統往往會默認不載入陌生來信的圖片,如果用了很多圖片的郵件,在片沒有載入的情況下,丑陋無比甚至看不清內容,沒耐心的用戶直接就刪除了。圖片上務必加上alt。

outlook 規則

1.在<td>里設置 margin 是無效的,不論是 margin-left、margin-right、margin-top 或者 margin-boottom 都沒有效果。

2.如果要使用<P>標簽要考慮到<P>標簽本身自帶的上下行之間的行高。

yahoo規則

在table里設定align="center"無法居中, 需要內聯style=“margin:0 auto,width:XX”

foxmail 規則

foxmail中所有p標簽的Margin:0; 使用p標簽時需要設置margin

郵件模板正好之后,接下來就是要解決根據不同的消息類型來展示不同的內容這個問題,目前我們采用的是thymeleaf模板引擎。主要用到的渲染語法如下:

1.獲取變量值

<p th:text="'Hello!, ' + ${name} + '!'" >3333</p>
全部替換
<p th:text="${copyright}"2018 Closeli, Inc., All rights reserved </p>

可以看出獲取變量值用$符號,對於javaBean的話使用變量名.屬性名方式獲取,這點和EL表達式一樣.

另外$表達式只能寫在th標簽內部,不然不會生效,上面例子就是使用th:text標簽的值替換p標簽里面的值,至於p里面的原有的值只是為了給前端開發時做展示用的.這樣的話很好的做到了前后端分離.

2.引入圖片url地址

Thymeleaf對於URL的處理是通過語法@{…}來處理

<a th:href="@{http://blog.csdn.net/u012706811}">絕對路徑</a>
<a th:href="@{/}">相對路徑</a>
<a th:href="@{css/bootstrap.min.css}">Content路徑,默認訪問static下的css文件夾</a>
動態獲取src地址
<img alt="" width="300" src="cid:inlineCid0"/>

3.字符串替換

很多時候可能我們只需要對一大段文字中的某一處地方進行替換,可以通過字符串拼接操作完成:

<span th:text="'Welcome to our application, ' + ${user.name} + '!'"> 

4.布爾值條件判斷

通過布爾值條件判斷渲染來切換不同的顯示界面從而達到預期效果,同時還用到了解析對象的語法th:utext

<div class="push-content" th:if="${pushContent != null}">
    <td th:text="${pushContent.title}">異常運動異常</td>
</div>

html5操作支持

th:abbr          th:accept             th:accept-charset
th:accesskey             th:action             th:align
th:alt             th:archive             th:audio
th:autocomplete             th:axis             th:background
th:bgcolor             th:border             th:cellpadding
th:cellspacing             th:challenge             th:charset
th:cite             th:class             th:classid
th:codebase             th:codetype             th:cols
th:colspan             th:compact             th:content
th:contenteditable             th:contextmenu             th:data
th:datetime             th:dir             th:draggable
th:dropzone             th:enctype             th:for
th:form             th:formaction             th:formenctype
th:formmethod             th:formtarget             th:fragment
th:frame             th:frameborder             th:headers
th:height             th:high             th:href
th:hreflang             th:hspace             th:http-equiv
 
th:icon             th:id             th:inline
th:keytype             th:kind             th:label
th:lang             th:list             th:longdesc
th:low             th:manifest             th:marginheight
th:marginwidth             th:max             th:maxlength
th:media             th:method             th:min
th:name            th:onabort            th:onafterprint
th:onbeforeprint            th:onbeforeunload            th:onblur
th:oncanplay            th:oncanplaythrough            th:onchange
th:onclick            th:oncontextmenu            th:ondblclick
th:ondrag            th:ondragend            th:ondragenter
th:ondragleave            th:ondragover            th:ondragstart
th:ondrop            th:ondurationchange            th:onemptied
th:onended            th:onerror            th:onfocus
th:onformchange            th:onforminput            th:onhashchange
th:oninput            th:oninvalid            th:onkeydown
th:onkeypress            th:onkeyup            th:onload
th:onloadeddata            th:onloadedmetadata            th:onloadstart
th:onmessage            th:onmousedown            th:onmousemove
th:onmouseout            th:onmouseover            th:onmouseup
th:onmousewheel            th:onoffline            th:ononline
th:onpause            th:onplay            th:onplaying
th:onpopstate            th:onprogress            th:onratechange
th:onreadystatechange            th:onredo            th:onreset
th:onresize            th:onscroll            th:onseeked
th:onseeking            th:onselect            th:onshow
th:onstalled            th:onstorage            th:onsubmit
th:onsuspend            th:ontimeupdate            th:onundo
th:onunload            th:onvolumechange            th:onwaiting
th:optimum            th:pattern            th:placeholder
th:poster            th:preload            th:radiogroup
th:rel            th:rev            th:rows
th:rowspan            th:rules            th:sandbox
th:scheme            th:scope            th:scrolling
th:size            th:sizes            th:span
th:spellcheck            th:src            th:srclang
th:standby            th:start            th:step
th:style            th:summary            th:tabindex
th:target            th:title            th:type
th:usemap            th:value            th:valuetype
th:vspace            th:width            th:wrap
 
th:vspace            th:width            th:wrap
th:xmlbase            th:xmllang            th:xmlspace

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM