-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmailto-decoder.js
More file actions
93 lines (78 loc) · 3.1 KB
/
mailto-decoder.js
File metadata and controls
93 lines (78 loc) · 3.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/**
* Mailto Decoder
* Converts obfuscated email spans into functional mailto links
* This prevents email addresses from being visible in raw source code
*/
(function() {
'use strict';
function decodeMailto() {
// Find all obfuscated mailto elements
const obfuscatedElements = document.querySelectorAll('.mailto-obfuscated');
obfuscatedElements.forEach(element => {
// Skip if already processed
if (element.dataset.processed === 'true') return;
// Extract encoded email parts
const user = element.dataset.user;
const domain = element.dataset.domain;
if (!user || !domain) return;
// Decode email parts
const decodedUser = atob(user);
const decodedDomain = atob(domain);
const email = `${decodedUser}@${decodedDomain}`;
// Build mailto URL
let mailtoUrl = `mailto:${email}`;
const params = [];
// Add optional parameters
if (element.dataset.subject) {
params.push(`subject=${encodeURIComponent(atob(element.dataset.subject))}`);
}
if (element.dataset.body) {
params.push(`body=${encodeURIComponent(atob(element.dataset.body))}`);
}
if (element.dataset.cc) {
params.push(`cc=${encodeURIComponent(atob(element.dataset.cc))}`);
}
if (element.dataset.bcc) {
params.push(`bcc=${encodeURIComponent(atob(element.dataset.bcc))}`);
}
if (params.length > 0) {
mailtoUrl += '?' + params.join('&');
}
// Create the actual link
const link = document.createElement('a');
link.href = mailtoUrl;
link.className = 'mailto-link';
link.title = element.title || 'Email';
// Copy over the content (encoded email display)
link.innerHTML = element.innerHTML;
// Replace the span with the link
element.parentNode.replaceChild(link, element);
// Mark as processed
link.dataset.processed = 'true';
});
}
// Run on DOM ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', decodeMailto);
} else {
decodeMailto();
}
// Also run on dynamic content updates (for AJAX loaded content)
if (typeof MutationObserver !== 'undefined') {
const observer = new MutationObserver(function(mutations) {
let shouldRun = false;
mutations.forEach(function(mutation) {
if (mutation.addedNodes.length > 0) {
shouldRun = true;
}
});
if (shouldRun) {
decodeMailto();
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
}
})();