diff --git a/javascript/src/iframe/viamapi-iframe.js b/javascript/src/iframe/viamapi-iframe.js
index 5b3e7eb4c4db7ffc53beac571610621cbaac1524..cdb6a46edff86b7068fa091309e22d4434a044dd 100644
--- a/javascript/src/iframe/viamapi-iframe.js
+++ b/javascript/src/iframe/viamapi-iframe.js
@@ -1539,7 +1539,7 @@ const connection = Penpal.connectToParent({
         console.log("Text body is not passed to signVCard, its value is ", {text: textBody});
       }
 
-      const count = prepareVCardParts(parts);
+      const count = await prepareVCardParts(parts);
       if (count.textParts === 0) {
         return encodeResponse("400", "", "No text parts passed to signVCard");
       }
diff --git a/javascript/src/utilities/emailUtilities.js b/javascript/src/utilities/emailUtilities.js
index 988f879940b4bd1cac8eb118367d6e8f7ff05413..1a696a1b566be6ea55bab5d3788584327c41bd77 100644
--- a/javascript/src/utilities/emailUtilities.js
+++ b/javascript/src/utilities/emailUtilities.js
@@ -17,8 +17,10 @@ import {
 } from "./signingUtilities";
 import {
   byteArrayToBase64,
-  stringToUtf8Base64
+  stringToUtf8Base64,
+  stringToUtf8ByteArray
 } from "./stringUtilities";
+import {getCrypto} from "pkijs";
 
 export const SIGNATURE_CONTENT_TYPE = "application/pkcs7-signature";
 export const DEFAULT_ATTACHMENT_NAME = "attachment";
@@ -150,14 +152,52 @@ const capitalizeFirstLetter = (s) => {
   return s.charAt(0).toUpperCase() + s.slice(1);
 };
 
-export function prepareVCardParts(parts) {
-  if (!parts) {
-    return;
+async function sha256(array) {
+  const cryptoLib = getCrypto();
+  const digestTmpBuf = await cryptoLib.digest({ name: "SHA-256" }, array);
+  const digestTmpArray = new Uint8Array(digestTmpBuf);
+  return digestTmpArray;
+}
+
+async function hashBody(part) {
+  const contentType = part.headers["Content-Type"];
+  const origContentType = part.headers["Original-Content-Type"];
+
+  if (!origContentType &&
+      !part.headers["Content-Type"].startsWith("application/hash") &&
+      !part.headers["Content-Type"].startsWith("text/plain") &&
+      !part.headers["Content-Type"].startsWith("text/html")) {
+    if (part.body) {
+      if (typeof part.body === "string") {
+        part.body = stringToUtf8ByteArray(part.body);
+      }
+      if (part.body instanceof ArrayBuffer) {
+        part.body = byteArrayToBase64(new Uint8Array(part.body));
+      }
+      if (!(part.body instanceof Uint8Array)) {
+        throw new Error('part body is neither string, nor Uint8Array, nor ArrayBuffer'); // should not happen
+      }
+
+      if (contentType) {
+        part.headers["Original-Content-Type"] = contentType;
+      }
+      part.headers["Content-Type"] = "application/hash; algorithm=SHA-256";
+
+      part.body = await sha256(part.body);
+    }
   }
+}
+
+export async function prepareVCardParts(parts) {
   const count = {
     textParts: 0,
     htmlParts: 0
   };
+
+  if (!parts) {
+    return count;
+  }
+
   for (const part of parts) {
     if (!part.headers) {
       part.headers = {
@@ -169,17 +209,18 @@ export function prepareVCardParts(parts) {
         capitalizedHeaders[capitalizeHeaderName(key)] = part.headers[key];
       }
       part.headers = capitalizedHeaders;
-      try {
+      if (!part.headers["Content-Type"]) {
+        part.headers["Content-Type"] = "application/octet-stream";
+      } else {
         if (part.headers["Content-Type"].startsWith("text/plain")) {
           count.textParts++;
         } else if (part.headers["Content-Type"].startsWith("text/html")) {
           count.htmlParts++;
         }
-      } catch (ignore) {
-        //ignore
       }
     }
     if (part.body) {
+      await hashBody(part);
       if (typeof part.body === "string") {
         part.body = stringToUtf8Base64(part.body);
       } else
@@ -193,7 +234,7 @@ export function prepareVCardParts(parts) {
       }
     }
     if (part.parts) {
-      const subcount = prepareVCardParts(part.parts);
+      const subcount = await prepareVCardParts(part.parts);
       count.textParts += subcount.textParts;
       count.htmlParts += subcount.htmlParts;
     }