// Utility: Save and load credentials function saveCredentials(username, password) { localStorage.setItem('username', username); localStorage.setItem('password', password); } function getCredentials() { return { username: localStorage.getItem('username'), password: localStorage.getItem('password') }; } function clearCredentials() { localStorage.removeItem('username'); localStorage.removeItem('password'); } function logout() { clearCredentials(); window.location.href = 'login.html'; } // Registration if (document.getElementById('registerForm')) { document.getElementById('registerForm').onsubmit = async function(e) { e.preventDefault(); const username = document.getElementById('registerUsername').value; const password = document.getElementById('registerPassword').value; const res = await fetch('http://localhost:8080/users', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }) }); if (res.ok) { saveCredentials(username, password); window.location.href = 'inbox.html'; } else { const err = await res.text(); document.getElementById('registerError').innerText = err; } }; } // Login if (document.getElementById('loginForm')) { document.getElementById('loginForm').onsubmit = async function(e) { e.preventDefault(); const username = document.getElementById('loginUsername').value; const password = document.getElementById('loginPassword').value; // Try to fetch mailbox to verify credentials const res = await fetch(`http://localhost:8080/mailbox?user=${encodeURIComponent(username)}`, { headers: { 'Authorization': 'Basic ' + btoa(username + ':' + password) } }); if (res.ok) { saveCredentials(username, password); window.location.href = 'inbox.html'; } else { document.getElementById('loginError').innerText = 'Invalid username or password.'; } }; } // Inbox if (document.getElementById('email-list')) { const { username, password } = getCredentials(); if (!username || !password) { window.location.href = 'login.html'; } else { fetch(`http://localhost:8080/mailbox?user=${encodeURIComponent(username)}`, { headers: { 'Authorization': 'Basic ' + btoa(username + ':' + password) } }) .then(res => res.json()) .then(emails => { if (!Array.isArray(emails)) throw new Error('Invalid mailbox response'); let userDomain = null; for (const email of emails) { if (email.to === username && email.domain) { userDomain = email.domain; break; } if (email.from === username && email.domain) { userDomain = email.domain; break; } } const userFull = userDomain ? `${username}!${userDomain}` : username; const inboxEmails = emails.filter(email => { if (!email.to) return false; const toFull = email.domain ? `${email.to}!${email.domain}` : email.to; return toFull === userFull; }); const sentEmails = emails.filter(email => { if (!email.from) return false; const fromFull = email.domain ? `${email.from}!${email.domain}` : email.from; return fromFull === userFull; }); let currentFolder = 'inbox'; let selectedEmail = null; function renderList() { const list = currentFolder === 'inbox' ? inboxEmails : sentEmails; let html = `
${currentFolder === 'inbox' ? 'Inbox' : 'Sent'}
`; if (list.length === 0) { html += '

No emails.

'; } else { html += list.map((email, idx) => { const display = currentFolder === 'inbox' ? (email.domain ? `${email.from}!${email.domain}` : email.from) : (email.domain ? `${email.to}!${email.domain}` : email.to); const fromto = currentFolder === 'inbox' ? `From: ${display}` : `To: ${display}`; return `
${email.subject}
${fromto}
`; }).join(''); } html += '
'; document.getElementById('email-list').innerHTML = html; // Add click listeners document.querySelectorAll('.email-list-item').forEach(item => { item.onclick = function() { selectedEmail = parseInt(this.getAttribute('data-idx')); renderList(); renderDetail(); }; }); } function renderDetail() { const list = currentFolder === 'inbox' ? inboxEmails : sentEmails; if (selectedEmail == null || !list[selectedEmail]) { document.getElementById('email-detail').innerHTML = ''; return; } const email = list[selectedEmail]; const fromDisplay = email.domain ? `${email.from}!${email.domain}` : email.from; const toDisplay = email.domain ? `${email.to}!${email.domain}` : email.to; document.getElementById('email-detail').innerHTML = `
From: ${fromDisplay}
To: ${toDisplay}
Subject: ${email.subject}
${email.body}
`; } // Sidebar folder switching document.getElementById('sidebar-inbox').onclick = function() { currentFolder = 'inbox'; selectedEmail = null; document.getElementById('sidebar-inbox').classList.add('active'); document.getElementById('sidebar-sent').classList.remove('active'); renderList(); renderDetail(); }; document.getElementById('sidebar-sent').onclick = function() { currentFolder = 'sent'; selectedEmail = null; document.getElementById('sidebar-inbox').classList.remove('active'); document.getElementById('sidebar-sent').classList.add('active'); renderList(); renderDetail(); }; renderList(); renderDetail(); }) .catch(err => { document.getElementById('inboxError').innerText = 'Failed to load inbox.'; }); } } // Send Email if (document.getElementById('sendForm')) { document.getElementById('sendForm').onsubmit = async function(e) { e.preventDefault(); const { username, password } = getCredentials(); if (!username || !password) { window.location.href = 'login.html'; return; } const toField = document.getElementById('to').value.trim(); // Require ! format if (!/^\w+!.+/.test(toField)) { document.getElementById('sendError').innerText = 'Recipient must be in the format username!domain'; return; } let to = toField; let domain = ''; if (toField.includes('!')) { [to, domain] = toField.split('!'); } const subject = document.getElementById('subject').value; const body = document.getElementById('body').value; const email = domain ? { from: username, to, domain, subject, body } : { from: username, to, subject, body }; const res = await fetch('http://localhost:8080/email', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Basic ' + btoa(username + ':' + password) }, body: JSON.stringify(email) }); if (res.ok) { window.location.href = 'inbox.html'; } else { const err = await res.text(); document.getElementById('sendError').innerText = err; } }; } // Compose Overlay logic if (document.getElementById('openComposeBtn')) { const overlay = document.getElementById('composeOverlay'); const openBtn = document.getElementById('openComposeBtn'); const closeBtn = document.getElementById('closeComposeBtn'); const form = document.getElementById('composeForm'); const errorP = document.getElementById('composeError'); openBtn.onclick = function() { overlay.style.display = 'flex'; form.reset(); errorP.innerText = ''; }; closeBtn.onclick = function() { overlay.style.display = 'none'; }; form.onsubmit = async function(e) { e.preventDefault(); const { username, password } = getCredentials(); if (!username || !password) { window.location.href = 'login.html'; return; } const toField = document.getElementById('composeTo').value.trim(); if (!/^\w+!.+/.test(toField)) { errorP.innerText = 'Recipient must be in the format username!domain'; return; } let to = toField; let domain = ''; if (toField.includes('!')) { [to, domain] = toField.split('!'); } const subject = document.getElementById('composeSubject').value; const body = document.getElementById('composeBody').value; const email = domain ? { from: username, to, domain, subject, body } : { from: username, to, subject, body }; const res = await fetch('http://localhost:8080/email', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Basic ' + btoa(username + ':' + password) }, body: JSON.stringify(email) }); if (res.ok) { overlay.style.display = 'none'; location.reload(); } else { const err = await res.text(); errorP.innerText = err; } }; }