在 iframe 中呈现电子邮件时如何处理 CID 图像源



我们有一个用Angular4+编写的Web-email-client。我们从 Exchange Web 服务加载电子邮件。

传入邮件经过清理,然后呈现为 iframe 的源。即使对于图像,这也工作正常,除了它们被嵌入为类似

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

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

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

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

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);
  }
}

也许它有帮助。

此致敬意克里斯托夫

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

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>