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.

  1. // ==UserScript==
  2. // @name Gmail Sender Shield
  3. // @name:es Gmail Escudo de Correos
  4. // @namespace http://tampermonkey.net/
  5. // @version 1.6
  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.
  7. // @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.
  8. // @author IgnaV
  9. // @match https://mail.google.com/*
  10. // @icon https://ssl.gstatic.com/ui/v1/icons/mail/rfr/gmail.ico
  11. // @license MIT
  12. // @grant GM_setValue
  13. // @grant GM_getValue
  14. // ==/UserScript==
  15.  
  16. (function() {
  17. 'use strict';
  18.  
  19. if (window.self !== window.top) return;
  20.  
  21. const userId = window.location.href.match(/\/u\/(\d+)\//)[1];
  22.  
  23. const addIcon = GM_getValue('addIcon', true);
  24. const addDomain = GM_getValue('addDomain', true);
  25. let allowedCommonDomains = GM_getValue('allowedDomains', []);
  26. let allowedUserDomains = GM_getValue('allowedUserDomains', {});
  27.  
  28. let userDomains = allowedUserDomains[userId] || [];
  29. allowedUserDomains[userId] = userDomains;
  30.  
  31. GM_setValue('addIcon', addIcon);
  32. GM_setValue('addDomain', addDomain);
  33. GM_setValue('allowedUserDomains', allowedUserDomains);
  34.  
  35. let allowedDomains = allowedCommonDomains.concat(userDomains);
  36. const hasDomains = allowedDomains.length !== 0;
  37.  
  38.  
  39. const channel = new BroadcastChannel('mi-canal');
  40. channel.onmessage = (event) => {
  41. refreshAllowedDomains();
  42. updateAllDomainStates();
  43. console.log('Mensaje recibido:', event.data);
  44. };
  45.  
  46. if (!addIcon && !addDomain && !hasDomains) return;
  47.  
  48. const processedElements = new Set();
  49.  
  50. function refreshAllowedDomains() {
  51. allowedCommonDomains = GM_getValue('allowedDomains', []);
  52. allowedUserDomains = GM_getValue('allowedUserDomains', {});
  53. userDomains = allowedUserDomains[userId] || [];
  54. allowedDomains = allowedCommonDomains.concat(userDomains);
  55. }
  56.  
  57. function addDomainContainer(element, email) {
  58. const domain = extractDomain(email);
  59. const domainContainer = document.createElement('div');
  60. domainContainer.className = 'domain-container';
  61. domainContainer.onclick = () => domainContainerEvent(domainContainer, email);
  62. updateDomainState(domainContainer, email);
  63.  
  64. addIconToContainer(domainContainer, domain);
  65. addDomainToContainer(domainContainer, domain);
  66. element.appendChild(domainContainer);
  67. return domainContainer;
  68. }
  69.  
  70. function updateDomainState(container, email) {
  71. const domain = extractDomain(email);
  72. container.classList.remove('not-allowed-domain', 'allowed-domain');
  73. if (allowedDomains.includes(email) || allowedDomains.includes(domain)) {
  74. container.classList.add('allowed-domain');
  75. } else {
  76. container.classList.add('not-allowed-domain');
  77. }
  78. }
  79.  
  80. function domainContainerEvent(domainContainer, email) {
  81. event.preventDefault();
  82. event.stopPropagation();
  83.  
  84. const domain = extractDomain(email);
  85.  
  86. let message;
  87. if (userDomains.includes(domain)) {
  88. userDomains.splice(userDomains.indexOf(domain), 1);
  89. allowedCommonDomains.push(domain);
  90. message = `+ Empresa (Todas las cuentas)`;
  91. } else if (allowedCommonDomains.includes(domain)) {
  92. allowedCommonDomains.splice(allowedCommonDomains.indexOf(domain), 1);
  93. userDomains.push(email);
  94. message = `+ Correo (Esta cuenta)`;
  95. } else if (userDomains.includes(email)) {
  96. userDomains.splice(userDomains.indexOf(email), 1);
  97. allowedCommonDomains.push(email);
  98. message = `+ Correo (Todas las cuentas)`;
  99. } else if (allowedCommonDomains.includes(email)) {
  100. allowedCommonDomains.splice(allowedCommonDomains.indexOf(email), 1);
  101. message = `Eliminado`;
  102. } else {
  103. userDomains.push(domain);
  104. message = `+ Empresa (Esta cuenta)`;
  105. }
  106.  
  107. allowedUserDomains[userId] = userDomains;
  108. GM_setValue('allowedUserDomains', allowedUserDomains);
  109. GM_setValue('allowedDomains', allowedCommonDomains);
  110. refreshAllowedDomains();
  111.  
  112. updateAllDomainStates();
  113.  
  114. showTooltip(domainContainer, message);
  115.  
  116. setTimeout(() => channel.postMessage(message), 200);
  117. };
  118.  
  119. function updateAllDomainStates() {
  120. const nameElements = document.querySelectorAll('.bA4, .bAK, .bAp');
  121. nameElements.forEach((element) => {
  122. const emailElement = element.querySelector('[email]');
  123. if (!emailElement) return;
  124.  
  125. const email = emailElement.getAttribute('email');
  126. const domain = extractDomain(email);
  127. const domainContainer = element.querySelector('.domain-container');
  128.  
  129. if (domainContainer) {
  130. updateDomainState(domainContainer, email);
  131. } else {
  132. addDomainContainer(element, email);
  133. }
  134. });
  135. }
  136.  
  137. function showTooltip(element, message) {
  138. const tooltip = document.createElement('span');
  139. tooltip.className = 'custom-tooltip';
  140. tooltip.textContent = message;
  141.  
  142. element.appendChild(tooltip);
  143. setTimeout(() => {
  144. if (element.contains(tooltip)) {
  145. element.removeChild(tooltip);
  146. }
  147. }, 3000);
  148. }
  149.  
  150. function addIconToContainer(domainContainer, domain) {
  151. const icon = document.createElement('img');
  152. icon.src = `https://www.google.com/s2/favicons?domain=${domain}`;
  153. icon.className = 'domain-icon';
  154. domainContainer.appendChild(icon);
  155. }
  156.  
  157. function addDomainToContainer(domainContainer, domain) {
  158. const domainSpan = document.createElement('span');
  159. domainSpan.className = 'domain-text';
  160. domainSpan.textContent = domain;
  161. domainContainer.appendChild(domainSpan);
  162. }
  163.  
  164. function addStyles(addIcon, addDomain, hasDomains) {
  165. const style = document.createElement('style');
  166. style.type = 'text/css';
  167. let css = ``;
  168. if (addIcon || addDomain) {
  169. css += `
  170. .bA4, .bAK, .bAp {
  171. padding-top: 9px;
  172. }
  173. .domain-container {
  174. display: flex;
  175. align-items: center;
  176. margin-top: -4px;
  177. font-size: 10px;
  178. color: #888;
  179. width: fit-content;
  180. height: 11px;
  181. padding: 1px 2px;
  182. }
  183. .domain-container:hover {
  184. background-color: #b1b1b1;
  185. }
  186. .domain-container.not-allowed-domain:hover {
  187. background-color: #e5afaf;
  188. }
  189. `;
  190. }
  191. if (addIcon) {
  192. css += `
  193. .domain-icon {
  194. width: 10px;
  195. height: 10px;
  196. margin-right: 3px;
  197. }
  198. `;
  199. }
  200. if (addDomain) {
  201. css += `
  202. .domain-text {
  203. white-space: nowrap;
  204. overflow: hidden;
  205. text-overflow: ellipsis;
  206. font-size: 10px;
  207. color: #888;
  208. color: inherit; /* Hereda el color del contenedor */
  209. }
  210. `;
  211. }
  212. if (hasDomains) {
  213. css += `
  214. .not-allowed-domain {
  215. background-color: #f8d7da;
  216. color: #721c24;
  217. }
  218. .allowed-domain {
  219. background-color: transparent;
  220. color: inherit;
  221. }
  222. .custom-tooltip {
  223. position: absolute;
  224. background-color: #000;
  225. color: #fff;
  226. padding: 4px;
  227. border-radius: 4px;
  228. font-size: 12px;
  229. white-space: nowrap;
  230. z-index: 1000;
  231. top: 40px;
  232. opacity: 0;
  233. transition: opacity 0.3s ease-in-out;
  234. }
  235. .custom-tooltip:has(+ .custom-tooltip) {
  236. display: none;
  237. }
  238. .domain-container:hover .custom-tooltip {
  239. opacity: 1;
  240. }
  241. `;
  242. }
  243. style.appendChild(document.createTextNode(css));
  244. document.head.appendChild(style);
  245. }
  246.  
  247. addStyles(addIcon, addDomain, hasDomains);
  248.  
  249. function addDomainBelowName() {
  250. const nameElements = document.querySelectorAll('.bA4, .bAK, .bAp');
  251.  
  252. nameElements.forEach((element) => {
  253. if (processedElements.has(element)) return;
  254.  
  255. const emailElement = element.querySelector('[email]');
  256. if (!emailElement) return;
  257.  
  258. const email = emailElement.getAttribute('email');
  259. const domain = extractDomain(email);
  260.  
  261. const domainElement = addDomainContainer(element, email);
  262.  
  263. processedElements.add(element);
  264. });
  265. }
  266.  
  267. function extractDomain(email) {
  268. const domainParts = email.split('@')[1].split('.');
  269. if (domainParts[domainParts.length - 2] === 'com') {
  270. return domainParts.slice(-3).join('.');
  271. }
  272. return domainParts.slice(-2).join('.');
  273. }
  274.  
  275. const observer = new MutationObserver((mutations) => {
  276. mutations.forEach(() => {
  277. addDomainBelowName();
  278. });
  279. });
  280.  
  281. observer.observe(document.body, {
  282. childList: true,
  283. subtree: true
  284. });
  285.  
  286. window.addEventListener('load', () => {
  287. addDomainBelowName();
  288. });
  289. })();

QingJ © 2025

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