Greasy Fork is available in English.

Gmail Sender Shield

Gmail Sender Shield enhances your Gmail experience by displaying sender domains and icons for quick identification and offering tools to highlight untrusted emails.

// ==UserScript==
// @name           Gmail Sender Shield
// @name:es        Gmail Escudo de Correos
// @namespace      http://tampermonkey.net/
// @version        1.6
// @description    Gmail Sender Shield enhances your Gmail experience by displaying sender domains and icons for quick identification and offering tools to highlight untrusted emails.
// @description:es Gmail Escudo de Correos mejora tu experiencia en Gmail mostrando los dominios e íconos de los remitentes para una identificación rápida y ofreciendo herramientas para resaltar correos no confiables.
// @author         IgnaV
// @match          https://mail.google.com/*
// @icon           https://ssl.gstatic.com/ui/v1/icons/mail/rfr/gmail.ico
// @license        MIT
// @grant          GM_setValue
// @grant          GM_getValue
// ==/UserScript==

(function() {
    'use strict';

    if (window.self !== window.top) return;

    const userId = window.location.href.match(/\/u\/(\d+)\//)[1];

    const addIcon = GM_getValue('addIcon', true);
    const addDomain = GM_getValue('addDomain', true);
    let allowedCommonDomains = GM_getValue('allowedDomains', []);
    let allowedUserDomains = GM_getValue('allowedUserDomains', {});

    let userDomains = allowedUserDomains[userId] || [];
    allowedUserDomains[userId] = userDomains;

    GM_setValue('addIcon', addIcon);
    GM_setValue('addDomain', addDomain);
    GM_setValue('allowedUserDomains', allowedUserDomains);

    let allowedDomains = allowedCommonDomains.concat(userDomains);
    const hasDomains = allowedDomains.length !== 0;


    const channel = new BroadcastChannel('mi-canal');
    channel.onmessage = (event) => {
        refreshAllowedDomains();
        updateAllDomainStates();
        console.log('Mensaje recibido:', event.data);
    };

    if (!addIcon && !addDomain && !hasDomains) return;

    const processedElements = new Set();

    function refreshAllowedDomains() {
        allowedCommonDomains = GM_getValue('allowedDomains', []);
        allowedUserDomains = GM_getValue('allowedUserDomains', {});
        userDomains = allowedUserDomains[userId] || [];
        allowedDomains = allowedCommonDomains.concat(userDomains);
    }

    function addDomainContainer(element, email) {
        const domain = extractDomain(email);
        const domainContainer = document.createElement('div');
        domainContainer.className = 'domain-container';
        domainContainer.onclick = () => domainContainerEvent(domainContainer, email);
        updateDomainState(domainContainer, email);

        addIconToContainer(domainContainer, domain);
        addDomainToContainer(domainContainer, domain);
        element.appendChild(domainContainer);
        return domainContainer;
    }

    function updateDomainState(container, email) {
        const domain = extractDomain(email);
        container.classList.remove('not-allowed-domain', 'allowed-domain');
        if (allowedDomains.includes(email) || allowedDomains.includes(domain)) {
            container.classList.add('allowed-domain');
        } else {
            container.classList.add('not-allowed-domain');
        }
    }

    function domainContainerEvent(domainContainer, email) {
        event.preventDefault();
        event.stopPropagation();

        const domain = extractDomain(email);

        let message;
        if (userDomains.includes(domain)) {
            userDomains.splice(userDomains.indexOf(domain), 1);
            allowedCommonDomains.push(domain);
            message = `+ Empresa (Todas las cuentas)`;
        } else if (allowedCommonDomains.includes(domain)) {
            allowedCommonDomains.splice(allowedCommonDomains.indexOf(domain), 1);
            userDomains.push(email);
            message = `+ Correo (Esta cuenta)`;
        } else if (userDomains.includes(email)) {
            userDomains.splice(userDomains.indexOf(email), 1);
            allowedCommonDomains.push(email);
            message = `+ Correo (Todas las cuentas)`;
        } else if (allowedCommonDomains.includes(email)) {
            allowedCommonDomains.splice(allowedCommonDomains.indexOf(email), 1);
            message = `Eliminado`;
        } else {
            userDomains.push(domain);
            message = `+ Empresa (Esta cuenta)`;
        }

        allowedUserDomains[userId] = userDomains;
        GM_setValue('allowedUserDomains', allowedUserDomains);
        GM_setValue('allowedDomains', allowedCommonDomains);
        refreshAllowedDomains();

        updateAllDomainStates();

        showTooltip(domainContainer, message);

        setTimeout(() => channel.postMessage(message), 200);
    };

    function updateAllDomainStates() {
        const nameElements = document.querySelectorAll('.bA4, .bAK, .bAp');
        nameElements.forEach((element) => {
            const emailElement = element.querySelector('[email]');
            if (!emailElement) return;

            const email = emailElement.getAttribute('email');
            const domain = extractDomain(email);
            const domainContainer = element.querySelector('.domain-container');

            if (domainContainer) {
                updateDomainState(domainContainer, email);
            } else {
                addDomainContainer(element, email);
            }
        });
    }

    function showTooltip(element, message) {
        const tooltip = document.createElement('span');
        tooltip.className = 'custom-tooltip';
        tooltip.textContent = message;

        element.appendChild(tooltip);
        setTimeout(() => {
            if (element.contains(tooltip)) {
                element.removeChild(tooltip);
            }
        }, 3000);
    }

    function addIconToContainer(domainContainer, domain) {
        const icon = document.createElement('img');
        icon.src = `https://www.google.com/s2/favicons?domain=${domain}`;
        icon.className = 'domain-icon';
        domainContainer.appendChild(icon);
    }

    function addDomainToContainer(domainContainer, domain) {
        const domainSpan = document.createElement('span');
        domainSpan.className = 'domain-text';
        domainSpan.textContent = domain;
        domainContainer.appendChild(domainSpan);
    }

    function addStyles(addIcon, addDomain, hasDomains) {
        const style = document.createElement('style');
        style.type = 'text/css';
        let css = ``;
        if (addIcon || addDomain) {
            css += `
                .bA4, .bAK, .bAp {
                    padding-top: 9px;
                }
                .domain-container {
                    display: flex;
                    align-items: center;
                    margin-top: -4px;
                    font-size: 10px;
                    color: #888;
                    width: fit-content;
                    height: 11px;
                    padding: 1px 2px;
                }
                .domain-container:hover {
                    background-color: #b1b1b1;
                }
                .domain-container.not-allowed-domain:hover {
                    background-color: #e5afaf;
                }
            `;
        }
        if (addIcon) {
            css += `
                .domain-icon {
                    width: 10px;
                    height: 10px;
                    margin-right: 3px;
                }
            `;
        }
        if (addDomain) {
            css += `
                .domain-text {
                    white-space: nowrap;
                    overflow: hidden;
                    text-overflow: ellipsis;
                    font-size: 10px;
                    color: #888;
                    color: inherit; /* Hereda el color del contenedor */
                }
            `;
        }
        if (hasDomains) {
            css += `
                .not-allowed-domain {
                    background-color: #f8d7da;
                    color: #721c24;
                }
                .allowed-domain {
                    background-color: transparent;
                    color: inherit;
                }
                .custom-tooltip {
                    position: absolute;
                    background-color: #000;
                    color: #fff;
                    padding: 4px;
                    border-radius: 4px;
                    font-size: 12px;
                    white-space: nowrap;
                    z-index: 1000;
                    top: 40px;
                    opacity: 0;
                    transition: opacity 0.3s ease-in-out;
                }
                .custom-tooltip:has(+ .custom-tooltip) {
                    display: none;
                }
                .domain-container:hover .custom-tooltip {
                    opacity: 1;
                }
            `;
        }
        style.appendChild(document.createTextNode(css));
        document.head.appendChild(style);
    }

    addStyles(addIcon, addDomain, hasDomains);

    function addDomainBelowName() {
        const nameElements = document.querySelectorAll('.bA4, .bAK, .bAp');

        nameElements.forEach((element) => {
            if (processedElements.has(element)) return;

            const emailElement = element.querySelector('[email]');
            if (!emailElement) return;

            const email = emailElement.getAttribute('email');
            const domain = extractDomain(email);

            const domainElement = addDomainContainer(element, email);

            processedElements.add(element);
        });
    }

    function extractDomain(email) {
        const domainParts = email.split('@')[1].split('.');
        if (domainParts[domainParts.length - 2] === 'com') {
            return domainParts.slice(-3).join('.');
        }
        return domainParts.slice(-2).join('.');
    }

    const observer = new MutationObserver((mutations) => {
        mutations.forEach(() => {
            addDomainBelowName();
        });
    });

    observer.observe(document.body, {
        childList: true,
        subtree: true
    });

    window.addEventListener('load', () => {
        addDomainBelowName();
    });
})();