Copy an e-mail including subject and details
// ==UserScript==
// @name Complete Copy for Gmail
// @namespace https://www.fiverr.com/ahkdev
// @version 2025-04-21
// @description Copy an e-mail including subject and details
// @author skygate2012
// @match https://mail.google.com/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=google.com
// @grant GM_addStyle
// @license MIT
// ==/UserScript==
(function() {
'use strict';
GM_addStyle(`
.copy-complete-btn {
width: 20px;
height: 20px;
margin-left: 20px;
cursor: pointer;
display: inline-block;
user-select: none;
background-image: url('data:image/svg+xml,%3Csvg%20viewBox%3D%220%20-960%20960%20960%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M120-220v-80h80v80h-80zm0-140v-80h80v80h-80zm0-140v-80h80v80h-80zM260-80v-80h80v80h-80zm100-160q-33%200-56.5-23.5T280-320v-480q0-33%2023.5-56.5T360-880h360q33%200%2056.5%2023.5T800-800v480q0%2033-23.5%2056.5T720-240H360zm0-80h360v-480H360v480zm40%20240v-80h80v80h-80zm-200%200q-33%200-56.5-23.5T120-160h80v80zm340%200v-80h80q0%2033-23.5%2056.5T540-80zM120-640q0-33%2023.5-56.5T200-720v80h-80zm420%2080z%22%2F%3E%3C%2Fsvg%3E');
}
.copy-complete-btn:before {
content: "";
display: block;
opacity: 0;
width: 200%;
height: 200%;
transition-duration: .15s;
transition-timing-function: cubic-bezier(0.4,0,0.2,1);
position: relative;
bottom: -10px;
left: -10px;
right: -10px;
top: -10px;
background: none;
border-radius: 50%;
box-sizing: border-box;
transform: scale(0);
transition-property: transform, opacity;
}
.copy-complete-btn:hover:before {
background-color: rgba(32, 33, 36, .12);
border: none;
box-shadow: inset 0 0 0 1px rgb(189, 193, 198);
opacity: .5;
-webkit-transform: scale(1);
transform: scale(1);
}
.copy-complete-btn:active:before {
opacity: 1;
}
`);
new MutationObserver((mutationRecords, observer) => {
document.querySelectorAll('[data-message-id]:not([data-ccgprocessed])').forEach((message) => {
const copyButton = document.createElement('div');
copyButton.role = 'button';
copyButton.dataset.tooltip = 'Copy Complete';
copyButton.className = 'copy-complete-btn';
copyButton.tabIndex = 0;
copyButton.addEventListener('click', (event) => {
const subject = document.querySelector('[data-thread-perm-id]')?.textContent.trim() || '';
const detailsButton = message.querySelector('div[aria-haspopup="true"]:nth-of-type(2)');
detailsButton.click();
detailsButton.click();
const detailsTable = message.querySelector('[style^="visibility"] table');
const detailsTableClone = message.querySelector('[style^="visibility"] table').cloneNode(true);
detailsTableClone.querySelectorAll('a[href]').forEach((link) => link.remove());
const details = Array.from(detailsTableClone.rows).map(row => Array.from(row.children).map(cell => cell.innerText.trim()).join(" ")).join('\n');
const body = (message.querySelector('[class*=msg]') || message.querySelector('[data-hash]')?.previousSibling)?.innerText?.trim() || "";
const content =
`${subject}
${details}
${body}`;
navigator.clipboard.writeText(content);
detailsTableClone.remove();
toast('Copied', 1750);
});
message.querySelector('[role="button"]').insertAdjacentElement('afterend', copyButton);
message.dataset.ccgprocessed = true;
});
}).observe(document.documentElement, {
childList: true,
subtree: true
});
function toast(message, timeout = 3000) {
let t = document.createElement('div');
t.textContent = message;
t.style.cssText = 'position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); background-color: rgba(0, 0, 0, 0.7); color: white; padding: 10px 20px; border-radius: 5px; z-index: 9999;';
document.body.appendChild(t);
setTimeout(() => t.remove(), timeout);
};
})();