?????????? ????????? - ??????????????? - /home/agenciai/public_html/php_mailer/index.php
???????
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>PHP Mailer with Unique Email Tags</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> <style> body { background: #f8f9fa; padding: 20px; } .login-container { max-width: 400px; margin: 100px auto; } .card { margin-bottom: 20px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); } .email-counter { font-size: 0.8rem; color: #6c757d; } .timer-display { font-size: 1.2rem; font-weight: bold; color: #0d6efd; padding: 5px 10px; borderRadius: 4px; background-color: #f8f9fa; border: 1px solid #dee2e6; } .tag-badge { cursor: pointer; margin: 2px; } .tag-badge:hover { opacity: 0.8; } .attachment-preview { max-height: 200px; overflow-y: auto; background-color: #f8f9fa; padding: 10px; borderRadius: 5px; border: 1px dashed #dee2e6; } .btn-gradient { background: linear-gradient(45deg, #007bff, #6610f2); color: white; border: none; } .btn-gradient:hover { background: linear-gradient(45deg, #0056b3, #4d08c1); color: white; } .success-banner { background: linear-gradient(45deg, #28a745, #20c997); color: white; padding: 15px; borderRadius: 8px; margin-bottom: 20px; text-align: center; box-shadow: 0 4px 6px rgba(0,0,0,0.1); } .error-banner { background: linear-gradient(45deg, #dc3545, #c82333); color: white; padding: 15px; borderRadius: 8px; margin-bottom: 20px; text-align: center; box-shadow: 0 4px 6px rgba(0,0,0,0.1); } .subject-container { position: relative; } .tag-help { position: absolute; right: 10px; top: 10px; font-size: 0.8rem; color: #6c757d; cursor: pointer; } .unique-tag-section { background-color: #f8f9fa; borderRadius: 8px; padding: 15px; margin-top: 15px; } .unique-tag-preview { font-family: monospace; background-color: #e9ecef; padding: 10px; borderRadius: 5px; margin-top: 10px; max-height: 100px; overflow-y: auto; } .unique-tag-badge { background: linear-gradient(45deg, #6f42c1, #d63384); cursor: pointer; } /* Progress Modal Styles */ .progress-modal .modal-content { borderRadius: 10px; box-shadow: 0 5px 20px rgba(0,0,0,0.15); } .progress-modal .modal-header { background: linear-gradient(45deg, #007bff, #6610f2); color: white; border-top-left-radius: 10px; border-top-right-radius: 10px; } .progress-container { height: 25px; borderRadius: 12px; overflow: hidden; background: #e9ecef; margin: 15px 0; } .progress-bar { transition: width 0.3s ease; } .email-details { background: #f8f9fa; borderRadius: 8px; padding: 12px; margin-top: 15px; font-size: 0.9rem; } .stats-box { background: #e9ecef; borderRadius: 8px; padding: 12px; text-align: center; } .stats-number { font-size: 1.5rem; font-weight: bold; color: #007bff; } .stats-label { font-size: 0.8rem; color: #6c757d; } .cancel-btn { background: linear-gradient(45deg, #dc3545, #c82333); color: white; border: none; } .cancel-btn:hover { background: linear-gradient(45deg, #bd2130, #a71e2a); color: white; } .completion-modal .modal-content { borderRadius: 10px; } .completion-modal .modal-header { border-bottom: none; } </style> </head> <body> <div class="container"> <div class="row"> <div class="col-12"> <!-- Login Form (shown if not logged in) --> <div id="loginForm" class="login-container" style="display: none;"> <div class="card"> <div class="card-header bg-primary text-white"> <h5 class="mb-0">Login to PHP Mailer</h5> </div> <div class="card-body"> <form id="loginFormElement" method="POST"> <div class="mb-3"> <label class="form-label">Password</label> <input type="password" class="form-control" name="password" id="password" required> </div> <div class="d-grid"> <button type="submit" class="btn btn-gradient btn-lg"> <i class="fas fa-sign-in-alt me-2"></i>Login </button> </div> </form> </div> </div> </div> <!-- Main App (shown if logged in) --> <div id="mainApp"> <div class="d-flex justify-content-between align-items-center mb-4"> <h1>📧 PHP Mailer with Unique Email Tags</h1> <a href="#" onclick="logout()" class="btn btn-outline-secondary">Logout</a> </div> <!-- Error Message --> <div class="error-banner" id="errorBanner" style="display: none;"> <h4><i class="fas fa-exclamation-circle"></i> Error</h4> <p id="errorMessage"></p> </div> <!-- Success Message --> <div class="success-banner" id="successBanner" style="display: none;"> <h4><i class="fas fa-check-circle"></i> Emails Sent Successfully!</h4> <p>Your message has been sent. You can review the details below or send again.</p> </div> <!-- Send Email Card --> <div class="card"> <div class="card-header bg-primary text-white"> <h5 class="mb-0">Send Email with Attachment</h5> </div> <div class="card-body"> <form action="send.php" method="POST" id="emailForm" enctype="multipart/form-data"> <div class="mb-3"> <label class="form-label">To Emails (one per line, up to 1000)</label> <textarea class="form-control" name="to_emails" id="to_emails" rows="4" required placeholder="Enter one email address per line. Maximum 1000 emails.">john@example.com jane@example.com mike@example.com</textarea> <div class="email-counter mt-1"> <span id="emailCount">3</span> email(s) entered (max 1000) </div> </div> <div class="mb-3 subject-container"> <label class="form-label">Subject</label> <input type="text" class="form-control" name="subject" id="subject" value="Hello {{name}}!" required> <span class="tag-help" title="Click on tags below to insert into subject">Tags work here too!</span> </div> <div class="mb-3"> <label class="form-label">Message</label> <textarea class="form-control" name="message" id="message" rows="4" required>Hi {{name}}, This is a test email sent from our PHP mailer system. Best regards, Mailer Team</textarea> </div> <!-- Dynamic Tags --> <div class="card mt-3"> <div class="card-header bg-info text-white"> <h6 class="mb-0">🏷️ Available Dynamic Tags</h6> </div> <div class="card-body"> <div class="row"> <div class="col-md-6"> <h6>Recipient Tags:</h6> <div class="d-flex flex-wrap gap-2 mb-3"> <span class="badge bg-primary tag-badge" onclick="insertTag('{{email}}')">{{email}}</span> <span class="badge bg-primary tag-badge" onclick="insertTag('{{name}}')">{{name}}</span> <span class="badge bg-primary tag-badge" onclick="insertTag('{{username}}')">{{username}}</span> <span class="badge bg-primary tag-badge" onclick="insertTag('{{domain}}')">{{domain}}</span> <span class="badge bg-primary tag-badge" onclick="insertTag('{{company}}')">{{company}}</span> </div> </div> <div class="col-md-6"> <h6>System Tags:</h6> <div class="d-flex flex-wrap gap-2 mb-3"> <span class="badge bg-success tag-badge" onclick="insertTag('{{date}}')">{{date}}</span> <span class="badge bg-success tag-badge" onclick="insertTag('{{time}}')">{{time}}</span> <span class="badge bg-success tag-badge" onclick="insertTag('{{datetime}}')">{{datetime}}</span> <span class="badge bg-warning tag-badge" onclick="insertTag('{{random_number}}')">{{random_number}}</span> <span class="badge bg-warning tag-badge" onclick="insertTag('{{random_string}}')">{{random_string}}</span> <span class="badge bg-warning tag-badge" onclick="insertTag('{{random_number_6}}')">{{random_number_6}}</span> <span class="badge bg-warning tag-badge" onclick="insertTag('{{random_string_12}}')">{{random_string_12}}</span> </div> </div> </div> <div class="form-text"> Click on any tag to insert it into your subject or message. Tags will be replaced with actual values when sending. </div> </div> </div> <!-- Attachment Section --> <div class="card mt-3"> <div class="card-header bg-success text-white"> <h6 class="mb-0">📎 File Attachment</h6> </div> <div class="card-body"> <div class="mb-3"> <label class="form-label">Upload File</label> <input type="file" class="form-control" name="attachment" id="attachment"> <div class="form-text"> Select a file to attach to your email. Max size: 5MB </div> </div> <div class="mb-3"> <label class="form-label">Custom File Name (optional)</label> <input type="text" class="form-control" name="custom_filename" id="custom_filename" placeholder="Leave empty to use original filename"> <div class="form-text"> You can use tags like {{email}} or {{name}} in the filename </div> </div> <!-- HTML Encryption Section --> <div class="card mt-3"> <div class="card-header bg-info text-white"> <h6 class="mb-0"><i class="fas fa-lock me-2"></i>HTML Encryption Options</h6> </div> <div class="card-body"> <div class="mb-3"> <label class="form-label">HTML Encryption Method</label> <select class="form-select" name="html_encryption_method" id="html_encryption_method"> <option value="none">No Encryption</option> <option value="advanced">Advanced Obfuscation</option> <option value="obfuscate">Basic Obfuscation</option> <option value="zerowidth">Zero-Width Characters</option> <option value="base64">Base64 Encoding</option> <option value="aes">AES Encryption</option> </select> </div> <div class="mb-3" id="zeroFontMessageContainer" style="display: none;"> <label class="form-label">Zero-Width Hidden Message</label> <input type="text" class="form-control" name="zero_font_message" placeholder="Enter message to hide with zero-width characters"> </div> <div class="mb-3" id="aesKeyContainer" style="display: none;"> <label class="form-label">AES Encryption Key</label> <input type="text" class="form-control" name="aes_encryption_key" placeholder="Enter encryption key (leave empty for auto-generated)"> </div> <div class="form-text"> These options apply to HTML attachments only. Select an encryption method to protect your content. </div> </div> </div> <!-- Unique Email Tag Section --> <div class="unique-tag-section"> <h6><i class="fas fa-key me-2"></i>Unique Email Tag Options</h6> <div class="form-check form-switch mb-2"> <input class="form-check-input" type="checkbox" id="enableUniqueTags" name="enable_unique_tags" checked> <label class="form-check-label" for="enableUniqueTags">Enable unique email tags in attachments</label> </div> <div class="form-text mb-2"> When enabled, each recipient will get a unique email tag in the attachment that maps to their actual email address. </div> <div class="mb-2"> <span class="badge unique-tag-badge tag-badge" onclick="insertTag('{{unique_email}}')">{{unique_email}}</span> <span class="form-text">Use this tag in your attachment content</span> </div> <div class="unique-tag-preview" id="uniqueTagPreview"> <small>Preview: {{email8291}}, {{email4723}}, {{email1567}}</small> </div> </div> <div class="attachment-preview mt-3" id="attachmentPreview"> <p class="text-center text-muted">No file selected</p> </div> </div> </div> <!-- Email Timer --> <div class="card mt-3"> <div class="card-header bg-warning text-dark"> <h6 class="mb-0">⏰ Email Timer</h6> </div> <div class="card-body"> <div class="mb-3"> <label class="form-label">Delay Between Emails (seconds)</label> <input type="number" class="form-control" name="email_delay" id="email_delay" min="0" max="3600" value="5" required> <div class="form-text"> Time to wait between sending each email. Use 0 for no delay. </div> </div> <div class="d-flex align-items-center"> <span class="me-2">Estimated sending time:</span> <span class="timer-display" id="timeEstimate">15 seconds</span> </div> </div> </div> <div class="d-grid mt-3"> <button type="submit" class="btn btn-gradient btn-lg"> <i class="fas fa-paper-plane me-2"></i>Send Emails </button> </div> </form> </div> </div> </div> </div> </div> </div> <!-- Progress Modal --> <div class="modal fade progress-modal" id="progressModal" tabindex="-1" aria-hidden="true"> <div class="modal-dialog modal-dialog-centered"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title"><i class="fas fa-paper-plane me-2"></i>Sending Emails</h5> </div> <div class="modal-body"> <div class="text-center mb-3"> <div class="spinner-border text-primary mb-2" role="status"> <span class="visually-hidden">Loading...</span> </div> <p id="progressStatus">Initializing...</p> </div> <div class="progress-container"> <div class="progress-bar progress-bar-striped progress-bar-animated bg-primary" role="progressbar" style="width: 0%" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" id="sendingProgressBar"></div> </div> <div class="email-details"> <h6>Current Email:</h6> <p id="currentEmail" class="mb-0 text-truncate">Preparing to send...</p> </div> <div class="row mt-3"> <div class="col-4"> <div class="stats-box"> <div class="stats-number" id="totalEmails">0</div> <div class="stats-label">Total</div> </div> </div> <div class="col-4"> <div class="stats-box"> <div class="stats-number text-success" id="sentEmails">0</div> <div class="stats-label">Sent</div> </div> </div> <div class="col-4"> <div class="stats-box"> <div class="stats-number text-danger" id="failedEmails">0</div> <div class="stats-label">Failed</div> </div> </div> </div> </div> <div class="modal-footer"> <button type="button" class="btn cancel-btn" id="cancelSending"> <i class="fas fa-times me-2"></i>Cancel Sending </button> </div> </div> </div> </div> <!-- Completion Modal --> <div class="modal fade completion-modal" id="completionModal" tabindex="-1" aria-hidden="true"> <div class="modal-dialog modal-dialog-centered"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title"><i class="fas fa-check-circle me-2 text-success"></i>Sending Complete</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body text-center"> <i class="fas fa-check-circle text-success mb-3" style="font-size: 3rem;"></i> <h4 id="completionMessage">Emails sent successfully!</h4> <div class="row mt-4"> <div class="col-4"> <div class="stats-box"> <div class="stats-number" id="completeTotal">0</div> <div class="stats-label">Total</div> </div> </div> <div class="col-4"> <div class="stats-box"> <div class="stats-number text-success" id="completeSent">0</div> <div class="stats-label">Sent</div> </div> </div> <div class="col-4"> <div class="stats-box"> <div class="stats-number text-danger" id="completeFailed">0</div> <div class="stats-label">Failed</div> </div> </div> </div> <div id="errorDetails" class="mt-3 p-3 bg-light rounded" style="display: none;"> <h6>Error Details:</h6> <ul id="errorList" class="text-start mb-0 ps-3"></ul> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button> <button type="button" class="btn btn-primary" onclick="location.reload()">Send More</button> </div> </div> </div> </div> <!-- Bootstrap & jQuery JS --> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> <script> // Check if user is logged in function checkLoginStatus() { $.ajax({ url: 'check_login.php', type: 'GET', success: function(response) { if (response === 'logged_in') { $('#loginForm').hide(); $('#mainApp').show(); } else { $('#loginForm').show(); $('#mainApp').hide(); } }, error: function() { $('#loginForm').show(); $('#mainApp').hide(); } }); } // Handle login form submission $('#loginFormElement').on('submit', function(e) { e.preventDefault(); const formData = new FormData(this); $.ajax({ url: 'login.php', type: 'POST', data: formData, processData: false, contentType: false, success: function(response) { if (response === 'success') { $('#loginForm').hide(); $('#mainApp').show(); } else { $('#errorMessage').text('Invalid password. Please try again.'); $('#errorBanner').show(); } }, error: function() { $('#errorMessage').text('Login failed. Please try again.'); $('#errorBanner').show(); } }); }); // Logout function function logout() { $.ajax({ url: 'logout.php', type: 'GET', success: function() { $('#loginForm').show(); $('#mainApp').hide(); } }); } // Function to insert tag into message or subject function insertTag(tag) { // Determine which field has focus const activeElement = document.activeElement; let targetField; if (activeElement.id === 'subject' || activeElement.id === 'message' || activeElement.id === 'custom_filename') { targetField = activeElement; } else { // Default to message field if no relevant field is focused targetField = document.getElementById('message'); } const startPos = targetField.selectionStart; const endPos = targetField.selectionEnd; const currentValue = targetField.value; // Insert tag at cursor position or replace selection targetField.value = currentValue.substring(0, startPos) + tag + currentValue.substring(endPos, currentValue.length); // Set cursor position after inserted tag targetField.selectionStart = startPos + tag.length; targetField.selectionEnd = startPos + tag.length; targetField.focus(); } // File attachment preview document.getElementById('attachment').addEventListener('change', function(e) { const file = e.target.files[0]; const preview = document.getElementById('attachmentPreview'); if (file) { if (file.size > 5 * 1024 * 1024) { preview.innerHTML = '<p class="text-danger">File is too large. Max size is 5MB.</p>'; this.value = ''; return; } const fileType = file.type; let previewText = ''; if (fileType.startsWith('image/')) { previewText = `<p><strong>Image File:</strong> ${file.name}</p><p>Size: ${(file.size/1024).toFixed(2)} KB</p>`; } else if (fileType === 'text/plain' || fileType === 'application/pdf') { previewText = `<p><strong>Document:</strong> ${file.name}</p><p>Size: ${(file.size/1024).toFixed(2)} KB</p>`; } else { previewText = `<p><strong>File:</strong> ${file.name}</p><p>Type: ${fileType || 'Unknown'}</p><p>Size: ${(file.size/1024).toFixed(2)} KB</p>`; } preview.innerHTML = previewText; } else { preview.innerHTML = '<p class="text-center text-muted">No file selected</p>'; } }); // Update unique tag preview function updateUniqueTagPreview() { const emails = document.getElementById('to_emails').value.split('\n') .map(email => email.trim()) .filter(email => email.length > 0 && email.includes('@')); let previewHtml = ''; if (emails.length > 0) { // Generate sample unique tags const sampleTags = emails.slice(0, 3).map(() => { const randomNum = Math.floor(1000 + Math.random() * 9000); return `{{email${randomNum}}}`; }); previewHtml = `<small>Preview: ${sampleTags.join(', ')}</small>`; } else { previewHtml = '<small>Enter emails above to see preview</small>'; } document.getElementById('uniqueTagPreview').innerHTML = previewHtml; } // Email counter and timer functionality document.addEventListener('DOMContentLoaded', function() { // Check login status on page load checkLoginStatus(); const emailTextarea = document.getElementById('to_emails'); const emailCount = document.getElementById('emailCount'); const delayInput = document.getElementById('email_delay'); const timeEstimate = document.getElementById('timeEstimate'); // Initialize unique tag preview updateUniqueTagPreview(); // Check if we have saved form data const savedFormData = localStorage.getItem('emailFormData'); if (savedFormData) { const formData = JSON.parse(savedFormData); document.getElementById('to_emails').value = formData.to_emails || ''; document.getElementById('subject').value = formData.subject || ''; document.getElementById('message').value = formData.message || ''; document.getElementById('custom_filename').value = formData.custom_filename || ''; document.getElementById('email_delay').value = formData.email_delay || '5'; // Show success banner if we have a recent submission if (formData.lastSubmitted) { const timeDiff = (Date.now() - formData.lastSubmitted) / 1000 / 60; // in minutes if (timeDiff < 10) { // Show banner if submission was less than 10 minutes ago document.getElementById('successBanner').style.display = 'block'; } } updateEmailCountAndEstimate(); updateUniqueTagPreview(); } // Count emails and update estimate function updateEmailCountAndEstimate() { const emails = emailTextarea.value.split('\n') .map(email => email.trim()) .filter(email => email.length > 0 && email.includes('@')); const validEmails = emails.filter(email => { // Simple email validation const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return re.test(email); }); emailCount.textContent = validEmails.length; // Calculate time estimate const delay = parseInt(delayInput.value) || 0; const totalSeconds = validEmails.length * delay; if (totalSeconds < 60) { timeEstimate.textContent = totalSeconds + ' seconds'; } else { const minutes = Math.floor(totalSeconds / 60); const seconds = totalSeconds % 60; timeEstimate.textContent = minutes + ' min ' + seconds + ' sec'; } // Update unique tag preview updateUniqueTagPreview(); } // Save form data to localStorage function saveFormData() { const formData = { to_emails: document.getElementById('to_emails').value, subject: document.getElementById('subject').value, message: document.getElementById('message').value, custom_filename: document.getElementById('custom_filename').value, email_delay: document.getElementById('email_delay').value, lastUpdated: Date.now() }; localStorage.setItem('emailFormData', JSON.stringify(formData)); } // Progress tracking variables let progressInterval; let isSending = false; // Validate email count on form submit document.getElementById('emailForm').addEventListener('submit', function(e) { const emails = emailTextarea.value.split('\n') .map(email => email.trim()) .filter(email => email.length > 0 && email.includes('@')); if (emails.length > 1000) { e.preventDefault(); alert('Maximum 1000 emails allowed. You have ' + emails.length + ' emails.'); return false; } const attachment = document.getElementById('attachment').files[0]; if (attachment && attachment.size > 5 * 1024 * 1024) { e.preventDefault(); alert('File size exceeds the 5MB limit. Please choose a smaller file.'); return false; } // Save form data with submission timestamp const formData = { to_emails: document.getElementById('to_emails').value, subject: document.getElementById('subject').value, message: document.getElementById('message').value, custom_filename: document.getElementById('custom_filename').value, email_delay: document.getElementById('email_delay').value, enable_unique_tags: document.getElementById('enableUniqueTags').checked ? 1 : 0, lastSubmitted: Date.now() }; localStorage.setItem('emailFormData', JSON.stringify(formData)); // Show progress modal const progressModal = new bootstrap.Modal(document.getElementById('progressModal')); progressModal.show(); isSending = true; // Start checking progress startProgressChecking(); // Submit the form via AJAX const formDataObj = new FormData(this); formDataObj.append('enable_unique_tags', document.getElementById('enableUniqueTags').checked ? '1' : '0'); $.ajax({ url: 'send.php', type: 'POST', data: formDataObj, processData: false, contentType: false, success: function(response) { isSending = false; clearInterval(progressInterval); // Hide progress modal progressModal.hide(); // Show completion modal showCompletionModal(); }, error: function(xhr, status, error) { isSending = false; clearInterval(progressInterval); // Hide progress modal progressModal.hide(); // Show error in completion modal $('#completionMessage').html('Error sending emails!'); $('#completionMessage').removeClass('text-success').addClass('text-danger'); $('#errorDetails').show(); $('#errorList').html('<li>' + error + '</li>'); const completionModal = new bootstrap.Modal(document.getElementById('completionModal')); completionModal.show(); } }); // Prevent default form submission e.preventDefault(); }); // Cancel sending button $('#cancelSending').on('click', function() { if (confirm('Are you sure you want to cancel sending?')) { isSending = false; clearInterval(progressInterval); // Send cancel request to server $.get('send.php?cancel=1', function() { $('#progressModal').modal('hide'); alert('Sending cancelled.'); }); } }); // Start checking progress function startProgressChecking() { progressInterval = setInterval(function() { if (!isSending) return; $.getJSON('send.php?progress=1', function(data) { updateProgressUI(data); }).fail(function() { console.log('Progress check failed'); }); }, 1000); // Check every second } // Update progress UI function updateProgressUI(data) { if (data.status === 'completed') { isSending = false; clearInterval(progressInterval); return; } // Update progress bar const progressPercent = data.total > 0 ? Math.round((data.sent + data.failed) / data.total * 100) : 0; $('#sendingProgressBar').css('width', progressPercent + '%').attr('aria-valuenow', progressPercent); // Update status text $('#progressStatus').text(data.status); $('#currentEmail').text(data.current); // Update counters $('#totalEmails').text(data.total); $('#sentEmails').text(data.sent); $('#failedEmails').text(data.failed); } // Show completion modal function showCompletionModal() { // Get final progress data $.getJSON('send.php?progress=1', function(data) { $('#completeTotal').text(data.total); $('#completeSent').text(data.sent); $('#completeFailed').text(data.failed); if (data.failed > 0) { $('#completionMessage').html('Sending completed with <span class="text-danger">' + data.failed + '</span> failures!'); if (data.errors && data.errors.length > 0) { $('#errorDetails').show(); let errorHtml = ''; data.errors.slice(0, 5).forEach(error => { errorHtml += '<li>' + error + '</li>'; }); if (data.errors.length > 5) { errorHtml += '<li>... and ' + (data.errors.length - 5) + ' more errors</li>'; } $('#errorList').html(errorHtml); } } else { $('#completionMessage').html('All emails sent successfully!'); $('#errorDetails').hide(); } const completionModal = new bootstrap.Modal(document.getElementById('completionModal')); completionModal.show(); }); } // Add event listeners emailTextarea.addEventListener('input', function() { updateEmailCountAndEstimate(); saveFormData(); }); delayInput.addEventListener('input', function() { updateEmailCountAndEstimate(); saveFormData(); }); document.getElementById('subject').addEventListener('input', saveFormData); document.getElementById('message').addEventListener('input', saveFormData); document.getElementById('custom_filename').addEventListener('input', saveFormData); document.getElementById('enableUniqueTags').addEventListener('change', updateUniqueTagPreview); // Initial update updateEmailCountAndEstimate(); }); // Show/hide encryption options based on selection document.getElementById('html_encryption_method').addEventListener('change', function() { const method = this.value; document.getElementById('zeroFontMessageContainer').style.display = (method === 'zerowidth') ? 'block' : 'none'; document.getElementById('aesKeyContainer').style.display = (method === 'aes') ? 'block' : 'none'; }); </script> </body> </html>
| ver. 1.6 |
Github
|
.
| PHP 8.2.30 | ??????????? ?????????: 0 |
proxy
|
phpinfo
|
???????????