2

我正在用 PHP 编写一个简单的 HTML 电子邮件设计编辑器,并演示了它的外观。

我认为向用户展示这在关闭图像的电子邮件客户端(如 gmail)中的外观也是非常有用的。

我最好的方法是什么?有人知道这是如何在 gmail/hotmail 等中完成的吗?

我是否简单地删除img -> srccss background: url使用 reg 表达式?

我想从以下位置删除背景部分: background="url"用于表格和 background-image:url(url);使用内联 css

我发现这个问题具有相同的想法,尽管我想从 HTML 文本中实际删除 img 和 backrgound-images 。

或者可以修改此代码以使用背景图像吗?

4

7 回答 7

3

为了完全模仿 gmail 或类似网络邮件的行为,将相应地替换标签和 background: css 属性,以便它们显示一个占位符,让用户清楚地知道这里有一个图像。

由于通常消息是在 iframe 中加载的,我相信您最好的猜测是清理消息服务器端,删除所有不需要的标签并在预览时相应地替换图像。

我同意 Michal 的观点,即仅使用正则表达式来验证您的 HTML 是不明智的,您可能应该遍历 DOM 树以确保安全。

为什么不看一下Roundcube 使用的 Frederic Motte的 washtml来帮助您入门?

于 2012-04-10T12:39:06.260 回答
3

我还建议使用 PHP DOM 而不是正则表达式,这通常是不准确的。这是一个示例代码,您可以使用它从字符串中去除所有 img 标签和所有背景属性:

// ...loading the DOM
$dom = new DOMDocument();
@$dom->loadHTML($string);  // Using @ to hide any parse warning sometimes resulting from markup errors
$dom->preserveWhiteSpace = false;
// Here we strip all the img tags in the document
$images = $dom->getElementsByTagName('img');
$imgs = array();
foreach($images as $img) {
    $imgs[] = $img;
}
foreach($imgs as $img) {
    $img->parentNode->removeChild($img);
}
// This part strips all 'background' attribute in (all) the body tag(s)
$bodies = $dom->getElementsByTagName('body');
$bodybg = array();
foreach($bodies as $bg) {
    $bodybg[] = $bg;
}
foreach($bodybg as $bg) {
    $bg->removeAttribute('background');
}

$str = $dom->saveHTML();

我选择了 body 标签而不是 table,因为它<table>本身没有background属性,它只有bgcolor. 要去除背景内联 css 属性,您可以使用sabberworm 的 PHP CSS Parser 来解析从 DOM 检索到的 CSS:试试这个

// Selecting all the elements since each one could have a style attribute
$alltags = $dom->getElementsByTagName('*');
$tags = array();
foreach($alltags as $tag) {
    $tags[] = $tag;
} $css = array();
foreach($tags as &$tag) {
    $oParser = new CSSParser("p{".$tag->getAttribute('style')."}");
    $oCss = $oParser->parse();
    foreach($oCss->getAllRuleSets() as $oRuleSet) {
        $oRuleSet->removeRule('background');
        $oRuleSet->removeRule('background-image');
    }
    $css = $oCss->__toString();
    $css = substr_replace($css, '', 0, 3);
    $css = substr_replace($css, '', -2, 2);
    if($css)
        $tag->setAttribute('style', $css);
}

一起使用所有这些代码,例如,如果你有一个

$string = '<!DOCTYPE html>
<html><body background="http://yo.ur/background/dot/com" etc="an attribute value">
<img src="http://your.pa/th/to/image"><img src="http://anoth.er/path/to/image">
<div style="background-image:url(http://inli.ne/css/background);border: 1px solid black">div content...</div>
<div style="background:url(http://inli.ne/css/background);border: 1px solid black">2nd div content...</div>
</body></html>';

PHP将输出

<!DOCTYPE html>
<html><body etc="an attribute value">
<div style="border: 1px solid black;">div content...</div>
<div style="border: 1px solid black;">2nd div content...</div>
</body></html>
于 2012-04-14T13:43:36.923 回答
1

通常不推荐使用正则表达式来解析 html。

我认为更好的方法是解析 html 服务器端,并对其进行操作以删除图像或图像 src 属性。我成功使用的一个库是http://simplehtmldom.sourceforge.net/,但我认为您可以使用官方的 PHP DOM 扩展。

删除背景图像可能更棘手。您可能必须使用http://www.pelagodesign.com/sidecar/emogrifier/之类的东西来将 {background: none} 之类的东西应用于 html 元素。但是,最新版本的 Microsoft Outlook 不支持 CSS 背景图像,因此我建议从一开始就不要使用它们,以使大多数电子邮件客户端的电子邮件保持一致。

于 2012-04-08T08:42:42.560 回答
1

就像 tkone 提到的:也许 JavaScript / jQuery 就是答案。

这将查看预览区域中的所有图像并将源更改为占位符图像。“占位符”类也将背景图像设置为占位符

jQuery

$("#previewArea img").each(function(){
  $(this).attr("src","placeholder.jpg");
  $(this).addClass("hideBG");
});

CSS

.hideBG{
  background: url("placeholder.jpg");
}

未经测试,但应该可以工作 - 取决于您的设置和需求。

于 2012-04-12T04:12:01.380 回答
1

我问过一个类似的问题(在解决方案中,不是实际问题):如何从字符串中去除特定标签和特定属性?解决方案

它是一个服务器端库,可根据预定义的设置清理(和格式化)HTML 输入。让它删除任何src属性和所有background属性。

于 2012-04-14T13:53:35.157 回答
0

您也可以始终在客户端执行此操作。

使用这个假设的代码,你应该能够做这样的事情,假装现代浏览器都工作相同:(或使用 jQuery 或其他东西)

var email;
var xhr = new XMLHttpRequest();
xhr.open('GET', URL_FOR_EMAIL, true);
xhr.onreadystatechange = function(event){
   if(xhr.readyState === 4 && xhr.status === 200){
        email = HTMLParser(xhr.responseText);
   }
}

var imgs = email.getElementsByTagName('img');
for(var i = 0; i > imgs.length; i++){
    email.removeChild(imgs[i]);
}

// attach the email body to the DOM
// do something with the images

来自MDN的 HTMLParser

function HTMLParser(aHTMLString){
  var html = document.implementation.createDocument("http://www.w3.org/1999/xhtml", "html", null),
    body = document.createElementNS("http://www.w3.org/1999/xhtml", "body");
  html.documentElement.appendChild(body);

  body.appendChild(Components.classes["@mozilla.org/feed-unescapehtml;1"]
    .getService(Components.interfaces.nsIScriptableUnescapeHTML)
    .parseFragment(aHTMLString, false, null, body));

  return body;
},
于 2012-04-10T13:09:54.903 回答
0

我认为最好的方法是使用不处理“src”属性的标签来保持更改可逆。

例如:将所有“img”更改为“br”

所以打印过滤后的 HTML 1st 并用 ajax 反转它,搜索所有带有 src 属性的 br 。

于 2012-04-13T18:38:34.127 回答