Gmail Domain Sorter

Sort Gmail emails by sender domain name

Size

5.0 KB

Version

1.0.3

Created

Apr 7, 2026

Updated

10 days ago

1// ==UserScript==
2// @name		Gmail Domain Sorter
3// @description		Sort Gmail emails by sender domain name
4// @version		1.0.3
5// @match		https://*.mail.google.com/*
6// @icon		https://ssl.gstatic.com/ui/v1/icons/mail/rfr/gmail.ico
7// ==/UserScript==
8(function() {
9    'use strict';
10
11    // Add custom styles
12    TM_addStyle(`
13        .domain-sort-btn {
14            background: #0b57d0;
15            color: white;
16            border: none;
17            padding: 8px 16px;
18            border-radius: 18px;
19            cursor: pointer;
20            font-size: 14px;
21            font-weight: 500;
22            margin-left: 8px;
23            transition: background 0.2s, box-shadow 0.2s;
24        }
25        
26        .domain-sort-btn:hover {
27            background: #0842a0;
28            box-shadow: 0 1px 3px rgba(0,0,0,0.2);
29        }
30        
31        .domain-sort-btn:active {
32            background: #062d6e;
33        }
34        
35        .domain-sort-btn.sorted {
36            background: #1a73e8;
37        }
38        
39        .domain-indicator {
40            font-size: 10px;
41            color: #5f6368;
42            margin-left: 4px;
43        }
44    `);
45
46    let isSorted = false;
47    let originalOrder = [];
48
49    // Extract domain from email address
50    function extractDomain(email) {
51        if (!email) return '';
52        const match = email.match(/@([^\s>]+)/);
53        return match ? match[1].toLowerCase() : '';
54    }
55
56    // Get all email rows
57    function getEmailRows() {
58        return Array.from(document.querySelectorAll('div.zA'));
59    }
60
61    // Sort emails by domain
62    function sortEmails() {
63        const container = document.querySelector('div.Nr.UI.S2.vy div.Nu.tf.aZ6 > div > div.aDP');
64        if (!container) {
65            console.log('Container not found');
66            return;
67        }
68
69        const emailRows = getEmailRows();
70        
71        if (emailRows.length === 0) {
72            console.log('No email rows found');
73            return;
74        }
75
76        // Store original order if not already stored
77        if (originalOrder.length === 0) {
78            originalOrder = [...emailRows];
79        }
80
81        if (isSorted) {
82            // Restore original order
83            originalOrder.forEach(row => {
84                container.appendChild(row);
85            });
86            isSorted = false;
87            updateButton();
88            console.log('Restored original order');
89            return;
90        }
91
92        // Sort by domain
93        const sortedRows = [...emailRows].sort((a, b) => {
94            const emailA = a.querySelector('span[data-hovercard-id]')?.getAttribute('data-hovercard-id') || '';
95            const emailB = b.querySelector('span[data-hovercard-id]')?.getAttribute('data-hovercard-id') || '';
96            const domainA = extractDomain(emailA);
97            const domainB = extractDomain(emailB);
98            return domainA.localeCompare(domainB);
99        });
100
101        // Re-append in sorted order
102        sortedRows.forEach(row => {
103            container.appendChild(row);
104        });
105
106        isSorted = true;
107        updateButton();
108        console.log('Sorted by domain');
109    }
110
111    // Update button state
112    function updateButton() {
113        const btn = document.querySelector('.domain-sort-btn');
114        if (btn) {
115            btn.textContent = isSorted ? 'Eredeti sorrend' : 'Domain szerinti rendezés';
116            btn.classList.toggle('sorted', isSorted);
117        }
118    }
119
120    // Create sort button
121    function createSortButton() {
122        // Check if button already exists
123        if (document.querySelector('.domain-sort-btn')) return;
124
125        // Find toolbar
126        const toolbar = document.querySelector('div.G-tF');
127        if (!toolbar) {
128            console.log('Toolbar not found');
129            return;
130        }
131
132        const btn = document.createElement('div');
133        btn.className = 'domain-sort-btn';
134        btn.setAttribute('role', 'button');
135        btn.setAttribute('tabindex', '0');
136        btn.textContent = 'Domain szerinti rendezés';
137        btn.onclick = sortEmails;
138        
139        // Make it keyboard accessible
140        btn.onkeydown = (e) => {
141            if (e.key === 'Enter' || e.key === ' ') {
142                e.preventDefault();
143                sortEmails();
144            }
145        };
146
147        // Insert as first child of toolbar
148        toolbar.insertBefore(btn, toolbar.firstChild);
149        console.log('Sort button added');
150    }
151
152    // Initialize
153    function init() {
154        console.log('Gmail Domain Sorter initialized');
155        
156        // Create button with delay to ensure Gmail is loaded
157        setTimeout(createSortButton, 1000);
158
159        // Observe DOM changes to re-add button if needed
160        const observer = new MutationObserver((mutations) => {
161            if (!document.querySelector('.domain-sort-btn')) {
162                createSortButton();
163            }
164        });
165
166        observer.observe(document.body, {
167            childList: true,
168            subtree: true
169        });
170    }
171
172    // Wait for Gmail to load
173    if (document.readyState === 'loading') {
174        document.addEventListener('DOMContentLoaded', init);
175    } else {
176        init();
177    }
178})();