Skip to content
Snippets Groups Projects
emailUtilities.js 3.2 KiB
Newer Older
  • Learn to ignore specific revisions
  • import dataUriToBlob from "data-uri-to-blob";
    import libmime from 'libmime';
    
    import union from 'lodash/union';
    
    
    import {
      fixNewLines,
      parseMIME,
      getHTML,
      getPlain,
      getAttachments,
      getAttachment,
      getGlobalHeaderValue
    } from "../helpers/mailparser";
    import { getCertificateChain } from "./signingUtilities";
    
    const SIGNATURE_CONTENT_TYPE = "application/pkcs7-signature";
    export const DEFAULT_ATTACHMENT_NAME = 'attachment';
    
    
    const splitParticipants = participantsList => {
    
      const participants = participantsList.map(participants => participants.split(",").map(p => p.trim()));
    
      return union.apply(null, participants);
    };
    
    
    export const parseSMIME = smimeString => {
      return new Promise(resolve => {
        setTimeout(async () => {
          const emailString = fixNewLines(smimeString);
          const parts = parseMIME(emailString);
          const html = getHTML(emailString, parts);
          const plain = getPlain(emailString, parts);
          const rawAttachments = getAttachments(emailString, parts);
    
          const attachments = [];
          let signatureBase64;
          for (const rawAttachment of rawAttachments) {
            const { contentType, base64 } = getAttachment(
              emailString,
              rawAttachment
            );
    
            if (contentType.indexOf(SIGNATURE_CONTENT_TYPE) !== -1) {
              signatureBase64 = base64;
            }
    
            const dataURI = "data:" + contentType + ";base64, " + base64;
            const blob = dataUriToBlob(dataURI);
            const filename = getFilenameFromHeaders(rawAttachment.headers);
    
            attachments.push({
              blob,
              filename
            });
          }
    
          const certificateChain = getCertificateChain(signatureBase64);
    
    
          const from = splitParticipants(getGlobalHeaderValue("from", parts));
          const to = splitParticipants(getGlobalHeaderValue("to", parts));
          const cc = splitParticipants(getGlobalHeaderValue("cc", parts));
    
    
            subject: getGlobalHeaderValue("subject", parts).join(" "),
            html: extractHtmlBodyFromString(html),
            plain,
            attachments,
            certificateChain
          };
    
          resolve(message);
        }, 50);
      });
    };
    
    /**
     * Function extracts file name from content type header
     * @param headers
     * @returns {string} ('file.txt')
     */
    export const getFilenameFromHeaders = headers => {
      const headersToSearch = ['content-type', 'content-disposition'];
    
      const filename = headers && Object.keys(headers)
        .filter(key => headersToSearch.includes(key))
        .reduce((result, key) => {
          const headerValue = libmime.parseHeaderValue(headers[key][0]);
          return result || headerValue.params.name || headerValue.params.filename;
        }, '');
    
      return filename || DEFAULT_ATTACHMENT_NAME;
    };
    
    /**
     * Function extracts all tags within <body></body> from provided string
     * and removes whitespaces between tags and HTML comments.
     * @param string
     * @returns {*}
     */
    export const extractHtmlBodyFromString = string => {
      const extractBodyRegex = /<body.*?>([\s\S]+)<\/body>/gm;
      const bodyMatch = extractBodyRegex.exec(string);
    
      let body;
    
      if (bodyMatch && bodyMatch[1]) {
        body = bodyMatch[1]
          .replace(/>\s+</gm, '><')
          .replace(/<!--[\s\S]*?-->/gm, '').trim()
      }
    
      return body;