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();
    });
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址