Email Extractor
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Email Extractor</title> <style> body { background: #000000; min-height: 100vh; font-family: Georgia, 'Times New Roman', Times, serif; font-weight: 300; color: #c084fc; margin: 0; padding: 1rem; line-height: 1.5; } body::before { content: ''; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: radial-gradient(circle at 20% 80%, rgba(192, 132, 252, 0.05) 0%, transparent 50%), radial-gradient(circle at 80% 20%, rgba(147, 51, 234, 0.05) 0%, transparent 50%), radial-gradient(circle at 40% 40%, rgba(168, 85, 247, 0.05) 0%, transparent 50%); pointer-events: none; z-index: -1; } .container { max-width: 800px; margin: 0 auto; padding: 1rem; } h1 { font-size: 1.2rem; md:font-size: 1.4rem; text-align: center; margin: 1rem 0 2rem 0; color: #c084fc; font-family: Georgia, serif; font-weight: 300; letter-spacing: 0.02em; text-shadow: 0 0 30px rgba(192,132,252,0.5); background: linear-gradient(to right, #d8b4fe, #c084fc, #a855f7); background-clip: text; -webkit-background-clip: text; -webkit-text-fill-color: transparent; } .glass-card { background: rgba(30, 30, 30, 0.8); backdrop-filter: blur(30px); border: 1px solid rgba(192, 132, 252, 0.2); box-shadow: 0 25px 45px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(192, 132, 252, 0.1); border-radius: 12px; padding: 1.5rem; margin-bottom: 1rem; position: relative; overflow: hidden; transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94); } .glass-card::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(192, 132, 252, 0.1), transparent); transition: left 0.8s ease; } .glass-card:hover::before { left: 100%; } .glass-card:hover { transform: translateY(-2px); box-shadow: 0 35px 60px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(192, 132, 252, 0.2); border-color: rgba(192, 132, 252, 0.3); } .info-box { background: rgba(40, 40, 40, 0.8); border: 1px solid rgba(192, 132, 252, 0.3); border-radius: 8px; padding: 1rem; margin-bottom: 1.5rem; font-size: 0.75rem; color: #a78bfa; font-family: Georgia, serif; font-weight: 300; } textarea { width: 100%; height: 150px; background: rgba(40, 40, 40, 0.8); color: #c084fc; font-family: Georgia, serif; font-weight: 300; font-size: 0.75rem; border: 2px solid rgba(192, 132, 252, 0.3); border-radius: 8px; padding: 0.75rem; box-sizing: border-box; resize: vertical; transition: all 0.3s ease; backdrop-filter: blur(10px); } textarea:focus { outline: none; background: rgba(50, 50, 50, 0.9); border-color: rgba(192, 132, 252, 0.6); box-shadow: 0 0 0 4px rgba(192, 132, 252, 0.1); } textarea::placeholder { color: #a78bfa; opacity: 0.7; } .controls { margin-top: 1rem; display: flex; flex-wrap: wrap; gap: 0.5rem; } .options { display: flex; align-items: center; gap: 1rem; margin-bottom: 1rem; flex-wrap: wrap; font-size: 0.75rem; } select, input[type="text"] { background: rgba(40, 40, 40, 0.8); color: #c084fc; border: 1px solid rgba(192, 132, 252, 0.3); border-radius: 4px; padding: 0.375rem; font-family: Georgia, serif; font-weight: 300; font-size: 0.75rem; transition: all 0.3s ease; } select:focus, input[type="text"]:focus { outline: none; border-color: rgba(192, 132, 252, 0.6); box-shadow: 0 0 0 2px rgba(192, 132, 252, 0.1); } input[type="text"]::placeholder { color: #a78bfa; opacity: 0.7; } input[type="text"][readonly] { background: rgba(60, 60, 60, 0.8); color: #a78bfa; } button { background: linear-gradient(135deg, #8b5cf6 0%, #a855f7 50%, #c084fc 100%); background-size: 200% 200%; color: #000000; border: none; border-radius: 6px; padding: 0.5rem 1rem; font-family: Georgia, serif; font-weight: 300; font-size: 0.75rem; cursor: pointer; transition: all 0.4s ease; position: relative; overflow: hidden; box-shadow: 0 4px 15px rgba(192, 132, 252, 0.3); } button:before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent); transition: left 0.6s; } button:hover { background-position: 100% 0%; transform: translateY(-1px) scale(1.02); box-shadow: 0 6px 20px rgba(192, 132, 252, 0.5); } button:hover:before { left: 100%; } button:active { transform: translateY(0px) scale(0.98); } button:disabled { opacity: 0.5; cursor: not-allowed; transform: none; } label { display: flex; align-items: center; gap: 0.5rem; font-size: 0.75rem; color: #c084fc; cursor: pointer; } input[type="checkbox"] { width: 14px; height: 14px; accent-color: #a855f7; } .display-info { display: flex; justify-content: space-between; align-items: center; margin-top: 1rem; font-size: 0.75rem; border-top: 1px solid rgba(192, 132, 252, 0.2); padding-top: 0.75rem; color: #a78bfa; } .status-text { color: #c084fc; } .error-status { color: #ef4444 !important; } .success-status { color: #10b981 !important; } .option-group { display: flex; align-items: center; gap: 0.5rem; } .option-group span { color: #a78bfa; font-size: 0.75rem; } @media (max-width: 768px) { body { padding: 0.5rem; } .container { padding: 0.5rem; } .glass-card { padding: 1rem; } .controls, .options { flex-direction: column; align-items: stretch; gap: 0.75rem; } .options { align-items: flex-start; } .option-group { width: 100%; justify-content: space-between; } button { width: 100%; justify-content: center; } .display-info { flex-direction: column; gap: 0.5rem; align-items: flex-start; } textarea { height: 120px; } } </style> </head> <body> <div class="container"> <h1>Email Extractor</h1> <div class="info-box"> > System ready for email extraction<br> > Paste raw data below and initiate extraction<br> > Duplicate detection enabled by default </div> <div class="glass-card"> <form name="extractor"> <textarea name="rawdata" placeholder="Copy text from any source and paste it here. Click EXTRACT to find all email addresses in the text."></textarea> <div class="options"> <div class="option-group"> <span>Separator:</span> <select name="sep" onchange="handleSepChange()"> <option value=", ">Comma</option> <option value="|">Pipe</option> <option value=" : ">Colon</option> <option value="new">New Line</option> <option value="other">Other</option> </select> <input type="text" name="othersep" size="6" oninput="checksep(this.value)" placeholder="Custom"> </div> <div class="option-group"> <span>Group:</span> <input type="text" size="6" name="groupby" onblur="numonly(this.value)" placeholder="No grouping"> <span>emails</span> </div> <label> <input type="checkbox" name="sort" id="sortbox"> Sort Alphabetically </label> <label> <input type="checkbox" name="rejectDuplicates" id="rejectDuplicatesBox"> Reject if Duplicates Found </label> </div> <div class="controls"> <button type="button" onclick="findEmail()">Extract</button> <button type="reset" onclick="resetForm()">Reset</button> <button type="button" onclick="highlight()">Select All</button> </div> <div class="display-info"> <span>Status: <span id="status" class="status-text">Ready</span></span> <span>Email count: <input name="count" size="8" readonly></span> </div> </form> </div> </div> <script> function handleSepChange() { const sepValue = document.extractor.sep.value; const otherSepInput = document.extractor.othersep; if (sepValue === "other") { otherSepInput.focus(); } } function checksep(value) { if (value && value.trim() !== "") { document.extractor.sep.value = "other"; } } function numonly(value) { if (value && value.trim() !== "" && isNaN(value)) { alert("Please enter a number or leave blank for no grouping."); document.extractor.groupby.focus(); return false; } return true; } function highlight() { document.extractor.rawdata.focus(); document.extractor.rawdata.select(); } function resetForm() { document.getElementById('status').textContent = 'Ready'; document.getElementById('status').className = 'status-text'; document.extractor.count.value = ''; } function findEmail() { const statusElement = document.getElementById('status'); statusElement.textContent = 'Processing...'; statusElement.className = 'status-text'; let email = "No email address detected"; let a = 0; let ingroup = 0; let separator = document.extractor.sep.value; const groupby = Math.round(document.extractor.groupby.value) || 0; const rejectDuplicates = document.extractor.rejectDuplicates.checked; // Handle separator selection if (separator === "new") { separator = "\n"; } else if (separator === "other") { separator = document.extractor.othersep.value || ", "; } // Extract emails using regex const rawemail = document.extractor.rawdata.value.match(/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+)/gi); if (!rawemail || rawemail.length === 0) { document.extractor.count.value = 0; document.extractor.rawdata.value = email; statusElement.textContent = 'No emails found'; statusElement.className = 'error-status'; return; } // Check for duplicates first if rejection is enabled if (rejectDuplicates) { const emailSet = new Set(); const duplicates = []; for (let i = 0; i < rawemail.length; i++) { const emailLower = rawemail[i].toLowerCase(); if (emailSet.has(emailLower)) { duplicates.push(rawemail[i]); } else { emailSet.add(emailLower); } } if (duplicates.length > 0) { document.extractor.count.value = 0; document.extractor.rawdata.value = `EXTRACTION REJECTED: Duplicates detected\n\nDuplicate emails found:\n${duplicates.join('\n')}\n\nPlease remove duplicates and try again.`; statusElement.textContent = 'Rejected - Duplicates found'; statusElement.className = 'error-status'; return; } } // Remove duplicates (case-insensitive) const seen = new Set(); const norepeat = []; for (let i = 0; i < rawemail.length; i++) { const emailLower = rawemail[i].toLowerCase(); if (!seen.has(emailLower)) { seen.add(emailLower); norepeat.push(rawemail[i]); } } // Sort if requested if (document.extractor.sort.checked) { norepeat.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())); } // Build output string email = ""; for (let k = 0; k < norepeat.length; k++) { if (ingroup !== 0) email += separator; email += norepeat[k]; ingroup++; // Group emails if a number is specified if (groupby > 0) { if (ingroup === groupby) { email += '\n\n'; ingroup = 0; } } } // Update results document.extractor.count.value = norepeat.length; document.extractor.rawdata.value = email; statusElement.textContent = 'Complete'; statusElement.className = 'success-status'; } // Initialize console.log('Email Extractor initialized successfully!'); </script> </body> </html>
Comments
Post a Comment