sqibhe commited on
Commit
6a835b3
·
verified ·
1 Parent(s): e61c957

Add 3 files

Browse files
Files changed (3) hide show
  1. README.md +7 -5
  2. index.html +1277 -19
  3. prompts.txt +0 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Email Validation
3
- emoji: 📈
4
- colorFrom: indigo
5
- colorTo: red
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: email-validation
3
+ emoji: 🐳
4
+ colorFrom: red
5
+ colorTo: yellow
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,1277 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Advanced Email Validation Bot</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
9
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script>
10
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
11
+ <style>
12
+ .dropzone {
13
+ border: 2px dashed #4b5563;
14
+ border-radius: 0.5rem;
15
+ transition: all 0.3s ease;
16
+ }
17
+ .dropzone.active {
18
+ border-color: #3b82f6;
19
+ background-color: rgba(59, 130, 246, 0.05);
20
+ }
21
+ .progress-bar {
22
+ transition: width 0.3s ease;
23
+ }
24
+ .tooltip {
25
+ position: relative;
26
+ display: inline-block;
27
+ }
28
+ .tooltip .tooltip-text {
29
+ visibility: hidden;
30
+ width: 200px;
31
+ background-color: #1f2937;
32
+ color: #fff;
33
+ text-align: center;
34
+ border-radius: 6px;
35
+ padding: 5px;
36
+ position: absolute;
37
+ z-index: 1;
38
+ bottom: 125%;
39
+ left: 50%;
40
+ margin-left: -100px;
41
+ opacity: 0;
42
+ transition: opacity 0.3s;
43
+ }
44
+ .tooltip:hover .tooltip-text {
45
+ visibility: visible;
46
+ opacity: 1;
47
+ }
48
+ .status-badge {
49
+ padding: 0.25rem 0.5rem;
50
+ border-radius: 0.25rem;
51
+ font-size: 0.75rem;
52
+ font-weight: 600;
53
+ text-transform: uppercase;
54
+ }
55
+ .status-valid {
56
+ background-color: #d1fae5;
57
+ color: #065f46;
58
+ }
59
+ .status-invalid {
60
+ background-color: #fee2e2;
61
+ color: #b91c1c;
62
+ }
63
+ .status-duplicate {
64
+ background-color: #fef3c7;
65
+ color: #92400e;
66
+ }
67
+ .status-typo {
68
+ background-color: #dbeafe;
69
+ color: #1e40af;
70
+ }
71
+ .status-unknown {
72
+ background-color: #e5e7eb;
73
+ color: #4b5563;
74
+ }
75
+ .status-undeliverable {
76
+ background-color: #f5f5f4;
77
+ color: #57534e;
78
+ }
79
+ .status-mx {
80
+ background-color: #ede9fe;
81
+ color: #5b21b6;
82
+ }
83
+ .fade-in {
84
+ animation: fadeIn 0.5s ease-in;
85
+ }
86
+ @keyframes fadeIn {
87
+ from { opacity: 0; }
88
+ to { opacity: 1; }
89
+ }
90
+ .insight-card {
91
+ transition: all 0.3s ease;
92
+ }
93
+ .insight-card:hover {
94
+ transform: translateY(-2px);
95
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
96
+ }
97
+ </style>
98
+ </head>
99
+ <body class="bg-gray-50 min-h-screen">
100
+ <div class="container mx-auto px-4 py-8 max-w-6xl">
101
+ <div class="text-center mb-8">
102
+ <h1 class="text-3xl font-bold text-gray-800 mb-2">Advanced Email Validation Bot</h1>
103
+ <p class="text-gray-600">Upload your Excel file to validate and clean email addresses</p>
104
+ </div>
105
+
106
+ <div class="bg-white rounded-lg shadow-md p-6 mb-8">
107
+ <div id="upload-section">
108
+ <div class="dropzone p-8 text-center cursor-pointer" id="dropzone">
109
+ <div class="flex flex-col items-center justify-center">
110
+ <i class="fas fa-file-excel text-4xl text-blue-500 mb-4"></i>
111
+ <h3 class="text-lg font-medium text-gray-700 mb-2">Drag & Drop your Excel file here</h3>
112
+ <p class="text-gray-500 mb-4">or</p>
113
+ <label for="file-upload" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-md cursor-pointer transition duration-300">
114
+ <i class="fas fa-upload mr-2"></i> Browse Files
115
+ </label>
116
+ <input id="file-upload" type="file" accept=".xlsx, .xls, .csv" class="hidden">
117
+ </div>
118
+ </div>
119
+ <div class="mt-4 text-sm text-gray-500">
120
+ <p>Supported formats: .xlsx, .xls, .csv</p>
121
+ <p>File should contain at least one column with email addresses</p>
122
+ </div>
123
+ </div>
124
+
125
+ <div id="processing-section" class="hidden">
126
+ <div class="flex items-center mb-4">
127
+ <div class="w-8 h-8 rounded-full bg-blue-100 flex items-center justify-center mr-3">
128
+ <i class="fas fa-cog text-blue-500 animate-spin"></i>
129
+ </div>
130
+ <h3 class="text-lg font-medium text-gray-700">Processing your file...</h3>
131
+ </div>
132
+
133
+ <div class="mb-4">
134
+ <div class="flex justify-between text-sm text-gray-600 mb-1">
135
+ <span>Progress</span>
136
+ <span id="progress-percent">0%</span>
137
+ </div>
138
+ <div class="w-full bg-gray-200 rounded-full h-2.5">
139
+ <div id="progress-bar" class="progress-bar bg-blue-600 h-2.5 rounded-full" style="width: 0%"></div>
140
+ </div>
141
+ </div>
142
+
143
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-4">
144
+ <div class="bg-gray-50 p-4 rounded-lg">
145
+ <div class="text-sm text-gray-500 mb-1">Emails Processed</div>
146
+ <div class="text-2xl font-bold text-gray-800" id="processed-count">0</div>
147
+ </div>
148
+ <div class="bg-gray-50 p-4 rounded-lg">
149
+ <div class="text-sm text-gray-500 mb-1">Valid Emails</div>
150
+ <div class="text-2xl font-bold text-green-600" id="valid-count">0</div>
151
+ </div>
152
+ <div class="bg-gray-50 p-4 rounded-lg">
153
+ <div class="text-sm text-gray-500 mb-1">Issues Found</div>
154
+ <div class="text-2xl font-bold text-red-600" id="issues-count">0</div>
155
+ </div>
156
+ </div>
157
+ </div>
158
+
159
+ <div id="results-section" class="hidden">
160
+ <div class="flex items-center mb-4">
161
+ <div class="w-8 h-8 rounded-full bg-green-100 flex items-center justify-center mr-3">
162
+ <i class="fas fa-check text-green-500"></i>
163
+ </div>
164
+ <h3 class="text-lg font-medium text-gray-700">Validation Complete</h3>
165
+ </div>
166
+
167
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
168
+ <div class="bg-white border border-gray-200 p-4 rounded-lg shadow-sm">
169
+ <div class="text-sm text-gray-500 mb-1">Total Emails</div>
170
+ <div class="text-2xl font-bold text-gray-800" id="total-emails">0</div>
171
+ </div>
172
+ <div class="bg-white border border-gray-200 p-4 rounded-lg shadow-sm">
173
+ <div class="text-sm text-gray-500 mb-1">Valid Emails</div>
174
+ <div class="text-2xl font-bold text-green-600" id="final-valid">0</div>
175
+ </div>
176
+ <div class="bg-white border border-gray-200 p-4 rounded-lg shadow-sm">
177
+ <div class="text-sm text-gray-500 mb-1">Invalid Emails</div>
178
+ <div class="text-2xl font-bold text-red-600" id="final-invalid">0</div>
179
+ </div>
180
+ </div>
181
+
182
+ <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 mb-6">
183
+ <div class="bg-white border border-gray-200 p-4 rounded-lg shadow-sm">
184
+ <div class="flex items-center justify-between mb-2">
185
+ <div class="text-sm text-gray-500">Duplicates</div>
186
+ <div class="text-lg font-bold text-amber-600" id="duplicate-count">0</div>
187
+ </div>
188
+ <div class="text-xs text-gray-400">Emails appearing multiple times</div>
189
+ </div>
190
+ <div class="bg-white border border-gray-200 p-4 rounded-lg shadow-sm">
191
+ <div class="flex items-center justify-between mb-2">
192
+ <div class="text-sm text-gray-500">Typos Found</div>
193
+ <div class="text-lg font-bold text-blue-600" id="typo-count">0</div>
194
+ </div>
195
+ <div class="text-xs text-gray-400">Potential email address typos</div>
196
+ </div>
197
+ <div class="bg-white border border-gray-200 p-4 rounded-lg shadow-sm">
198
+ <div class="flex items-center justify-between mb-2">
199
+ <div class="text-sm text-gray-500">Syntax Errors</div>
200
+ <div class="text-lg font-bold text-red-600" id="syntax-count">0</div>
201
+ </div>
202
+ <div class="text-xs text-gray-400">Invalid email formats</div>
203
+ </div>
204
+ <div class="bg-white border border-gray-200 p-4 rounded-lg shadow-sm">
205
+ <div class="flex items-center justify-between mb-2">
206
+ <div class="text-sm text-gray-500">MX Issues</div>
207
+ <div class="text-lg font-bold text-purple-600" id="mx-count">0</div>
208
+ </div>
209
+ <div class="text-xs text-gray-400">Domains without mail servers</div>
210
+ </div>
211
+ <div class="bg-white border border-gray-200 p-4 rounded-lg shadow-sm">
212
+ <div class="flex items-center justify-between mb-2">
213
+ <div class="text-sm text-gray-500">Undeliverable</div>
214
+ <div class="text-lg font-bold text-gray-600" id="undeliverable-count">0</div>
215
+ </div>
216
+ <div class="text-xs text-gray-400">Emails that may bounce</div>
217
+ </div>
218
+ <div class="bg-white border border-gray-200 p-4 rounded-lg shadow-sm">
219
+ <div class="flex items-center justify-between mb-2">
220
+ <div class="text-sm text-gray-500">Unknown Status</div>
221
+ <div class="text-lg font-bold text-gray-500" id="unknown-count">0</div>
222
+ </div>
223
+ <div class="text-xs text-gray-400">Could not verify deliverability</div>
224
+ </div>
225
+ </div>
226
+
227
+ <!-- MX Response Insights Section -->
228
+ <div class="mb-6">
229
+ <h4 class="font-medium text-gray-700 mb-4 flex items-center">
230
+ <i class="fas fa-server mr-2 text-blue-500"></i> MX Record Analysis
231
+ </h4>
232
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
233
+ <div class="bg-white border border-blue-100 rounded-lg p-4 insight-card">
234
+ <div class="flex items-center mb-2">
235
+ <div class="w-10 h-10 bg-blue-50 rounded-full flex items-center justify-center mr-3">
236
+ <i class="fas fa-check-circle text-blue-500"></i>
237
+ </div>
238
+ <h5 class="font-medium text-gray-800">Valid MX Records</h5>
239
+ </div>
240
+ <div class="text-3xl font-bold text-blue-600 mb-2" id="valid-mx-count">0</div>
241
+ <div class="text-sm text-gray-600">
242
+ <span id="valid-mx-percent">0</span>% of emails have domains with properly configured mail servers
243
+ </div>
244
+ </div>
245
+ <div class="bg-white border border-purple-100 rounded-lg p-4 insight-card">
246
+ <div class="flex items-center mb-2">
247
+ <div class="w-10 h-10 bg-purple-50 rounded-full flex items-center justify-center mr-3">
248
+ <i class="fas fa-exclamation-triangle text-purple-500"></i>
249
+ </div>
250
+ <h5 class="font-medium text-gray-800">MX Issues Detected</h5>
251
+ </div>
252
+ <div class="text-3xl font-bold text-purple-600 mb-2" id="invalid-mx-count">0</div>
253
+ <div class="text-sm text-gray-600">
254
+ These domains cannot receive emails due to missing or incorrect MX records
255
+ </div>
256
+ <div class="mt-2">
257
+ <div class="text-xs font-medium text-gray-500 mb-1">Top Problematic Domains:</div>
258
+ <div class="text-xs text-gray-600" id="top-mx-issues"></div>
259
+ </div>
260
+ </div>
261
+ </div>
262
+ </div>
263
+
264
+ <!-- Deliverability Insights Section -->
265
+ <div class="mb-6">
266
+ <h4 class="font-medium text-gray-700 mb-4 flex items-center">
267
+ <i class="fas fa-paper-plane mr-2 text-green-500"></i> Email Deliverability Insights
268
+ </h4>
269
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
270
+ <div class="bg-white border border-green-100 rounded-lg p-4 insight-card">
271
+ <div class="flex items-center mb-2">
272
+ <div class="w-10 h-10 bg-green-50 rounded-full flex items-center justify-center mr-3">
273
+ <i class="fas fa-check-circle text-green-500"></i>
274
+ </div>
275
+ <h5 class="font-medium text-gray-800">High Deliverability</h5>
276
+ </div>
277
+ <div class="text-3xl font-bold text-green-600 mb-2" id="deliverable-count">0</div>
278
+ <div class="text-sm text-gray-600">
279
+ <span id="deliverable-percent">0</span>% of emails are confirmed to be deliverable
280
+ </div>
281
+ </div>
282
+ <div class="bg-white border border-red-100 rounded-lg p-4 insight-card">
283
+ <div class="flex items-center mb-2">
284
+ <div class="w-10 h-10 bg-red-50 rounded-full flex items-center justify-center mr-3">
285
+ <i class="fas fa-times-circle text-red-500"></i>
286
+ </div>
287
+ <h5 class="font-medium text-gray-800">Undeliverable</h5>
288
+ </div>
289
+ <div class="text-3xl font-bold text-red-600 mb-2" id="undeliverable-insight-count">0</div>
290
+ <div class="text-sm text-gray-600">
291
+ These emails will likely bounce or be rejected by receiving servers
292
+ </div>
293
+ </div>
294
+ <div class="bg-white border border-gray-200 rounded-lg p-4 insight-card">
295
+ <div class="flex items-center mb-2">
296
+ <div class="w-10 h-10 bg-gray-50 rounded-full flex items-center justify-center mr-3">
297
+ <i class="fas fa-question-circle text-gray-500"></i>
298
+ </div>
299
+ <h5 class="font-medium text-gray-800">Unknown Status</h5>
300
+ </div>
301
+ <div class="text-3xl font-bold text-gray-600 mb-2" id="unknown-deliverability-count">0</div>
302
+ <div class="text-sm text-gray-600">
303
+ Could not verify deliverability due to server restrictions or timeouts
304
+ </div>
305
+ </div>
306
+ </div>
307
+ <div class="mt-4 bg-white border border-yellow-100 rounded-lg p-4 insight-card">
308
+ <div class="flex items-center mb-2">
309
+ <div class="w-10 h-10 bg-yellow-50 rounded-full flex items-center justify-center mr-3">
310
+ <i class="fas fa-chart-line text-yellow-500"></i>
311
+ </div>
312
+ <h5 class="font-medium text-gray-800">Overall Deliverability Score</h5>
313
+ </div>
314
+ <div class="flex items-center">
315
+ <div class="w-full bg-gray-200 rounded-full h-4 mr-4">
316
+ <div id="deliverability-score-bar" class="h-4 rounded-full" style="width: 0%; background: linear-gradient(90deg, #10b981 0%, #f59e0b 50%, #ef4444 100%);"></div>
317
+ </div>
318
+ <div class="text-2xl font-bold" id="deliverability-score">0</div>
319
+ <span class="ml-1 text-gray-500">/100</span>
320
+ </div>
321
+ <div class="mt-2 text-sm text-gray-600">
322
+ <span id="deliverability-rating" class="font-medium">Poor</span> -
323
+ <span id="deliverability-description">This list has significant deliverability issues that need attention</span>
324
+ </div>
325
+ </div>
326
+ </div>
327
+
328
+ <div class="mb-6">
329
+ <div class="flex justify-between items-center mb-2">
330
+ <h4 class="font-medium text-gray-700">Email Details</h4>
331
+ <div class="text-sm text-gray-500">
332
+ <span id="showing-count">0</span> of <span id="total-count">0</span> emails shown
333
+ </div>
334
+ </div>
335
+ <div class="overflow-x-auto">
336
+ <table class="min-w-full bg-white border border-gray-200 rounded-lg overflow-hidden">
337
+ <thead class="bg-gray-50">
338
+ <tr>
339
+ <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Email</th>
340
+ <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>
341
+ <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Details</th>
342
+ <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">MX Response</th>
343
+ </tr>
344
+ </thead>
345
+ <tbody id="email-table-body" class="divide-y divide-gray-200">
346
+ <!-- Email rows will be inserted here -->
347
+ </tbody>
348
+ </table>
349
+ </div>
350
+ </div>
351
+
352
+ <div class="flex flex-col sm:flex-row justify-between gap-4">
353
+ <button id="download-report" class="flex-1 bg-blue-500 hover:bg-blue-600 text-white px-6 py-3 rounded-md flex items-center justify-center transition duration-300">
354
+ <i class="fas fa-file-excel mr-2"></i> Download Cleaned Excel File
355
+ </button>
356
+ <button id="download-summary" class="flex-1 bg-gray-100 hover:bg-gray-200 text-gray-700 px-6 py-3 rounded-md flex items-center justify-center transition duration-300">
357
+ <i class="fas fa-file-alt mr-2"></i> Download Full Report (PDF)
358
+ </button>
359
+ <button id="start-over" class="flex-1 bg-white border border-gray-300 hover:bg-gray-50 text-gray-700 px-6 py-3 rounded-md flex items-center justify-center transition duration-300">
360
+ <i class="fas fa-redo mr-2"></i> Start Over
361
+ </button>
362
+ </div>
363
+ </div>
364
+ </div>
365
+
366
+ <div class="bg-white rounded-lg shadow-md p-6 mb-8 hidden" id="error-section">
367
+ <div class="flex items-center mb-4">
368
+ <div class="w-8 h-8 rounded-full bg-red-100 flex items-center justify-center mr-3">
369
+ <i class="fas fa-exclamation-triangle text-red-500"></i>
370
+ </div>
371
+ <h3 class="text-lg font-medium text-gray-700">Error Processing File</h3>
372
+ </div>
373
+ <div class="text-red-600 mb-4" id="error-message"></div>
374
+ <button id="try-again" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-md transition duration-300">
375
+ <i class="fas fa-redo mr-2"></i> Try Again
376
+ </button>
377
+ </div>
378
+
379
+ <div class="bg-white rounded-lg shadow-md p-6">
380
+ <h3 class="text-lg font-medium text-gray-700 mb-4">How It Works</h3>
381
+ <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
382
+ <div class="bg-gray-50 p-4 rounded-lg">
383
+ <div class="w-10 h-10 bg-blue-100 rounded-full flex items-center justify-center mb-3">
384
+ <i class="fas fa-file-upload text-blue-500"></i>
385
+ </div>
386
+ <h4 class="font-medium text-gray-800 mb-1">1. Upload File</h4>
387
+ <p class="text-sm text-gray-600">Upload your Excel file containing email addresses</p>
388
+ </div>
389
+ <div class="bg-gray-50 p-4 rounded-lg">
390
+ <div class="w-10 h-10 bg-purple-100 rounded-full flex items-center justify-center mb-3">
391
+ <i class="fas fa-check-circle text-purple-500"></i>
392
+ </div>
393
+ <h4 class="font-medium text-gray-800 mb-1">2. Validation</h4>
394
+ <p class="text-sm text-gray-600">We check each email for syntax, typos, duplicates, and deliverability</p>
395
+ </div>
396
+ <div class="bg-gray-50 p-4 rounded-lg">
397
+ <div class="w-10 h-10 bg-green-100 rounded-full flex items-center justify-center mb-3">
398
+ <i class="fas fa-chart-pie text-green-500"></i>
399
+ </div>
400
+ <h4 class="font-medium text-gray-800 mb-1">3. Analysis</h4>
401
+ <p class="text-sm text-gray-600">Get detailed statistics about your email list quality</p>
402
+ </div>
403
+ <div class="bg-gray-50 p-4 rounded-lg">
404
+ <div class="w-10 h-10 bg-amber-100 rounded-full flex items-center justify-center mb-3">
405
+ <i class="fas fa-download text-amber-500"></i>
406
+ </div>
407
+ <h4 class="font-medium text-gray-800 mb-1">4. Download</h4>
408
+ <p class="text-sm text-gray-600">Download cleaned file with validation results and suggestions</p>
409
+ </div>
410
+ </div>
411
+ </div>
412
+ </div>
413
+
414
+ <script>
415
+ document.addEventListener('DOMContentLoaded', function() {
416
+ // DOM elements
417
+ const dropzone = document.getElementById('dropzone');
418
+ const fileUpload = document.getElementById('file-upload');
419
+ const uploadSection = document.getElementById('upload-section');
420
+ const processingSection = document.getElementById('processing-section');
421
+ const resultsSection = document.getElementById('results-section');
422
+ const errorSection = document.getElementById('error-section');
423
+ const emailTableBody = document.getElementById('email-table-body');
424
+
425
+ // Progress elements
426
+ const progressBar = document.getElementById('progress-bar');
427
+ const progressPercent = document.getElementById('progress-percent');
428
+ const processedCount = document.getElementById('processed-count');
429
+ const validCount = document.getElementById('valid-count');
430
+ const issuesCount = document.getElementById('issues-count');
431
+
432
+ // Result elements
433
+ const totalEmails = document.getElementById('total-emails');
434
+ const finalValid = document.getElementById('final-valid');
435
+ const finalInvalid = document.getElementById('final-invalid');
436
+ const duplicateCount = document.getElementById('duplicate-count');
437
+ const typoCount = document.getElementById('typo-count');
438
+ const syntaxCount = document.getElementById('syntax-count');
439
+ const mxCount = document.getElementById('mx-count');
440
+ const undeliverableCount = document.getElementById('undeliverable-count');
441
+ const unknownCount = document.getElementById('unknown-count');
442
+ const showingCount = document.getElementById('showing-count');
443
+ const totalCount = document.getElementById('total-count');
444
+
445
+ // MX Insights elements
446
+ const validMxCount = document.getElementById('valid-mx-count');
447
+ const validMxPercent = document.getElementById('valid-mx-percent');
448
+ const invalidMxCount = document.getElementById('invalid-mx-count');
449
+ const topMxIssues = document.getElementById('top-mx-issues');
450
+
451
+ // Deliverability Insights elements
452
+ const deliverableCount = document.getElementById('deliverable-count');
453
+ const deliverablePercent = document.getElementById('deliverable-percent');
454
+ const undeliverableInsightCount = document.getElementById('undeliverable-insight-count');
455
+ const unknownDeliverabilityCount = document.getElementById('unknown-deliverability-count');
456
+ const deliverabilityScoreBar = document.getElementById('deliverability-score-bar');
457
+ const deliverabilityScore = document.getElementById('deliverability-score');
458
+ const deliverabilityRating = document.getElementById('deliverability-rating');
459
+ const deliverabilityDescription = document.getElementById('deliverability-description');
460
+
461
+ // Buttons
462
+ const downloadReport = document.getElementById('download-report');
463
+ const downloadSummary = document.getElementById('download-summary');
464
+ const startOver = document.getElementById('start-over');
465
+ const tryAgain = document.getElementById('try-again');
466
+
467
+ // Data storage
468
+ let emailData = [];
469
+ let processedEmails = [];
470
+ let workbook = null;
471
+ let domainStats = {};
472
+
473
+ // Common typos mapping
474
+ const commonTypos = {
475
+ 'gmai.com': 'gmail.com',
476
+ 'gmail.con': 'gmail.com',
477
+ 'gmail.co': 'gmail.com',
478
+ 'gmail.cm': 'gmail.com',
479
+ 'gmial.com': 'gmail.com',
480
+ 'gmal.com': 'gmail.com',
481
+ 'gamil.com': 'gmail.com',
482
+ 'gnail.com': 'gmail.com',
483
+ 'gmsil.com': 'gmail.com',
484
+ 'gmaill.com': 'gmail.com',
485
+ 'gmail..com': 'gmail.com',
486
+ 'gmail.comm': 'gmail.com',
487
+ 'gmail.om': 'gmail.com',
488
+ 'gmil.com': 'gmail.com',
489
+ 'gmaul.com': 'gmail.com',
490
+ 'gmaio.com': 'gmail.com',
491
+ 'gmaiil.com': 'gmail.com',
492
+ 'gmeil.com': 'gmail.com',
493
+ 'gmil.com': 'gmail.com',
494
+ 'gmaile.com': 'gmail.com',
495
+ 'gmaim.com': 'gmail.com',
496
+ 'hotnail.com': 'hotmail.com',
497
+ 'homail.com': 'hotmail.com',
498
+ 'hotmal.com': 'hotmail.com',
499
+ 'hotmaill.com': 'hotmail.com',
500
+ 'hotmail..com': 'hotmail.com',
501
+ 'yahoo.co': 'yahoo.com',
502
+ 'yaho.com': 'yahoo.com',
503
+ 'yahho.com': 'yahoo.com',
504
+ 'yahoocom': 'yahoo.com',
505
+ 'yahooo.com': 'yahoo.com',
506
+ 'yahoo.comm': 'yahoo.com',
507
+ 'outlok.com': 'outlook.com',
508
+ 'outllok.com': 'outlook.com',
509
+ 'outlook..com': 'outlook.com'
510
+ };
511
+
512
+ // MX response messages
513
+ const mxResponses = {
514
+ valid: "Valid MX records found. Domain can receive emails.",
515
+ invalid: "No MX records found. Domain cannot receive emails.",
516
+ timeout: "MX lookup timed out. Could not verify mail servers.",
517
+ restricted: "MX lookup restricted by DNS settings.",
518
+ temporary: "Temporary MX lookup failure. Try again later."
519
+ };
520
+
521
+ // Deliverability messages
522
+ const deliverabilityMessages = {
523
+ deliverable: "Server confirmed email exists and can receive messages.",
524
+ undeliverable: "Server confirmed email does not exist or cannot receive messages.",
525
+ unknown: "Could not verify deliverability due to server restrictions.",
526
+ risky: "Email appears valid but may have deliverability issues.",
527
+ catchall: "Domain accepts all emails (catch-all), making verification less reliable."
528
+ };
529
+
530
+ // Event listeners
531
+ fileUpload.addEventListener('change', handleFileSelect);
532
+ dropzone.addEventListener('dragover', handleDragOver);
533
+ dropzone.addEventListener('dragleave', handleDragLeave);
534
+ dropzone.addEventListener('drop', handleDrop);
535
+ downloadReport.addEventListener('click', downloadCleanedFile);
536
+ downloadSummary.addEventListener('click', downloadSummaryReport);
537
+ startOver.addEventListener('click', resetForm);
538
+ tryAgain.addEventListener('click', resetForm);
539
+
540
+ // Functions
541
+ function handleFileSelect(e) {
542
+ const files = e.target.files;
543
+ if (files.length) {
544
+ processFile(files[0]);
545
+ }
546
+ }
547
+
548
+ function handleDragOver(e) {
549
+ e.preventDefault();
550
+ e.stopPropagation();
551
+ dropzone.classList.add('active');
552
+ }
553
+
554
+ function handleDragLeave(e) {
555
+ e.preventDefault();
556
+ e.stopPropagation();
557
+ dropzone.classList.remove('active');
558
+ }
559
+
560
+ function handleDrop(e) {
561
+ e.preventDefault();
562
+ e.stopPropagation();
563
+ dropzone.classList.remove('active');
564
+
565
+ const files = e.dataTransfer.files;
566
+ if (files.length) {
567
+ processFile(files[0]);
568
+ }
569
+ }
570
+
571
+ function processFile(file) {
572
+ const reader = new FileReader();
573
+
574
+ reader.onload = function(e) {
575
+ try {
576
+ const data = new Uint8Array(e.target.result);
577
+ workbook = XLSX.read(data, { type: 'array' });
578
+
579
+ // Extract all emails from the workbook
580
+ emailData = extractEmailsFromWorkbook(workbook);
581
+
582
+ if (emailData.length === 0) {
583
+ showError("No email addresses found in the file. Please upload a file with at least one column containing email addresses.");
584
+ return;
585
+ }
586
+
587
+ // Initialize domain stats
588
+ initDomainStats(emailData);
589
+
590
+ // Show processing section
591
+ uploadSection.classList.add('hidden');
592
+ processingSection.classList.remove('hidden');
593
+ resultsSection.classList.add('hidden');
594
+ errorSection.classList.add('hidden');
595
+
596
+ // Start processing emails
597
+ processEmails(emailData);
598
+
599
+ } catch (error) {
600
+ showError("Error reading the file. Please make sure it's a valid Excel file.");
601
+ console.error(error);
602
+ }
603
+ };
604
+
605
+ reader.onerror = function() {
606
+ showError("Error reading the file. Please try again.");
607
+ };
608
+
609
+ reader.readAsArrayBuffer(file);
610
+ }
611
+
612
+ function extractEmailsFromWorkbook(workbook) {
613
+ const emails = [];
614
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
615
+
616
+ // Process each sheet
617
+ workbook.SheetNames.forEach(sheetName => {
618
+ const worksheet = workbook.Sheets[sheetName];
619
+ const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
620
+
621
+ // Process each row and cell
622
+ jsonData.forEach(row => {
623
+ if (Array.isArray(row)) {
624
+ row.forEach(cell => {
625
+ if (typeof cell === 'string') {
626
+ // Check if the cell looks like an email
627
+ if (emailRegex.test(cell.trim())) {
628
+ emails.push({
629
+ original: cell.trim(),
630
+ cleaned: cell.trim().toLowerCase(),
631
+ rowData: row // Store the entire row for later
632
+ });
633
+ }
634
+ }
635
+ });
636
+ }
637
+ });
638
+ });
639
+
640
+ return emails;
641
+ }
642
+
643
+ function initDomainStats(emails) {
644
+ domainStats = {};
645
+
646
+ // Count frequency of each domain
647
+ emails.forEach(email => {
648
+ const domain = email.cleaned.split('@')[1];
649
+ if (!domainStats[domain]) {
650
+ domainStats[domain] = {
651
+ count: 0,
652
+ validMx: 0,
653
+ invalidMx: 0,
654
+ deliverable: 0,
655
+ undeliverable: 0,
656
+ unknown: 0
657
+ };
658
+ }
659
+ domainStats[domain].count++;
660
+ });
661
+ }
662
+
663
+ function processEmails(emails) {
664
+ let processed = 0;
665
+ let valid = 0;
666
+ let issues = 0;
667
+ let duplicates = 0;
668
+ let typos = 0;
669
+ let syntaxErrors = 0;
670
+ let mxErrors = 0;
671
+ let undeliverable = 0;
672
+ let unknown = 0;
673
+ let deliverable = 0;
674
+
675
+ const totalEmails = emails.length;
676
+ const emailFrequency = {};
677
+ const processedEmailsList = [];
678
+
679
+ // Count frequency for duplicates
680
+ emails.forEach(email => {
681
+ const cleanEmail = email.cleaned;
682
+ emailFrequency[cleanEmail] = (emailFrequency[cleanEmail] || 0) + 1;
683
+ });
684
+
685
+ // Process each email
686
+ emails.forEach((email, index) => {
687
+ setTimeout(() => {
688
+ const result = validateEmail(email, emailFrequency);
689
+
690
+ // Update domain stats
691
+ const domain = email.cleaned.split('@')[1];
692
+ if (result.hasMxError) {
693
+ domainStats[domain].invalidMx++;
694
+ } else {
695
+ domainStats[domain].validMx++;
696
+
697
+ if (result.status === 'Valid') {
698
+ domainStats[domain].deliverable++;
699
+ deliverable++;
700
+ } else if (result.isUndeliverable) {
701
+ domainStats[domain].undeliverable++;
702
+ } else {
703
+ domainStats[domain].unknown++;
704
+ }
705
+ }
706
+
707
+ processedEmailsList.push({
708
+ ...email,
709
+ ...result
710
+ });
711
+
712
+ processed++;
713
+
714
+ // Update counters based on result
715
+ if (result.status === 'Valid') valid++;
716
+ else issues++;
717
+
718
+ if (result.isDuplicate) duplicates++;
719
+ if (result.hasTypo) typos++;
720
+ if (result.hasSyntaxError) syntaxErrors++;
721
+ if (result.hasMxError) mxErrors++;
722
+ if (result.isUndeliverable) undeliverable++;
723
+ if (result.status === 'Unknown') unknown++;
724
+
725
+ // Update progress
726
+ const progress = Math.round((processed / totalEmails) * 100);
727
+ progressBar.style.width = `${progress}%`;
728
+ progressPercent.textContent = `${progress}%`;
729
+ processedCount.textContent = processed;
730
+ validCount.textContent = valid;
731
+ issuesCount.textContent = issues;
732
+
733
+ // When all emails are processed
734
+ if (processed === totalEmails) {
735
+ showResults({
736
+ totalEmails,
737
+ valid,
738
+ invalid: issues,
739
+ duplicates,
740
+ typos,
741
+ syntaxErrors,
742
+ mxErrors,
743
+ undeliverable,
744
+ unknown,
745
+ deliverable,
746
+ processedEmails: processedEmailsList
747
+ });
748
+ }
749
+ }, index * 10); // Small delay to allow UI updates
750
+ });
751
+ }
752
+
753
+ function validateEmail(email, emailFrequency) {
754
+ const result = {
755
+ status: 'Valid',
756
+ isDuplicate: false,
757
+ hasTypo: false,
758
+ hasSyntaxError: false,
759
+ hasMxError: false,
760
+ isUndeliverable: false,
761
+ suggestion: null,
762
+ details: 'Email appears to be valid',
763
+ mxResponse: mxResponses.valid,
764
+ deliverability: deliverabilityMessages.deliverable
765
+ };
766
+
767
+ // Check for duplicates
768
+ if (emailFrequency[email.cleaned] > 1) {
769
+ result.isDuplicate = true;
770
+ result.status = 'Duplicate';
771
+ result.details = 'This email appears multiple times in your list';
772
+ return result;
773
+ }
774
+
775
+ // Check for syntax errors
776
+ if (!isValidEmailSyntax(email.original)) {
777
+ result.hasSyntaxError = true;
778
+ result.status = 'Invalid Syntax';
779
+ result.details = 'Email format is invalid (missing @, invalid characters, etc.)';
780
+ result.mxResponse = 'N/A - Invalid email format';
781
+ result.deliverability = 'N/A - Invalid email format';
782
+ return result;
783
+ }
784
+
785
+ // Check for typos
786
+ const typoCheck = checkForTypos(email.cleaned);
787
+ if (typoCheck.hasTypo) {
788
+ result.hasTypo = true;
789
+ result.status = 'Typo';
790
+ result.suggestion = typoCheck.suggestion;
791
+ result.details = `Possible typo detected. Did you mean ${typoCheck.suggestion}?`;
792
+ }
793
+
794
+ // Simulate MX check (in a real app, this would be an API call)
795
+ const domain = email.cleaned.split('@')[1];
796
+ const mxCheckResult = simulateMxCheck(domain);
797
+
798
+ if (!mxCheckResult.valid) {
799
+ result.hasMxError = true;
800
+ result.status = 'Invalid MX';
801
+ result.details = 'Domain does not have valid mail server records';
802
+ result.mxResponse = mxCheckResult.message;
803
+ result.deliverability = 'N/A - No mail servers found';
804
+ return result;
805
+ } else {
806
+ result.mxResponse = mxCheckResult.message;
807
+ }
808
+
809
+ // Simulate deliverability check (in a real app, this would be an API call)
810
+ const deliverabilityResult = simulateDeliverabilityCheck(email.cleaned);
811
+
812
+ if (deliverabilityResult.status === 'undeliverable') {
813
+ result.isUndeliverable = true;
814
+ result.status = 'Undeliverable';
815
+ result.details = 'Email address appears to be invalid or not accepting mail';
816
+ result.deliverability = deliverabilityResult.message;
817
+ } else if (deliverabilityResult.status === 'unknown') {
818
+ result.status = 'Unknown';
819
+ result.details = 'Could not verify deliverability';
820
+ result.deliverability = deliverabilityResult.message;
821
+ } else if (deliverabilityResult.status === 'risky') {
822
+ result.deliverability = deliverabilityResult.message;
823
+ } else if (deliverabilityResult.status === 'catchall') {
824
+ result.deliverability = deliverabilityResult.message;
825
+ }
826
+
827
+ return result;
828
+ }
829
+
830
+ function isValidEmailSyntax(email) {
831
+ // More comprehensive regex for email validation
832
+ const regex = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
833
+ return regex.test(email);
834
+ }
835
+
836
+ function checkForTypos(email) {
837
+ const result = {
838
+ hasTypo: false,
839
+ suggestion: null
840
+ };
841
+
842
+ const [localPart, domain] = email.split('@');
843
+
844
+ // Check for common domain typos
845
+ if (commonTypos[domain]) {
846
+ result.hasTypo = true;
847
+ result.suggestion = `${localPart}@${commonTypos[domain]}`;
848
+ return result;
849
+ }
850
+
851
+ // Check for doubled dots
852
+ if (domain.includes('..')) {
853
+ const correctedDomain = domain.replace(/\.+/g, '.');
854
+ result.hasTypo = true;
855
+ result.suggestion = `${localPart}@${correctedDomain}`;
856
+ return result;
857
+ }
858
+
859
+ // Check for common TLD typos
860
+ const tld = domain.split('.').pop();
861
+ const commonTldTypos = {
862
+ 'con': 'com',
863
+ 'cpm': 'com',
864
+ 'cim': 'com',
865
+ 'col': 'com',
866
+ 'cok': 'com',
867
+ 'co': 'com',
868
+ 'cm': 'com',
869
+ 'comm': 'com',
870
+ 'netl': 'net',
871
+ 'ner': 'net',
872
+ 'orgn': 'org',
873
+ 'og': 'org',
874
+ 'edu.': 'edu',
875
+ 'gouv': 'gov',
876
+ 'gob': 'gov'
877
+ };
878
+
879
+ if (commonTldTypos[tld]) {
880
+ const correctedDomain = domain.replace(new RegExp(`${tld}$`), commonTldTypos[tld]);
881
+ result.hasTypo = true;
882
+ result.suggestion = `${localPart}@${correctedDomain}`;
883
+ return result;
884
+ }
885
+
886
+ return result;
887
+ }
888
+
889
+ function simulateMxCheck(domain) {
890
+ // In a real implementation, this would make a DNS query
891
+ // For simulation, we'll randomly fail for some domains
892
+ const badDomains = ['example.com', 'test.com', 'invalid.com', 'fakedomain.com'];
893
+
894
+ if (badDomains.includes(domain)) {
895
+ return {
896
+ valid: false,
897
+ message: mxResponses.invalid
898
+ };
899
+ }
900
+
901
+ // Randomly simulate other MX issues
902
+ const random = Math.random();
903
+ if (random < 0.05) {
904
+ return {
905
+ valid: false,
906
+ message: mxResponses.timeout
907
+ };
908
+ } else if (random < 0.1) {
909
+ return {
910
+ valid: false,
911
+ message: mxResponses.restricted
912
+ };
913
+ } else if (random < 0.15) {
914
+ return {
915
+ valid: false,
916
+ message: mxResponses.temporary
917
+ };
918
+ }
919
+
920
+ return {
921
+ valid: true,
922
+ message: mxResponses.valid
923
+ };
924
+ }
925
+
926
+ function simulateDeliverabilityCheck(email) {
927
+ // In a real implementation, this would make an SMTP check
928
+ // For simulation, we'll randomly mark some as undeliverable
929
+ const random = Math.random();
930
+
931
+ if (random < 0.1) {
932
+ return {
933
+ status: 'undeliverable',
934
+ message: deliverabilityMessages.undeliverable
935
+ };
936
+ } else if (random < 0.2) {
937
+ return {
938
+ status: 'unknown',
939
+ message: deliverabilityMessages.unknown
940
+ };
941
+ } else if (random < 0.3) {
942
+ return {
943
+ status: 'risky',
944
+ message: deliverabilityMessages.risky
945
+ };
946
+ } else if (random < 0.4) {
947
+ return {
948
+ status: 'catchall',
949
+ message: deliverabilityMessages.catchall
950
+ };
951
+ }
952
+
953
+ return {
954
+ status: 'deliverable',
955
+ message: deliverabilityMessages.deliverable
956
+ };
957
+ }
958
+
959
+ function showResults(stats) {
960
+ processingSection.classList.add('hidden');
961
+ resultsSection.classList.remove('hidden');
962
+
963
+ // Update summary stats
964
+ totalEmails.textContent = stats.totalEmails;
965
+ finalValid.textContent = stats.valid;
966
+ finalInvalid.textContent = stats.invalid;
967
+ duplicateCount.textContent = stats.duplicates;
968
+ typoCount.textContent = stats.typos;
969
+ syntaxCount.textContent = stats.syntaxErrors;
970
+ mxCount.textContent = stats.mxErrors;
971
+ undeliverableCount.textContent = stats.undeliverable;
972
+ unknownCount.textContent = stats.unknown;
973
+
974
+ // Calculate MX stats
975
+ const validMx = stats.totalEmails - stats.mxErrors;
976
+ const validMxPct = Math.round((validMx / stats.totalEmails) * 100);
977
+ validMxCount.textContent = validMx;
978
+ validMxPercent.textContent = validMxPct;
979
+ invalidMxCount.textContent = stats.mxErrors;
980
+
981
+ // Show top MX issues
982
+ const problematicDomains = Object.entries(domainStats)
983
+ .filter(([domain, stats]) => stats.invalidMx > 0)
984
+ .sort((a, b) => b[1].invalidMx - a[1].invalidMx)
985
+ .slice(0, 5);
986
+
987
+ if (problematicDomains.length > 0) {
988
+ topMxIssues.innerHTML = problematicDomains
989
+ .map(([domain, stats]) =>
990
+ `<div class="flex justify-between py-1">
991
+ <span class="truncate">${domain}</span>
992
+ <span class="font-medium">${stats.invalidMx} issues</span>
993
+ </div>`
994
+ ).join('');
995
+ } else {
996
+ topMxIssues.textContent = "No significant MX issues detected";
997
+ }
998
+
999
+ // Update deliverability stats
1000
+ deliverableCount.textContent = stats.deliverable;
1001
+ const deliverablePct = Math.round((stats.deliverable / stats.totalEmails) * 100);
1002
+ deliverablePercent.textContent = deliverablePct;
1003
+ undeliverableInsightCount.textContent = stats.undeliverable;
1004
+ unknownDeliverabilityCount.textContent = stats.unknown;
1005
+
1006
+ // Calculate deliverability score (0-100)
1007
+ const deliverabilityScoreValue = Math.min(100, Math.max(0,
1008
+ (stats.deliverable / stats.totalEmails) * 80 +
1009
+ ((stats.totalEmails - stats.undeliverable) / stats.totalEmails) * 20
1010
+ ));
1011
+
1012
+ deliverabilityScoreBar.style.width = `${deliverabilityScoreValue}%`;
1013
+ deliverabilityScore.textContent = Math.round(deliverabilityScoreValue);
1014
+
1015
+ // Set deliverability rating
1016
+ if (deliverabilityScoreValue >= 80) {
1017
+ deliverabilityRating.textContent = "Excellent";
1018
+ deliverabilityRating.className = "font-medium text-green-600";
1019
+ deliverabilityDescription.textContent = "This list has excellent deliverability potential";
1020
+ } else if (deliverabilityScoreValue >= 60) {
1021
+ deliverabilityRating.textContent = "Good";
1022
+ deliverabilityRating.className = "font-medium text-blue-600";
1023
+ deliverabilityDescription.textContent = "This list has good deliverability with minor issues";
1024
+ } else if (deliverabilityScoreValue >= 40) {
1025
+ deliverabilityRating.textContent = "Fair";
1026
+ deliverabilityRating.className = "font-medium text-yellow-600";
1027
+ deliverabilityDescription.textContent = "This list may have deliverability issues that need attention";
1028
+ } else {
1029
+ deliverabilityRating.textContent = "Poor";
1030
+ deliverabilityRating.className = "font-medium text-red-600";
1031
+ deliverabilityDescription.textContent = "This list has significant deliverability issues that need attention";
1032
+ }
1033
+
1034
+ // Show first 100 emails in the table
1035
+ const emailsToShow = stats.processedEmails.slice(0, 100);
1036
+ showingCount.textContent = emailsToShow.length;
1037
+ totalCount.textContent = stats.totalEmails;
1038
+
1039
+ emailTableBody.innerHTML = '';
1040
+ emailsToShow.forEach(email => {
1041
+ const row = document.createElement('tr');
1042
+ row.className = 'fade-in';
1043
+
1044
+ // Status badge
1045
+ let statusClass = '';
1046
+ if (email.status === 'Valid') statusClass = 'status-valid';
1047
+ else if (email.status === 'Duplicate') statusClass = 'status-duplicate';
1048
+ else if (email.status === 'Typo') statusClass = 'status-typo';
1049
+ else if (email.status === 'Invalid Syntax') statusClass = 'status-invalid';
1050
+ else if (email.status === 'Invalid MX') statusClass = 'status-mx';
1051
+ else if (email.status === 'Undeliverable') statusClass = 'status-undeliverable';
1052
+ else statusClass = 'status-unknown';
1053
+
1054
+ // Tooltip for details
1055
+ const tooltipId = `tooltip-${Math.random().toString(36).substr(2, 9)}`;
1056
+
1057
+ row.innerHTML = `
1058
+ <td class="px-4 py-3 whitespace-nowrap text-sm text-gray-800">${email.original}</td>
1059
+ <td class="px-4 py-3 whitespace-nowrap">
1060
+ <span class="status-badge ${statusClass}">${email.status}</span>
1061
+ </td>
1062
+ <td class="px-4 py-3 whitespace-nowrap text-sm text-gray-600">
1063
+ <div class="tooltip">
1064
+ <i class="fas fa-info-circle text-gray-400"></i>
1065
+ <span class="tooltip-text">${email.details}${email.suggestion ? `<br><br>Suggestion: ${email.suggestion}` : ''}</span>
1066
+ </div>
1067
+ ${email.suggestion ? `<span class="ml-2">${email.suggestion}</span>` : ''}
1068
+ </td>
1069
+ <td class="px-4 py-3 whitespace-nowrap text-sm text-gray-600">
1070
+ <div class="tooltip">
1071
+ <i class="fas fa-server text-gray-400"></i>
1072
+ <span class="tooltip-text">${email.mxResponse}</span>
1073
+ </div>
1074
+ <span class="ml-2">${email.deliverability}</span>
1075
+ </td>
1076
+ `;
1077
+
1078
+ emailTableBody.appendChild(row);
1079
+ });
1080
+
1081
+ // Store processed emails for download
1082
+ processedEmails = stats.processedEmails;
1083
+ workbook = addValidationResultsToWorkbook(workbook, processedEmails);
1084
+ }
1085
+
1086
+ function addValidationResultsToWorkbook(workbook, processedEmails) {
1087
+ // Create a map of original emails to their validation results
1088
+ const emailMap = {};
1089
+ processedEmails.forEach(email => {
1090
+ emailMap[email.original] = {
1091
+ status: email.status,
1092
+ suggestion: email.suggestion || '',
1093
+ mxResponse: email.mxResponse,
1094
+ deliverability: email.deliverability
1095
+ };
1096
+ });
1097
+
1098
+ // Process each sheet
1099
+ workbook.SheetNames.forEach(sheetName => {
1100
+ const worksheet = workbook.Sheets[sheetName];
1101
+ const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
1102
+
1103
+ // Add headers for new columns if they don't exist
1104
+ if (jsonData.length > 0) {
1105
+ const headers = jsonData[0];
1106
+ if (!headers.includes('Email Status')) {
1107
+ headers.push('Email Status');
1108
+ headers.push('Suggestion');
1109
+ headers.push('MX Response');
1110
+ headers.push('Deliverability');
1111
+ }
1112
+ }
1113
+
1114
+ // Process each row
1115
+ for (let i = 1; i < jsonData.length; i++) {
1116
+ const row = jsonData[i];
1117
+ if (!Array.isArray(row)) continue;
1118
+
1119
+ // Find email in row
1120
+ let emailInRow = null;
1121
+ for (let j = 0; j < row.length; j++) {
1122
+ const cell = row[j];
1123
+ if (typeof cell === 'string' && isValidEmailSyntax(cell.trim())) {
1124
+ emailInRow = cell.trim();
1125
+ break;
1126
+ }
1127
+ }
1128
+
1129
+ // Add validation results
1130
+ if (emailInRow && emailMap[emailInRow]) {
1131
+ // Make sure row has enough columns
1132
+ while (row.length < jsonData[0].length - 4) {
1133
+ row.push('');
1134
+ }
1135
+
1136
+ row.push(emailMap[emailInRow].status);
1137
+ row.push(emailMap[emailInRow].suggestion);
1138
+ row.push(emailMap[emailInRow].mxResponse);
1139
+ row.push(emailMap[emailInRow].deliverability);
1140
+ } else {
1141
+ // For rows without email or invalid email
1142
+ while (row.length < jsonData[0].length - 4) {
1143
+ row.push('');
1144
+ }
1145
+
1146
+ row.push('No valid email');
1147
+ row.push('');
1148
+ row.push('');
1149
+ row.push('');
1150
+ }
1151
+ }
1152
+
1153
+ // Convert back to worksheet
1154
+ const newWorksheet = XLSX.utils.aoa_to_sheet(jsonData);
1155
+ workbook.Sheets[sheetName] = newWorksheet;
1156
+ });
1157
+
1158
+ return workbook;
1159
+ }
1160
+
1161
+ function downloadCleanedFile() {
1162
+ if (!workbook) return;
1163
+
1164
+ // Convert workbook to binary
1165
+ const wbout = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
1166
+
1167
+ // Create blob and download
1168
+ const blob = new Blob([wbout], { type: 'application/octet-stream' });
1169
+ saveAs(blob, 'cleaned_emails.xlsx');
1170
+ }
1171
+
1172
+ function downloadSummaryReport() {
1173
+ // In a real implementation, this would generate a PDF report
1174
+ // For this demo, we'll create a more detailed text file
1175
+
1176
+ let reportText = `EMAIL VALIDATION REPORT\n`;
1177
+ reportText += `================================\n`;
1178
+ reportText += `Generated on: ${new Date().toLocaleString()}\n\n`;
1179
+
1180
+ // Summary stats
1181
+ reportText += `SUMMARY STATISTICS\n`;
1182
+ reportText += `------------------\n`;
1183
+ reportText += `Total Emails Processed: ${totalEmails.textContent}\n`;
1184
+ reportText += `Valid Emails: ${finalValid.textContent} (${Math.round((finalValid.textContent / totalEmails.textContent) * 100)}%)\n`;
1185
+ reportText += `Invalid Emails: ${finalInvalid.textContent} (${Math.round((finalInvalid.textContent / totalEmails.textContent) * 100)}%)\n\n`;
1186
+
1187
+ // Detailed issues
1188
+ reportText += `DETAILED ISSUES\n`;
1189
+ reportText += `---------------\n`;
1190
+ reportText += `- Duplicates: ${duplicateCount.textContent}\n`;
1191
+ reportText += `- Typos Found: ${typoCount.textContent}\n`;
1192
+ reportText += `- Syntax Errors: ${syntaxCount.textContent}\n`;
1193
+ reportText += `- MX Record Issues: ${mxCount.textContent}\n`;
1194
+ reportText += `- Undeliverable: ${undeliverableCount.textContent}\n`;
1195
+ reportText += `- Unknown Status: ${unknownCount.textContent}\n\n`;
1196
+
1197
+ // MX Analysis
1198
+ reportText += `MX RECORD ANALYSIS\n`;
1199
+ reportText += `------------------\n`;
1200
+ reportText += `Emails with valid MX records: ${validMxCount.textContent} (${validMxPercent.textContent}%)\n`;
1201
+ reportText += `Emails with MX issues: ${invalidMxCount.textContent}\n\n`;
1202
+
1203
+ // Top MX issues
1204
+ const topMxDomains = document.querySelectorAll('#top-mx-issues div');
1205
+ if (topMxDomains.length > 0) {
1206
+ reportText += `Top Domains with MX Issues:\n`;
1207
+ topMxDomains.forEach(domain => {
1208
+ reportText += ` - ${domain.textContent.trim()}\n`;
1209
+ });
1210
+ reportText += `\n`;
1211
+ }
1212
+
1213
+ // Deliverability Analysis
1214
+ reportText += `DELIVERABILITY ANALYSIS\n`;
1215
+ reportText += `-----------------------\n`;
1216
+ reportText += `Confirmed Deliverable: ${deliverableCount.textContent} (${deliverablePercent.textContent}%)\n`;
1217
+ reportText += `Undeliverable: ${undeliverableInsightCount.textContent}\n`;
1218
+ reportText += `Unknown Status: ${unknownDeliverabilityCount.textContent}\n\n`;
1219
+ reportText += `Overall Deliverability Score: ${deliverabilityScore.textContent}/100\n`;
1220
+ reportText += `Rating: ${deliverabilityRating.textContent}\n`;
1221
+ reportText += `Description: ${deliverabilityDescription.textContent}\n\n`;
1222
+
1223
+ // Recommendations
1224
+ reportText += `RECOMMENDATIONS\n`;
1225
+ reportText += `---------------\n`;
1226
+ if (parseInt(mxCount.textContent) > 0) {
1227
+ reportText += `1. Address MX record issues for ${mxCount.textContent} emails to improve deliverability\n`;
1228
+ }
1229
+ if (parseInt(typoCount.textContent) > 0) {
1230
+ reportText += `2. Review ${typoCount.textContent} emails with potential typos for correction\n`;
1231
+ }
1232
+ if (parseInt(duplicateCount.textContent) > 0) {
1233
+ reportText += `3. Remove ${duplicateCount.textContent} duplicate emails to maintain list quality\n`;
1234
+ }
1235
+ if (parseInt(undeliverableCount.textContent) > 0) {
1236
+ reportText += `4. Remove or verify ${undeliverableCount.textContent} undeliverable emails to improve sender reputation\n`;
1237
+ }
1238
+
1239
+ const blob = new Blob([reportText], { type: 'text/plain;charset=utf-8' });
1240
+ saveAs(blob, 'email_validation_report.txt');
1241
+ }
1242
+
1243
+ function showError(message) {
1244
+ uploadSection.classList.add('hidden');
1245
+ processingSection.classList.add('hidden');
1246
+ resultsSection.classList.add('hidden');
1247
+ errorSection.classList.remove('hidden');
1248
+
1249
+ document.getElementById('error-message').textContent = message;
1250
+ }
1251
+
1252
+ function resetForm() {
1253
+ uploadSection.classList.remove('hidden');
1254
+ processingSection.classList.add('hidden');
1255
+ resultsSection.classList.add('hidden');
1256
+ errorSection.classList.add('hidden');
1257
+
1258
+ // Reset progress
1259
+ progressBar.style.width = '0%';
1260
+ progressPercent.textContent = '0%';
1261
+ processedCount.textContent = '0';
1262
+ validCount.textContent = '0';
1263
+ issuesCount.textContent = '0';
1264
+
1265
+ // Reset file input
1266
+ fileUpload.value = '';
1267
+
1268
+ // Clear data
1269
+ emailData = [];
1270
+ processedEmails = [];
1271
+ workbook = null;
1272
+ domainStats = {};
1273
+ }
1274
+ });
1275
+ </script>
1276
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=sqibhe/email-validation" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
1277
+ </html>
prompts.txt ADDED
File without changes