【问题标题】:how to handle cid image sources when rendering emails in iframe在 iframe 中渲染电子邮件时如何处理 cid 图像源
【发布时间】:2018-06-28 18:34:07
【问题描述】:

我们有一个用 Angular4+ 编写的网络电子邮件客户端。 我们从 Exchange 网络服务加载电子邮件。

传入的邮件经过清理,然后作为 iframe 的源呈现。 即使图像也能正常工作,只是它们像嵌入一样

<img width="486" height="572" id="Grafik_x0020_2" src="cid:image002.jpg@01D39103.BD805530">

有没有办法在呈现电子邮件时显示图像? 我们也可以下载附件。

感谢和最好的问候 克里斯托夫

【问题讨论】:

    标签: javascript email iframe exchangewebservices embedded-resource


    【解决方案1】:

    因为我们已经下载了附件,所以我写了一个解决问题的管道:

    import { Pipe, PipeTransform } from '@angular/core';
    import { TrusthtmlPipe } from 'app/crm-modules/core/pipes/trusthtmlPipe';
    import { DomSanitizer } from '@angular/platform-browser';
    import { SafeHtml } from '@angular/platform-browser/src/security/dom_sanitization_service';
    import { AttachmentInfo } from 'app/crm-modules/email/models/attachment-info';
    
    import * as _ from 'lodash';
    
    @Pipe({
      name: 'cidToBase64'
    })
    
    export class CidToBase64Pipe implements PipeTransform {
      constructor(private sanitizer: DomSanitizer) {
        this.sanitizer = sanitizer;
      }
    
      transform(html: any, attachments: Array<AttachmentInfo> = []): SafeHtml {
        let htmlToParse;
        if (typeof html === 'string') {
          htmlToParse = html;
        } else if (html instanceof Object && html.hasOwnProperty('changingThisBreaksApplicationSecurity')) {
          htmlToParse = (html.changingThisBreaksApplicationSecurity !== null || html.changingThisBreaksApplicationSecurity !== undefined)
            ? html.changingThisBreaksApplicationSecurity
            : '';
        } else {
          htmlToParse = '';
        }
    
        const parser = new DOMParser();
        const doc = parser.parseFromString(htmlToParse, 'text/html');
    
        if (attachments !== null && attachments !== undefined && attachments.length > 0 && htmlToParse.length > 0) {
          const imageLinks = doc.getElementsByTagName('img');
          for (let i = 0; i < imageLinks.length; i++) {
            const imageLink = imageLinks[i];
            const src = imageLink.getAttribute('src');
            if (src !== null && src !== undefined && _.includes(src, 'cid:')) {
    
              let cidInfo;
              let fileName;
              let fileIndex;
              let useImage = true;
    
              cidInfo = src.split('cid:');
              useImage = cidInfo.length === 2;
    
              if (useImage) {
                fileName = cidInfo[1].split('@')[0];
                fileIndex = _.findIndex(attachments, { 'name': fileName, 'inline': true });
                useImage = fileIndex > -1;
              }
    
              if (useImage) {
                imageLink.setAttribute('src', 'data:image/png;base64,' + attachments[fileIndex].content);
              } else {
                // @todo: show placeholder or remove the node...
              }
            }
          }
        }
    
        const trustHtmlPipe = new TrusthtmlPipe(this.sanitizer);
        return trustHtmlPipe.transform(doc.documentElement.innerHTML);
      }
    }
    

    也许有帮助。

    最好的问候 克里斯托夫

    【讨论】:

      【解决方案2】:

      感谢您的代码。我重写了你的管道以自己使用它,我认为它更通用,所以我把它留在这里以防有人发现它有用:

      import { Pipe, PipeTransform } from '@angular/core';
      
      @Pipe({
        name: 'cidToBase64'
      })
      
      export class CidToBase64Pipe implements PipeTransform {
      
        parser : DOMParser = new DOMParser();
      
        constructor() {
        }
      
        transform(html: String, attachments: Attachment[]): String {
      
          if (html.length <= 0) {
            return "";
          }
          if (attachments == null || attachments == undefined || attachments.length < 0) {
            return "";
          }
      
          const doc = this.parser.parseFromString(html.toString(), 'text/html');
          const imageLinks = doc.getElementsByTagName('img');
      
          for (let i = 0; i < imageLinks.length; i++) {
            const src = imageLinks[i].getAttribute('src');
            if (src !== null && src !== undefined && src.includes('cid:')) {
              let attachmentContent = src.split('cid:')[1].split('@')[0];
              let fileIndex = attachments.findIndex(obj => obj.Name === attachmentContent);
              imageLinks[i].setAttribute('src', 'data:image/png;base64,' + attachments[fileIndex].Content);
              html = html.replace(src, imageLinks[i].getAttribute('src'));
            }
          }
          return html;
        }
      }
      
      export interface Attachment {
        Content: String;
        ContentLength: Number;
        Name: String;
        ContentType: String;
        ContentID: String;
      }
      

      然后您可以在 .html 中将其用作任何其他管道:

      <p [innerHTML]="mail.HtmlBody | cidToBase64 : mail.Attachments"></p>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-09-29
        • 2015-06-29
        • 2016-07-29
        • 1970-01-01
        • 2020-08-26
        • 2012-10-20
        • 1970-01-01
        相关资源
        最近更新 更多