Skip to content
Snippets Groups Projects
emailUtilities.js 3.28 KiB
Newer Older
  • Learn to ignore specific revisions
  • import dataUriToBlob from "data-uri-to-blob";
    
    Alexey Lunin's avatar
    Alexey Lunin committed
    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";
    
    Alexey Lunin's avatar
    Alexey Lunin committed
    export const DEFAULT_ATTACHMENT_NAME = "attachment";
    
    const splitParticipants = participantsList => {
    
      if (!participantsList) {
        return [];
      }
    
    
    Alexey Lunin's avatar
    Alexey Lunin committed
      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 => {
    
    Alexey Lunin's avatar
    Alexey Lunin committed
      const headersToSearch = ["content-type", "content-disposition"];
    
    Alexey Lunin's avatar
    Alexey Lunin committed
      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]
    
    Alexey Lunin's avatar
    Alexey Lunin committed
          .replace(/>\s+</gm, "><")
          .replace(/<!--[\s\S]*?-->/gm, "")
          .trim();