【问题标题】:Remove images from html the same as gmail would do for emails without images enabled从 html 中删除图像,就像 gmail 对未启用图像的电子邮件所做的那样
【发布时间】:2012-04-08 08:03:04
【问题描述】:

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

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

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

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

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

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

或者this code 是否可以修改为也可以处理背景图片?

【问题讨论】:

  • 你总是可以注入一点 CSS 来设置所有要显示的图像:无;在预览中。
  • @BenGriffiths,我认为这是完全错误的,因为 display:none 仍会加载图像但不会显示它们(因此违反了您在实现此类功能时可能想到的任何安全性)跨度>
  • @mobius 只是为了生成预览,我认为他不需要担心安全性?
  • @BenGriffiths,在未经用户同意的情况下不加载图像的全部意义在于,大多数图像都位于 url 跟踪架构的后面,这样就可以验证收件人是否实际上是一个有效的电子邮件地址,以及是否他/她确实打开了电子邮件。
  • @mobius - 我认为他正在预览在发送之前,即检查布局。这不是收件人在电子邮件客户端中的预览。至少我是这么理解他写的。

标签: php html email gmail html-email


【解决方案1】:

我还建议使用 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();

我选择了正文标签而不是表格,因为<table> 本身没有background 属性,它只有bgcolor。 要剥离背景内联 css 属性,可以使用 sabberworm's 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>

【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

    • 这看起来像是他尝试做的一个很好的起点。如果您希望它完全复制其他平台的功能,则需要进行一些修改,但总的来说那里有一些很棒的内容
    【解决方案3】:

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

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

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

    【讨论】:

    【解决方案4】:

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

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

    jQuery

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

    CSS

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

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

    【讨论】:

    • 它不会工作,因为它只会在页面加载完成后运行。使您的代码无用。
    • 如果它确实在$(window).load 上运行,它在技术上仍然可以工作,但用户必须在它更改为预览模式之前查看并下载所有内容。因为这是一个电子邮件设计应用程序,所以应该不是问题。如果这是一个问题,它可以在$(document).ready 上运行,这将在 DOM 加载后立即进行所有更改,而不管图像的加载状态(即在它们显示在页面上之前)。跨度>
    【解决方案5】:

    我问过一个类似的问题(在解决方案中,不是实际问题):How to strip specific tags and specific attributes from a string? (Solution)

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

    【讨论】:

      【解决方案6】:

      您也可以随时在客户端执行此操作。

      使用这个假设的代码,你应该能够做这样的事情,假设现代浏览器都工作相同:(或使用 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;
      },
      

      【讨论】:

        【解决方案7】:

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

        例如:把所有的“img”换成“br”

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

        【讨论】:

          猜你喜欢
          • 2011-11-09
          • 1970-01-01
          • 1970-01-01
          • 2021-08-27
          • 2012-01-08
          • 1970-01-01
          • 2016-12-31
          • 2018-12-27
          • 2011-06-09
          相关资源
          最近更新 更多