added more checks to email verif

This commit is contained in:
durn
2026-04-29 12:14:00 -06:00
parent 57e3115634
commit f9dfbc813a
3 changed files with 82 additions and 10 deletions
@@ -20,16 +20,22 @@ public class EmailController {
@Autowired
private EmailService emailService;
@PostMapping("/check")
public ResponseEntity<?> check(@RequestParam String email){
if (emailService.isValidEmail(email) == false) {
return ResponseEntity.status(429).body("Invalid Email Detected.");
}
return ResponseEntity.ok().build();
}
@PostMapping("/send")
public ResponseEntity<?> send(@RequestParam String email) {
if (!otpStore.canResend(email)) {
return ResponseEntity.status(429).body("Please wait before requesting another code.");
try {
emailService.sendOtpEmail(email);
return ResponseEntity.ok().build();
} catch (RuntimeException e) {
return ResponseEntity.status(500).body("Failed to send verification email.");
}
emailService.sendOtpEmail(email);
return ResponseEntity.ok().build();
}
@@ -1,9 +1,18 @@
package com.example.demo.service;
import java.util.Hashtable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import jakarta.mail.internet.AddressException;
import jakarta.mail.internet.InternetAddress;
@Service
public class EmailService {
@@ -29,6 +38,45 @@ public class EmailService {
"The Thyme Crunch Team"
);
mailSender.send(message);
try {
mailSender.send(message);
} catch (MailException e) {
otpStore.clear(toEmail);
throw new RuntimeException("Failed to send email to: " + toEmail, e);
}
}
public boolean isValidEmail(String email) {
if (email == null || email.isBlank()) return false;
String emailRegex = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$";
if (!email.matches(emailRegex)) return false;
try {
InternetAddress emailAddr = new InternetAddress(email, true);
emailAddr.validate();
} catch (AddressException ex) {
return false;
}
String domain = email.substring(email.indexOf('@') + 1);
return hasMxRecord(domain);
}
private boolean hasMxRecord(String domain) {
try {
Hashtable<String, String> env = new Hashtable<>();
env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
env.put("java.naming.provider.url", "dns:");
env.put("com.sun.jndi.dns.timeout.initial", "2000");
env.put("com.sun.jndi.dns.timeout.retries", "1");
DirContext ctx = new InitialDirContext(env);
Attributes attrs = ctx.getAttributes(domain, new String[]{"MX"});
return attrs.get("MX") != null;
} catch (Exception e) {
return false;
}
}
}
@@ -146,6 +146,18 @@ function isProfane(str) {
const csrfHeader = document.querySelector('meta[name="_csrf_header"]').getAttribute('content');
try {
const checkResponse = await fetch(`/api/email/check?email=${encodeURIComponent(email)}`, {
method: "POST",
headers: { [csrfHeader]: csrfToken }
});
if (!checkResponse.ok) {
const errorText = await checkResponse.text();
passwordError.style.color = "red";
passwordError.textContent = errorText || "Invalid Email Detected.";
return;
}
sessionStorage.setItem("pendingEmail", email);
sessionStorage.setItem("pendingUser", JSON.stringify({
username: name,
@@ -154,10 +166,16 @@ function isProfane(str) {
role: "ROLE_USER"
}));
await fetch(`/api/email/send?email=${encodeURIComponent(email)}`, {
const sendResponse = await fetch(`/api/email/send?email=${encodeURIComponent(email)}`, {
method: "POST",
headers: { [csrfHeader]: csrfToken }
});
if (!sendResponse.ok) {
passwordError.style.color = "red";
passwordError.textContent = "Failed to send verification email. Please check your address.";
return;
}
passwordError.style.color = "green";
passwordError.textContent = "Check your email for a verification code...";
@@ -170,7 +188,7 @@ function isProfane(str) {
passwordError.textContent = "Could not connect to the server.";
console.error("Request error:", error);
}
});
});
});
});
</script>