在桌面和移动端渲染电子邮件大约有上百万种不同的组合方式。
尤其是鼎鼎大名的 OutLook,从 OutLook2007 开始便使用 Word HTML 引擎进行渲染,为了它的安全性从而使得整个邮件倒退回了 2000 年前,为了邮件的兼容性你不得不使用很多废弃的标签、属性,并且这一状况将会维持无数个
年头,因为虽然万事终有尽头,但 OutLook 始终存在。
因为微软一向地特立独行,使得 OutLook 成为了最难啃的骨头。因为 OutLook 支持的标签和属性少得可怜,所以只要兼容了 OutLook,其他邮箱客户端基本都不会有什么问题。
使用tableb布局
这几乎是 HTML 邮件与普通 HTML 页面最大的区别,因为各个邮箱对 div + css 这一套布局的解析问题很大(如 float / position 等 CSS 都会被过滤,甚至 margin: 0 auto都不起作用),基本各大邮箱都会解析混乱,所以老式的 table 布局是上乘之选。这就意味着 HTML 邮件中几乎只有这几个元素——table / tr / td / span / img / a,尽量避免使用 div / p 或是其他标签。
而且并不是所有邮箱都支持 colspan / rowspan 属性,所以所有布局都需要使用 table 嵌套解决。
1.Doctype
目前,兼容性最好的Doctype是XHTML 1.0 Strict,事实上Gmail和Hotmail会删掉你的Doctype,换上这个Doctype。
使用这个Doctype,也就意味着,不能使用HTML5的语法。
2.布局
网页的布局(layout)必须使用表格(table)。首先,放置一个最外层的大表格,用来设置背景。
基本html
3.图片
图片是唯一可以引用的外部资源。其他的外部资源,比如样式表文件、字体文件、视频文件等,一概不能引用。
有些客户端会给图片链接加上边框,要去除边框。
需要注意的是,不少客户端默认不显示图片(比如Gmail),所以要确保即使没有图片,主要内容也能被阅读。
4.行内样式
所有的CSS规则,最好都采用行内样式。因为放置在网页头部的样式,很可能会被客户端删除。客户端对CSS规则的支持情况,请看这里。
另外,不要采用CSS的简写形式,有些客户端不支持。比如,不要写成下面这样:
如果想表达
要写成下面这样:
相关文章
HTML 邮件兼容问题与解决方案
首先,我们来说一下如何发送HTML邮件。
发送图文HTML邮件很简单,发送方法如下:
首先,复制邮件代码,然后打开自己的邮箱,转换为代码输入方式,粘贴代码,就可以发送邮件了。详见下图(图1为QQ邮箱,图2为163邮箱)。
接下来,我们再说一下如何制作图文HTML邮件。
制作图文邮件如果是自己写代码,那就太难了,反正有很多坑,如果不是专业人员,就不要自己写了。
难道没有其他办法了,有的,那就是使用别人做好的现成的平台来写HTML邮件,跳过写代码这一步,这样做邮件就很简单了,可以说人人都会。具体怎么做,请自行百度搜索“图文并茂+邮件”,就能找到自己的制作方法了。
附:相关概念:
什么是html格式邮件?
HTML邮件就是使用HTML标记来写的邮件。
就邮件类别来说,纯文本邮件和HTML邮件没有区别,都是邮件,但是后者内容和形式更加丰富,可以有颜色、链接和图片,就象一个彩色的图文彩页,表现力更强。
就本质来说,HTML实际上它就是一个网页,但又不同于网页,因HTML邮件要求兼容性必须更好,否则就有可能存在错位无法观看的风险。
那么HTML制作是不是很难呢?从专业写代码的角度说,确实艰难,代码、兼容性、各种邮箱的差异性均有可能造成邮件乱码和错位,达不到展示效果。
实际上难不难关键在于你的着眼点,在于你的解决问题的方法。如果你的方法使用正确了,HTML邮件的制作又是艰简单的,因为他们都跳过了写代码,所以适合普通人使用,网上有很多类似的平台,请自行百度搜索“图文并茂+邮件”就会找到适合自己的制作图文邮件的方法,提高制作效率。
发送html格式的邮件void jButton8_actionPerformed(ActionEvent e) {try
{//此段代码用来发送带有html信息的邮件
Properties props = new Properties()
Authenticator auth = new Email_Autherticator()
props.put( "mail.smtp.host ",host)
props.put( "mail.smtp.auth ", "true ")
Session session = Session.getDefaultInstance(props,auth)
MimeMessage message = new MimeMessage(session)
//设置邮件正文
String htmltext= " <h1>hello </h1>"+ " <a href=\ " http://www.sina.com.cn\ " target=\ "_blank\ ">click me please! </a>"
message.setContent(htmltext, "text/html ")//text/plain设置邮件的格式因为是带有html文档的,所以用text/html格式
message.setSubject(mail_subject)
// message.setText(mail_body)在使用message.setContent()时候,好象不能用message.setText()
message.setHeader(mail_head_name,mail_head_value)
message.setSentDate(new Date())
Address address = new InternetAddress(mail_from, "sunxiaoming ")
message.setFrom(address)
Address toAddress = new InternetAddress(mail_to)
message.addRecipient(Message.RecipientType.TO,toAddress)
Transport.send(message)
System.out.println( "send ok! ")
}
catch(Exception ex)
{
System.out.println( "faild "+ex)
}
}
void jButton9_actionPerformed(ActionEvent e) {
try
{//此段代码用来发送带有图片的邮件
String file = "./20020423/test.gif "
Properties props = new Properties()
Authenticator auth = new Email_Autherticator()
props.put( "mail.smtp.host ",host)
props.put( "mail.smtp.auth ", "true ")
Session session = Session.getDefaultInstance(props,auth)
MimeMessage message = new MimeMessage(session)
message.setSubject( "Embedded Image ")
Address address = new InternetAddress(mail_from, "sunxiaoming ")
message.setFrom(address)
Address toAddress = new InternetAddress(mail_to)
message.addRecipient(Message.RecipientType.TO,toAddress)
message.setHeader(mail_head_name,mail_head_value)
message.setSentDate(new Date())
BodyPart messageBodyPart = new MimeBodyPart()
String htmlText = " <h1><hello></h1>"+ " <img src=\ "cid:memememe\ ">"//加入图片
messageBodyPart.setContent(htmlText, "text/html ")
//原理同发送附件一样,将邮件看成有多个部分组成的,先设置每一个部分,然后再全部将它们合起来即可。
//Create a related multi-part to combine the parts
MimeMultipart multipart = new MimeMultipart( "related ")
multipart.addBodyPart(messageBodyPart)
//Create part for the image
messageBodyPart = new MimeBodyPart()
//Fetch the image and associate to part
DataSource fds = new FileDataSource(file)
messageBodyPart.setDataHandler(new DataHandler(fds))
messageBodyPart.setHeader( "Content-ID ", "memememe ")
//Add part to multi-part
multipart.addBodyPart(messageBodyPart)
//Associate multi-part with message
message.setContent(multipart)
Transport.send(message)
System.out.println( "send ok! ")
}
catch(Exception ex)
{
System.out.println( "faild "+ex)
}
}
void jButton7_actionPerformed(ActionEvent e) {
try
{//该程序用来接受带有html信息的邮件
Properties props = System.getProperties()
Authenticator auth = new Email_Autherticator()
props.put( "mail.smtp.host ",host)
props.put( "mail.smtp.auth ", "true ")
Session session = Session.getDefaultInstance(props,auth)
Store store = session.getStore( "pop3 ")
store.connect(host,username,password)
//After connecting to the Store,you can get a Folder,which must be opened before you can read messages from it:
Folder folder = store.getFolder( "INBOX ")
folder.open(Folder.READ_WRITE)
Message message[] = folder.getMessages()
for (int i=0,n=message.lengthi <ni++)
// for (int i=0,n=1i <ni++)//only one letter received from inbox //for debug
{
String out_from_person = ((InternetAddress)message[i].getFrom()[0]).getPersonal()
String out_from_address = ((InternetAddress)message[i].getFrom()[0]).getAddress()
System.out.println( "From: "+out_from_person+ "\t ")
System.out.println( "Address: "+out_from_address+ "\t ")
String out_subject = message[i].getSubject()
System.out.println( "Subject: "+out_subject+ "\t ")
//获取邮件的信息,并且对其每一部分进行操作
Part messagePart = message[i]
Object out_content = messagePart.getContent()
if (out_content instanceof Multipart)
{
messagePart = ((Multipart)out_content).getBodyPart(0)
System.out.println( "[ Multipart Message ] ")
}
String out_content_type = messagePart.getContentType()
System.out.println( "CONTENT: "+out_content_type)
jEditorPane1.setText( " ")//将其显示在jEditorPanel上
jEditorPane1.setContentType( "text/html ")
jEditorPane1.setText((String)out_content)
jEditorPane1.setEditable(false)
/*
if (out_content_type.startsWith( "text/plain ") || out_content_type.startsWith( "text/html "))
{
InputStream ipstm = messagePart.getInputStream()
BufferedReader bufreader = new BufferedReader(new InputStreamReader(ipstm))
String thisLine = bufreader.readLine()
while (thisLine != null)
{
System.out.println( "thisLine: "+thisLine)
thisLine = bufreader.readLine()
}
}
*/
System.out.println( "------------------------------------------------------------ ")
message[i].setFlag(Flags.Flag.DELETED,true)
}
folder.close(true)
store.close()
}
catch(Exception ej2)
{
System.out.println(ej2)
}
}