diff --git a/.github/workflows/sonarqube.yml b/.github/workflows/sonarqube.yml
index 89fb05fe1c1c6f0a9aabe9a034320ee6789dc372..a74e1d6a911805b26a95eb345be549afb55b81ee 100644
--- a/.github/workflows/sonarqube.yml
+++ b/.github/workflows/sonarqube.yml
@@ -1,10 +1,8 @@
-name: Build
-
+name: SonarQube
 on:
   push:
     branches:
-      - main
-      - staging
+      - '*'
   pull_request:
     types: [opened, synchronize, reopened]
 
diff --git a/pom.xml b/pom.xml
index 9241721030bf479832618ab802d0c51a37e5e12f..a63ccbe75f2dd4fdd2e922b756d2fa0629cd1ae7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,6 +28,8 @@
 	</scm>
 	<properties>
 		<java.version>21</java.version>
+		<sonar.organization>safetypin-official</sonar.organization>
+		<sonar.host.url>https://sonarcloud.io</sonar.host.url>
 	</properties>
 	<dependencyManagement>
 		<dependencies>
@@ -74,6 +76,24 @@
 			<scope>test</scope>
 		</dependency>
 
+		<!-- Spring Mail + testing suite -->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-mail</artifactId>
+			<version>3.4.2</version>
+		</dependency>
+		<dependency>
+			<groupId>com.icegreen</groupId>
+			<artifactId>greenmail-junit5</artifactId>
+			<version>2.1.3</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>javax.activation</groupId>
+			<artifactId>activation</artifactId>
+			<version>1.1.1</version>
+		</dependency>
+
 		<!-- JUnit 5 for unit and regression testing -->
 		<dependency>
 			<groupId>org.junit.jupiter</groupId>
diff --git a/src/main/java/com/safetypin/authentication/AuthenticationApplication.java b/src/main/java/com/safetypin/authentication/AuthenticationApplication.java
index b54a9d5381a33cdf0bc8f447f1dcd01b76f08e7f..4a2663bc70b02db96bfcabb9312ae35a510ae936 100644
--- a/src/main/java/com/safetypin/authentication/AuthenticationApplication.java
+++ b/src/main/java/com/safetypin/authentication/AuthenticationApplication.java
@@ -8,17 +8,17 @@ import org.springframework.web.bind.annotation.RestController;
 
 @SpringBootApplication
 public class AuthenticationApplication {
-	public static void main(String[] args) {
-		SpringApplication.run(AuthenticationApplication.class, args);
-	}
+    public static void main(String[] args) {
+        SpringApplication.run(AuthenticationApplication.class, args);
+    }
 
 }
 
 @RestController
 @RequestMapping("/")
 class HelloController {
-	@GetMapping
-	public String sayHello() {
-		return "Hello, World!";
-	}
+    @GetMapping
+    public String sayHello() {
+        return "Hello, World!";
+    }
 }
\ No newline at end of file
diff --git a/src/main/java/com/safetypin/authentication/config/AsyncConfig.java b/src/main/java/com/safetypin/authentication/config/AsyncConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..a8367a78f00cd7a989e09feb147d673d547c2029
--- /dev/null
+++ b/src/main/java/com/safetypin/authentication/config/AsyncConfig.java
@@ -0,0 +1,24 @@
+package com.safetypin.authentication.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.Executor;
+
+@Configuration
+@EnableAsync
+public class AsyncConfig {
+
+    @Bean(name = "emailTaskExecutor")
+    public Executor taskExecutor() {
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        executor.setCorePoolSize(2);
+        executor.setMaxPoolSize(5);
+        executor.setQueueCapacity(100);
+        executor.setThreadNamePrefix("EmailThread-");
+        executor.initialize();
+        return executor;
+    }
+}
diff --git a/src/main/java/com/safetypin/authentication/controller/AuthenticationController.java b/src/main/java/com/safetypin/authentication/controller/AuthenticationController.java
index 7ca84622cbdab798b161cdf8726b879bea775321..0869e05fe92245a14d85d5640e5c1d2a91047580 100644
--- a/src/main/java/com/safetypin/authentication/controller/AuthenticationController.java
+++ b/src/main/java/com/safetypin/authentication/controller/AuthenticationController.java
@@ -4,12 +4,12 @@ import com.safetypin.authentication.dto.*;
 import com.safetypin.authentication.exception.InvalidCredentialsException;
 import com.safetypin.authentication.exception.UserAlreadyExistsException;
 import com.safetypin.authentication.service.AuthenticationService;
+import jakarta.validation.Valid;
 import com.safetypin.authentication.service.GoogleAuthService;
 import com.safetypin.authentication.service.JwtService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
-import jakarta.validation.Valid;
 import org.springframework.web.bind.annotation.*;
 
 @RestController
@@ -53,13 +53,14 @@ public class AuthenticationController {
 
     }
 
+
     // Endpoint for email login
     @PostMapping("/login-email")
     public ResponseEntity<AuthResponse> loginEmail(@RequestParam String email, @RequestParam String password) {
         try {
             String jwt = authenticationService.loginUser(email, password);
             return ResponseEntity.ok(new AuthResponse(true, "OK", new Token(jwt)));
-        } catch (InvalidCredentialsException e){
+        } catch (InvalidCredentialsException e) {
             AuthResponse response = new AuthResponse(false, e.getMessage(), null);
             return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
         }
diff --git a/src/main/java/com/safetypin/authentication/dto/AuthResponse.java b/src/main/java/com/safetypin/authentication/dto/AuthResponse.java
index a29962ff41457e80c4adbbb6f198b35b121751b4..6dab9c4cf1de8eece2643d5c09035a53ac7ba3e3 100644
--- a/src/main/java/com/safetypin/authentication/dto/AuthResponse.java
+++ b/src/main/java/com/safetypin/authentication/dto/AuthResponse.java
@@ -1,6 +1,9 @@
 package com.safetypin.authentication.dto;
 
-import lombok.*;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
 
 @Data
 @Getter
diff --git a/src/main/java/com/safetypin/authentication/dto/ErrorResponse.java b/src/main/java/com/safetypin/authentication/dto/ErrorResponse.java
index e7bb4102d7b8ee0ef4a89fd83cbef9406ccb6922..110cb738155cc93c353937b3947a836ed825894c 100644
--- a/src/main/java/com/safetypin/authentication/dto/ErrorResponse.java
+++ b/src/main/java/com/safetypin/authentication/dto/ErrorResponse.java
@@ -11,7 +11,7 @@ import java.time.LocalDateTime;
 @Getter
 @Setter
 @NoArgsConstructor
-public class ErrorResponse{
+public class ErrorResponse {
     private int status;
     private String message;
     private LocalDateTime timestamp;
diff --git a/src/main/java/com/safetypin/authentication/dto/UserResponse.java b/src/main/java/com/safetypin/authentication/dto/UserResponse.java
index be8d012012efb11128b24114879a31afb2f697b0..736e217c98e5af268455783892bfd476923d33c5 100644
--- a/src/main/java/com/safetypin/authentication/dto/UserResponse.java
+++ b/src/main/java/com/safetypin/authentication/dto/UserResponse.java
@@ -1,6 +1,9 @@
 package com.safetypin.authentication.dto;
 
-import lombok.*;
+import lombok.Builder;
+import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
 
 import java.time.LocalDate;
 import java.util.UUID;
diff --git a/src/main/java/com/safetypin/authentication/exception/OTPException.java b/src/main/java/com/safetypin/authentication/exception/OTPException.java
new file mode 100644
index 0000000000000000000000000000000000000000..897c8b90c87757f8c4894f68d128bdc355d0cadb
--- /dev/null
+++ b/src/main/java/com/safetypin/authentication/exception/OTPException.java
@@ -0,0 +1,7 @@
+package com.safetypin.authentication.exception;
+
+public class OTPException extends RuntimeException {
+    public OTPException(String message) {
+        super(message);
+    }
+}
diff --git a/src/main/java/com/safetypin/authentication/model/Role.java b/src/main/java/com/safetypin/authentication/model/Role.java
new file mode 100644
index 0000000000000000000000000000000000000000..38c5972169a47c0d782419cb239a47a62d2294a4
--- /dev/null
+++ b/src/main/java/com/safetypin/authentication/model/Role.java
@@ -0,0 +1,7 @@
+package com.safetypin.authentication.model;
+
+public enum Role {
+    REGISTERED_USER,
+    PREMIUM_USER,
+    MODERATOR
+}
diff --git a/src/main/java/com/safetypin/authentication/model/User.java b/src/main/java/com/safetypin/authentication/model/User.java
index 63f738b505d663715566e2da56d35a9180dc2433..7fd5f65f99ed01e7058afb07ad8b8dbb267984c2 100644
--- a/src/main/java/com/safetypin/authentication/model/User.java
+++ b/src/main/java/com/safetypin/authentication/model/User.java
@@ -14,54 +14,64 @@ import java.util.UUID;
 @NoArgsConstructor
 public class User {
     @Id
-    @Setter @Getter
+    @Setter
+    @Getter
     @GeneratedValue(strategy = GenerationType.UUID)
     private UUID id;
 
-    @Setter @Getter
+    @Setter
+    @Getter
     @Column(nullable = false, unique = true)
     private String email;
 
     // May be null for social login users
-    @Setter @Getter
+    @Setter
+    @Getter
+    @Column(nullable = false)
     private String password;
 
-    @Setter @Getter
+    @Setter
+    @Getter
     @Column(nullable = false)
     private String name;
 
     @Column(nullable = false)
     private boolean isVerified = false;
 
-    @Setter @Getter
-    private String role;
+    @Setter
+    @Getter
+    @Enumerated(EnumType.STRING)
+    private Role role;
 
     // New fields
-    @Setter @Getter
+    @Setter
+    @Getter
     private LocalDate birthdate;
 
-    @Setter  @Getter
+    @Setter
+    @Getter
     private String provider;  // "EMAIL", "GOOGLE", "APPLE"
 
+
     // Getters and setters
 
     public boolean isVerified() {
         return isVerified;
     }
+
     public void setVerified(boolean verified) {
         isVerified = verified;
     }
 
-    public UserResponse generateUserResponse(){
+    public UserResponse generateUserResponse() {
         return UserResponse.builder()
                 .email(email)
                 .id(id)
                 .provider(provider)
                 .birthdate(birthdate)
-                .role(role)
+                .role(role != null ? role.name() : null)
                 .name(name)
                 .isVerified(isVerified)
                 .build();
     }
-
 }
diff --git a/src/main/java/com/safetypin/authentication/repository/UserRepository.java b/src/main/java/com/safetypin/authentication/repository/UserRepository.java
index f95b36e46e310152b9104b1b1fb8ef892c4d7597..1370373728acefe890fe282fd6107d353c3dc66c 100644
--- a/src/main/java/com/safetypin/authentication/repository/UserRepository.java
+++ b/src/main/java/com/safetypin/authentication/repository/UserRepository.java
@@ -1,12 +1,15 @@
 package com.safetypin.authentication.repository;
 
+import com.safetypin.authentication.model.Role;
+import com.safetypin.authentication.model.User;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.stereotype.Repository;
-import com.safetypin.authentication.model.User;
 
 import java.util.UUID;
 
 @Repository
 public interface UserRepository extends JpaRepository<User, UUID> {
     User findByEmail(String email);
+
+    User findByRole(Role role);
 }
diff --git a/src/main/java/com/safetypin/authentication/security/PasswordEncoderConfig.java b/src/main/java/com/safetypin/authentication/security/PasswordEncoderConfig.java
index a4e107fa1ac73de8fa0c5389dcca59178bcf043e..1dbb102c31430d88ab9945b7818c182a1a02553e 100644
--- a/src/main/java/com/safetypin/authentication/security/PasswordEncoderConfig.java
+++ b/src/main/java/com/safetypin/authentication/security/PasswordEncoderConfig.java
@@ -11,4 +11,4 @@ public class PasswordEncoderConfig {
     public PasswordEncoder passwordEncoder() {
         return new BCryptPasswordEncoder();
     }
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/safetypin/authentication/security/SecurityConfig.java b/src/main/java/com/safetypin/authentication/security/SecurityConfig.java
index e4483b6ace1e6990f50540772ee0c5d893e44190..20ab02f50ce8dd3852704388e9dda1f1ec602132 100644
--- a/src/main/java/com/safetypin/authentication/security/SecurityConfig.java
+++ b/src/main/java/com/safetypin/authentication/security/SecurityConfig.java
@@ -31,4 +31,4 @@ public class SecurityConfig {
     public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
         return authenticationConfiguration.getAuthenticationManager();
     }
-}
+}
\ No newline at end of file
diff --git a/src/main/java/com/safetypin/authentication/seeder/DevDataSeeder.java b/src/main/java/com/safetypin/authentication/seeder/DevDataSeeder.java
index 9a2f3f97063e8e6d0c8e40f26bfbbf74424f668b..2018c87adba7ba92f8d4c5c454b19c8348e5281a 100644
--- a/src/main/java/com/safetypin/authentication/seeder/DevDataSeeder.java
+++ b/src/main/java/com/safetypin/authentication/seeder/DevDataSeeder.java
@@ -1,9 +1,8 @@
 package com.safetypin.authentication.seeder;
 
+import com.safetypin.authentication.model.Role;
 import com.safetypin.authentication.model.User;
 import com.safetypin.authentication.repository.UserRepository;
-import static com.safetypin.authentication.service.AuthenticationService.EMAIL_PROVIDER;
-
 import jakarta.annotation.PostConstruct;
 import org.springframework.context.annotation.Profile;
 import org.springframework.security.crypto.password.PasswordEncoder;
@@ -11,6 +10,8 @@ import org.springframework.stereotype.Component;
 
 import java.time.LocalDate;
 
+import static com.safetypin.authentication.service.AuthenticationService.EMAIL_PROVIDER;
+
 @Component
 @Profile({"dev"})
 public class DevDataSeeder implements Runnable {
@@ -38,7 +39,7 @@ public class DevDataSeeder implements Runnable {
             user1.setPassword(passwordEncoder.encode("password1")); //NOSONAR
             user1.setName("User One");
             user1.setVerified(true);
-            user1.setRole("user");
+            user1.setRole(Role.REGISTERED_USER);
             user1.setBirthdate(LocalDate.of(1990, 1, 1));
             user1.setProvider(EMAIL_PROVIDER);
             userRepository.save(user1);
@@ -48,7 +49,7 @@ public class DevDataSeeder implements Runnable {
             user2.setPassword(passwordEncoder.encode("password2")); //NOSONAR
             user2.setName("User Two");
             user2.setVerified(true);
-            user2.setRole("user");
+            user2.setRole(Role.REGISTERED_USER);
             user2.setBirthdate(LocalDate.of(1991, 2, 2));
             user2.setProvider(EMAIL_PROVIDER);
             userRepository.save(user2);
@@ -59,7 +60,7 @@ public class DevDataSeeder implements Runnable {
             user3.setPassword(passwordEncoder.encode("password3")); //NOSONAR
             user3.setName("User Three");
             user3.setVerified(true);
-            user3.setRole("user");
+            user3.setRole(Role.REGISTERED_USER);
             user3.setBirthdate(LocalDate.of(1992, 3, 3));
             user3.setProvider(EMAIL_PROVIDER);
             userRepository.save(user3);
@@ -69,7 +70,7 @@ public class DevDataSeeder implements Runnable {
             user4.setPassword(passwordEncoder.encode("password4")); //NOSONAR
             user4.setName("User Four");
             user4.setVerified(true);
-            user4.setRole("user");
+            user4.setRole(Role.REGISTERED_USER);
             user4.setBirthdate(LocalDate.of(1993, 4, 4));
             user4.setProvider(EMAIL_PROVIDER);
             userRepository.save(user4);
@@ -79,10 +80,18 @@ public class DevDataSeeder implements Runnable {
             user5.setPassword(passwordEncoder.encode("password5")); //NOSONAR
             user5.setName("User Five");
             user5.setVerified(true);
-            user5.setRole("user");
+            user5.setRole(Role.PREMIUM_USER);
             user5.setBirthdate(LocalDate.of(1994, 5, 5));
             user5.setProvider(EMAIL_PROVIDER);
             userRepository.save(user5);
+
+            User user6 = new User();
+            user6.setEmail("user6@example.com");
+            user6.setPassword(passwordEncoder.encode("password6")); //NOSONAR
+            user6.setName("User Six");
+            user6.setVerified(true);
+            user6.setRole(Role.MODERATOR);
+
         }
     }
 }
diff --git a/src/main/java/com/safetypin/authentication/service/AuthenticationService.java b/src/main/java/com/safetypin/authentication/service/AuthenticationService.java
index e351df0cd36866c84b848d21e2238b50b0b327e2..064d215910db7c568e17df7567b26a51c294da1e 100644
--- a/src/main/java/com/safetypin/authentication/service/AuthenticationService.java
+++ b/src/main/java/com/safetypin/authentication/service/AuthenticationService.java
@@ -3,6 +3,7 @@ package com.safetypin.authentication.service;
 import com.safetypin.authentication.dto.RegistrationRequest;
 import com.safetypin.authentication.exception.InvalidCredentialsException;
 import com.safetypin.authentication.exception.UserAlreadyExistsException;
+import com.safetypin.authentication.model.Role;
 import com.safetypin.authentication.model.User;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -48,7 +49,7 @@ public class AuthenticationService {
         user.setPassword(encodedPassword);
         user.setName(request.getName());
         user.setVerified(false);
-        user.setRole("USER");
+        user.setRole(Role.REGISTERED_USER);
         user.setBirthdate(request.getBirthdate());
         user.setProvider(EMAIL_PROVIDER);
         user = userService.save(user);
diff --git a/src/main/java/com/safetypin/authentication/service/EmailService.java b/src/main/java/com/safetypin/authentication/service/EmailService.java
new file mode 100644
index 0000000000000000000000000000000000000000..498cf9de236e2a7843fcb26cbf480fc0458696fb
--- /dev/null
+++ b/src/main/java/com/safetypin/authentication/service/EmailService.java
@@ -0,0 +1,77 @@
+package com.safetypin.authentication.service;
+
+import jakarta.mail.internet.MimeMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.mail.javamail.MimeMessageHelper;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+import java.util.concurrent.CompletableFuture;
+
+@Service
+public class EmailService {
+    private static final Logger logger = LoggerFactory.getLogger(EmailService.class);
+    private static final String SENDER = "noreply@safetyp.in";
+    private final JavaMailSender mailSender;
+
+    @Autowired
+    public EmailService(JavaMailSender mailSender) {
+        this.mailSender = mailSender;
+    }
+
+    @Async("emailTaskExecutor")
+    public CompletableFuture<Boolean> sendOTPMail(String to, String otp) {
+        try {
+            MimeMessage mimeMessage = mailSender.createMimeMessage();
+            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, "utf-8");
+
+            helper.setFrom(SENDER);
+            helper.setTo(to);
+            helper.setSubject("OTP Code for SafetyPin");
+
+            String htmlContent =
+                    "<!DOCTYPE html>" +
+                            "<html>" +
+                            "<head>" +
+                            "    <style>" +
+                            "        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }" +
+                            "        .container { max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #ddd; border-radius: 5px; }" +
+                            "        .header { background-color: #4285f4; color: white; padding: 10px; text-align: center; border-radius: 5px 5px 0 0; }" +
+                            "        .content { padding: 20px; }" +
+                            "        .otp-code { font-size: 24px; font-weight: bold; text-align: center; margin: 20px 0; padding: 10px; background-color: #f0f0f0; border-radius: 4px; letter-spacing: 5px; }" +
+                            "        .footer { font-size: 12px; color: #777; text-align: center; margin-top: 20px; }" +
+                            "    </style>" +
+                            "</head>" +
+                            "<body>" +
+                            "    <div class='container'>" +
+                            "        <div class='header'>" +
+                            "            <h2>SafetyPin Security</h2>" +
+                            "        </div>" +
+                            "        <div class='content'>" +
+                            "            <p>Hello,</p>" +
+                            "            <p>Your one-time verification code is:</p>" +
+                            "            <div class='otp-code'>" + otp + "</div>" +
+                            "            <p>This code will expire in 2 minutes. Please do not share this code with anyone.</p>" +
+                            "            <p>If you didn't request this code, please ignore this email.</p>" +
+                            "        </div>" +
+                            "        <div class='footer'>" +
+                            "            <p>This is an automated message. Please do not reply.</p>" +
+                            "            <p>&copy; " + java.time.Year.now().getValue() + " SafetyPin. All rights reserved.</p>" +
+                            "        </div>" +
+                            "    </div>" +
+                            "</body>" +
+                            "</html>";
+
+            helper.setText(htmlContent, true); // true indicates HTML content
+
+            mailSender.send(mimeMessage);
+            return CompletableFuture.completedFuture(true);
+        } catch (Exception e) {
+            logger.warn("EmailService.sendOTPMail:: Failed to send mail with error; {}", e.getMessage());
+            return CompletableFuture.completedFuture(false);
+        }
+    }
+}
diff --git a/src/main/java/com/safetypin/authentication/service/GoogleAuthService.java b/src/main/java/com/safetypin/authentication/service/GoogleAuthService.java
index 0fab5334bcf136c3edd689c5108cab4d8fb3d310..ce8ef7ad860c7fe5af0ffade7017a4dcfd264664 100644
--- a/src/main/java/com/safetypin/authentication/service/GoogleAuthService.java
+++ b/src/main/java/com/safetypin/authentication/service/GoogleAuthService.java
@@ -15,6 +15,7 @@ import com.safetypin.authentication.dto.GoogleAuthDTO;
 import com.safetypin.authentication.exception.ApiException;
 import com.safetypin.authentication.exception.InvalidCredentialsException;
 import com.safetypin.authentication.exception.UserAlreadyExistsException;
+import com.safetypin.authentication.model.Role;
 import com.safetypin.authentication.model.User;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -77,7 +78,7 @@ public class GoogleAuthService {
             newUser.setPassword(null);
             newUser.setProvider(EMAIL_PROVIDER);
             newUser.setVerified(true);
-            newUser.setRole("USER");
+            newUser.setRole(Role.REGISTERED_USER);
             newUser.setBirthdate(userBirthdate);
 
             User user = userService.save(newUser);
diff --git a/src/main/java/com/safetypin/authentication/service/OTPService.java b/src/main/java/com/safetypin/authentication/service/OTPService.java
index b338aca55d7c58021ce5e648fa48ce1cf362d8dd..1eaf4d51c0adc253861825fd898dd18fa1a9e8ec 100644
--- a/src/main/java/com/safetypin/authentication/service/OTPService.java
+++ b/src/main/java/com/safetypin/authentication/service/OTPService.java
@@ -1,31 +1,53 @@
 package com.safetypin.authentication.service;
 
+import com.safetypin.authentication.exception.OTPException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.security.SecureRandom;
 import java.time.LocalDateTime;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
 
 @Service
 public class OTPService {
-
     private static final long OTP_EXPIRATION_SECONDS = 120; // 2 minutes expiration
     private static final Logger log = LoggerFactory.getLogger(OTPService.class);
+    private final EmailService emailService;
     private final ConcurrentHashMap<String, OTPDetails> otpStorage = new ConcurrentHashMap<>();
     private final SecureRandom random = new SecureRandom();
 
+    @Autowired
+    public OTPService(EmailService emailService) {
+        this.emailService = emailService;
+    }
+
     public String generateOTP(String email) {
         String otp = String.format("%06d", random.nextInt(1000000));
         OTPDetails details = new OTPDetails(otp, LocalDateTime.now());
         otpStorage.put(email, details);
-        // Simulate sending OTP via email (in production, integrate with an email service)
+
+        try {
+            boolean status = emailService.sendOTPMail(email, otp).get();
+            if (!status) {
+                throw new OTPException("Failed to send OTP");
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            Thread.currentThread().interrupt();
+            throw new OTPException("Failed to send OTP: " + e.getMessage());
+        }
+
         log.info("Sending OTP {} to {}", otp, email);
         return otp;
     }
 
     public boolean verifyOTP(String email, String otp) {
+        if (otp == null) {
+            throw new NullPointerException("OTP cannot be null");
+        }
+        
         OTPDetails details = otpStorage.get(email);
         if (details == null) {
             return false;
diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties
index b7c904d50fe81e4261f1b3a6d8da9bc3c7e217cf..c285b8f3a59be337bead1db487bcd7720d6fee81 100644
--- a/src/main/resources/application-dev.properties
+++ b/src/main/resources/application-dev.properties
@@ -1,12 +1,9 @@
 spring.application.name=authentication
-
 spring.datasource.url=jdbc:postgresql://localhost:5432/be-authentication
 spring.datasource.username=postgres
 spring.datasource.password=postgres
-
 spring.datasource.driver-class-name=org.postgresql.Driver
 spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
-
 # Hibernate Properties
 spring.jpa.hibernate.ddl-auto=update
 spring.jpa.show-sql=true
\ No newline at end of file
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index b8b6b6876d8b2a41a1fbac05b638f338a7c41039..1f57723b9a70ad73a3d55c4e9401aa7f9b34885a 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -1,5 +1,15 @@
 spring.application.name=authentication
 spring.profiles.active=${PRODUCTION:dev}
+
+# Spring Mail
+spring.mail.host=smtp.gmail.com
+spring.mail.port=587
+spring.mail.username=${MAIL_EMAIL}
+spring.mail.password=${MAIL_PASSWORD}
+spring.mail.properties.mail.smtp.auth=true
+spring.mail.properties.mail.smtp.starttls.enable=true
+spring.mail.properties.mail.smtp.starttls.required=true
+
 google.client.id=${GOOGLE_CLIENT_ID:default}
 google.client.secret=${GOOGLE_CLIENT_SECRET:default}
 jwt.secret=${JWT_SECRET:biggerboysandstolensweetheartsss}
\ No newline at end of file
diff --git a/src/test/java/com/safetypin/authentication/AuthenticationApplicationTests.java b/src/test/java/com/safetypin/authentication/AuthenticationApplicationTests.java
index a528070135724a4e7a25ed890042dfd3bcf6b5cc..ecb4d4d77cfc758998b5f6d80ff002382cf0eda5 100644
--- a/src/test/java/com/safetypin/authentication/AuthenticationApplicationTests.java
+++ b/src/test/java/com/safetypin/authentication/AuthenticationApplicationTests.java
@@ -1,13 +1,14 @@
 package com.safetypin.authentication;
 
 import org.junit.jupiter.api.Test;
+
 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 
 class AuthenticationApplicationTest {
 
-	@Test
-	void testMainDoesNotThrowException() {
-		// Calling the main method should load the context without throwing an exception.
-		assertDoesNotThrow(() -> AuthenticationApplication.main(new String[] {}));
-	}
+    @Test
+    void testMainDoesNotThrowException() {
+        // Calling the main method should load the context without throwing an exception.
+        assertDoesNotThrow(() -> AuthenticationApplication.main(new String[]{}));
+    }
 }
diff --git a/src/test/java/com/safetypin/authentication/HelloControllerTest.java b/src/test/java/com/safetypin/authentication/HelloControllerTest.java
index cb308d4ee48d94b9afc7856f1d598ef9a30217a3..6b252241af31f1ddb269cd4987e12bbc4557c85e 100644
--- a/src/test/java/com/safetypin/authentication/HelloControllerTest.java
+++ b/src/test/java/com/safetypin/authentication/HelloControllerTest.java
@@ -1,6 +1,7 @@
 package com.safetypin.authentication;
 
 import org.junit.jupiter.api.Test;
+
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 class HelloControllerTest {
diff --git a/src/test/java/com/safetypin/authentication/config/AsyncConfigTest.java b/src/test/java/com/safetypin/authentication/config/AsyncConfigTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..8a38915dac38fb861ed52428d1ad00ca8d44f79b
--- /dev/null
+++ b/src/test/java/com/safetypin/authentication/config/AsyncConfigTest.java
@@ -0,0 +1,52 @@
+package com.safetypin.authentication.config;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@SpringBootTest
+class AsyncConfigTest {
+
+    @Autowired
+    private Executor emailTaskExecutor;
+
+    @Test
+    void testEmailTaskExecutorConfiguration() {
+        // Verify that emailTaskExecutor is not null
+        assertNotNull(emailTaskExecutor, "Email task executor should not be null");
+
+        // Verify that it's a ThreadPoolTaskExecutor instance
+        assertInstanceOf(ThreadPoolTaskExecutor.class, emailTaskExecutor, "Executor should be an instance of ThreadPoolTaskExecutor");
+
+        ThreadPoolTaskExecutor executor = (ThreadPoolTaskExecutor) emailTaskExecutor;
+
+        // Test core pool size
+        assertEquals(2, executor.getCorePoolSize(),
+                "Core pool size should be 2");
+
+        // Test max pool size
+        assertEquals(5, executor.getMaxPoolSize(),
+                "Max pool size should be 5");
+
+        // Test queue capacity
+        assertEquals(100, executor.getQueueCapacity(),
+                "Queue capacity should be 100");
+
+        // Get the actual ThreadPoolExecutor and verify it's initialized
+        ThreadPoolExecutor threadPoolExecutor = executor.getThreadPoolExecutor();
+        assertNotNull(threadPoolExecutor, "ThreadPoolExecutor should be initialized");
+
+        // Verify thread prefix naming indirectly through a newly created thread
+        executor.execute(() -> {
+            String currentThreadName = Thread.currentThread().getName();
+            assertTrue(currentThreadName.startsWith("EmailThread-"),
+                    "Thread name should start with 'EmailThread-'");
+        });
+    }
+}
diff --git a/src/test/java/com/safetypin/authentication/controller/AuthenticationControllerTest.java b/src/test/java/com/safetypin/authentication/controller/AuthenticationControllerTest.java
index ab3d5012e63ec79723bc9fe0636065408e97aedc..3002d32c3d68eae6b6713d7fe98bd541c5838547 100644
--- a/src/test/java/com/safetypin/authentication/controller/AuthenticationControllerTest.java
+++ b/src/test/java/com/safetypin/authentication/controller/AuthenticationControllerTest.java
@@ -6,6 +6,7 @@ import com.safetypin.authentication.dto.PasswordResetRequest;
 import com.safetypin.authentication.dto.RegistrationRequest;
 import com.safetypin.authentication.dto.UserResponse;
 import com.safetypin.authentication.exception.InvalidCredentialsException;
+import com.safetypin.authentication.model.Role;
 import com.safetypin.authentication.exception.UserAlreadyExistsException;
 import com.safetypin.authentication.model.User;
 import com.safetypin.authentication.service.AuthenticationService;
@@ -33,7 +34,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
 
 @WebMvcTest(AuthenticationController.class)
-@Import({AuthenticationControllerTest.TestConfig.class, AuthenticationControllerTest.TestSecurityConfig.class})
+@Import({AuthenticationControllerTest.TestConfig.class})
 class AuthenticationControllerTest {
 
     @Autowired
@@ -92,7 +93,7 @@ class AuthenticationControllerTest {
         user.setEmail("email@example.com");
         user.setPassword("encodedPassword");
         user.setName("Test User");
-        user.setRole("USER");
+        user.setRole(Role.REGISTERED_USER);
         user.setBirthdate(request.getBirthdate());
         user.setProvider("EMAIL");
 
@@ -115,7 +116,7 @@ class AuthenticationControllerTest {
         user.setPassword("encodedPassword");
         user.setName("Test User");
         user.setVerified(true);
-        user.setRole("USER");
+        user.setRole(Role.REGISTERED_USER);
         user.setBirthdate(LocalDate.now().minusYears(20));
         user.setProvider("EMAIL");
 
@@ -176,6 +177,17 @@ class AuthenticationControllerTest {
                 .andExpect(jsonPath("$.message").value("OTP verification failed"));
     }
 
+    @Test
+    void testVerifyOTP_InvalidCredentials() throws Exception {
+        String errorMessage = "Invalid email or OTP";
+        Mockito.when(authenticationService.verifyOTP("email@example.com", "invalid"))
+                .thenThrow(new InvalidCredentialsException(errorMessage));
+
+        mockMvc.perform(post("/api/auth/verify-otp")
+                        .param("email", "Invalid OTP code or expired"))
+                .andExpect(status().isBadRequest());
+    }
+
     @Test
     void testForgotPassword() throws Exception {
         PasswordResetRequest request = new PasswordResetRequest();
diff --git a/src/test/java/com/safetypin/authentication/dto/ErrorResponseTest.java b/src/test/java/com/safetypin/authentication/dto/ErrorResponseTest.java
index 1398d5a2527655c91f052f4ca71b62f1a3003f55..a5249ce2e9c1050524682f320ecfb1b8f8338ec3 100644
--- a/src/test/java/com/safetypin/authentication/dto/ErrorResponseTest.java
+++ b/src/test/java/com/safetypin/authentication/dto/ErrorResponseTest.java
@@ -1,18 +1,85 @@
 package com.safetypin.authentication.dto;
 
 import org.junit.jupiter.api.Test;
-import static org.assertj.core.api.Assertions.assertThat;
 import java.time.LocalDateTime;
+import static org.junit.jupiter.api.Assertions.*;
 
 class ErrorResponseTest {
 
     @Test
-    void testErrorResponseConstructor() {
-        ErrorResponse errorResponse = new ErrorResponse(404, "Resource not found");
+    void testNoArgsConstructor() {
+        // Act
+        ErrorResponse response = new ErrorResponse();
 
-        assertThat(errorResponse.getStatus()).isEqualTo(404);
-        assertThat(errorResponse.getMessage()).isEqualTo("Resource not found");
-        assertThat(errorResponse.getTimestamp()).isNotNull();
-        assertThat(errorResponse.getTimestamp()).isBeforeOrEqualTo(LocalDateTime.now());
+        // Assert
+        assertNull(response.getMessage());
+        assertEquals(0, response.getStatus());
+        assertNull(response.getTimestamp());
+    }
+
+    @Test
+    void testParameterizedConstructor() {
+        // Arrange
+        int status = 404;
+        String message = "Not Found";
+
+        // Act
+        ErrorResponse response = new ErrorResponse(status, message);
+        LocalDateTime beforeTest = LocalDateTime.now().minusSeconds(1);
+        
+        // Assert
+        assertEquals(status, response.getStatus());
+        assertEquals(message, response.getMessage());
+        assertNotNull(response.getTimestamp());
+        // Check that timestamp is recent
+        assertTrue(response.getTimestamp().isAfter(beforeTest));
+    }
+
+    @Test
+    void testGettersAndSetters() {
+        // Arrange
+        ErrorResponse response = new ErrorResponse();
+        int status = 500;
+        String message = "Internal Server Error";
+        LocalDateTime timestamp = LocalDateTime.now();
+
+        // Act
+        response.setStatus(status);
+        response.setMessage(message);
+        response.setTimestamp(timestamp);
+
+        // Assert
+        assertEquals(status, response.getStatus());
+        assertEquals(message, response.getMessage());
+        assertEquals(timestamp, response.getTimestamp());
+    }
+
+    @Test
+    void testEqualsAndHashCode() {
+        // Arrange
+        ErrorResponse response1 = new ErrorResponse(404, "Not Found");
+        ErrorResponse response2 = new ErrorResponse(404, "Not Found");
+        response2.setTimestamp(response1.getTimestamp()); // Ensure same timestamp for equality check
+        ErrorResponse response3 = new ErrorResponse(500, "Error");
+
+        // Assert
+        assertEquals(response1, response2);
+        assertNotEquals(response1, response3);
+        assertEquals(response1.hashCode(), response2.hashCode());
+        assertNotEquals(response1.hashCode(), response3.hashCode());
+    }
+
+    @Test
+    void testToString() {
+        // Arrange
+        ErrorResponse response = new ErrorResponse(404, "Not Found");
+        
+        // Act
+        String toStringResult = response.toString();
+        
+        // Assert
+        assertTrue(toStringResult.contains("404"));
+        assertTrue(toStringResult.contains("Not Found"));
+        assertTrue(toStringResult.contains("timestamp"));
     }
 }
diff --git a/src/test/java/com/safetypin/authentication/dto/GoogleAuthDTOTest.java b/src/test/java/com/safetypin/authentication/dto/GoogleAuthDTOTest.java
index e7ec48fccb80385eb27e1a00eb67320aedbc11b8..c9d0095f4bed6d5bba42c7710e285122dc2c5933 100644
--- a/src/test/java/com/safetypin/authentication/dto/GoogleAuthDTOTest.java
+++ b/src/test/java/com/safetypin/authentication/dto/GoogleAuthDTOTest.java
@@ -122,7 +122,7 @@ class GoogleAuthDTOTest {
         assertEquals(dto1, dto2, "Identical DTOs should be equal");
         assertNotEquals(dto1, dto3, "Different DTOs should not be equal");
         assertNotEquals(null, dto1, "Should not be equal to null");
-        assertNotEquals(dto1, new Object(), "Should not be equal to different object type");
+        assertNotEquals(new Object(), dto1, "Should not be equal to different object type");
 
         // Test hashCode
         assertEquals(dto1.hashCode(), dto2.hashCode(), "Identical DTOs should have same hashCode");
diff --git a/src/test/java/com/safetypin/authentication/dto/PasswordResetRequestTest.java b/src/test/java/com/safetypin/authentication/dto/PasswordResetRequestTest.java
index 013ec5dcdbecc804e717e1185c093433603614a8..9447b1c8b6201650a95f657c22cb0cb7d2bf9539 100644
--- a/src/test/java/com/safetypin/authentication/dto/PasswordResetRequestTest.java
+++ b/src/test/java/com/safetypin/authentication/dto/PasswordResetRequestTest.java
@@ -1,37 +1,20 @@
 package com.safetypin.authentication.dto;
 
 import org.junit.jupiter.api.Test;
-import static org.assertj.core.api.Assertions.assertThat;
-import jakarta.validation.Validation;
-import jakarta.validation.Validator;
-import jakarta.validation.ValidatorFactory;
-import jakarta.validation.ConstraintViolation;
-import java.util.Set;
+import static org.junit.jupiter.api.Assertions.*;
 
 class PasswordResetRequestTest {
 
-    private final Validator validator;
-
-    public PasswordResetRequestTest() {
-        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
-        this.validator = factory.getValidator();
-    }
-
     @Test
-    void testPasswordResetRequestValid() {
+    void testGettersAndSetters() {
+        // Arrange
         PasswordResetRequest request = new PasswordResetRequest();
-        request.setEmail("user@example.com");
+        String email = "test@example.com";
 
-        Set<ConstraintViolation<PasswordResetRequest>> violations = validator.validate(request);
-        assertThat(violations).isEmpty();
-    }
-
-    @Test
-    void testPasswordResetRequestInvalidEmail() {
-        PasswordResetRequest request = new PasswordResetRequest();
-        request.setEmail("invalid-email");
+        // Act
+        request.setEmail(email);
 
-        Set<ConstraintViolation<PasswordResetRequest>> violations = validator.validate(request);
-        assertThat(violations).isNotEmpty();
+        // Assert
+        assertEquals(email, request.getEmail());
     }
 }
diff --git a/src/test/java/com/safetypin/authentication/dto/RegistrationRequestTest.java b/src/test/java/com/safetypin/authentication/dto/RegistrationRequestTest.java
index b231e6732dc2eba209553a509fac64f1b35e3120..02a7fc7c38617a7e814e645bea2921730484270a 100644
--- a/src/test/java/com/safetypin/authentication/dto/RegistrationRequestTest.java
+++ b/src/test/java/com/safetypin/authentication/dto/RegistrationRequestTest.java
@@ -1,42 +1,30 @@
 package com.safetypin.authentication.dto;
 
 import org.junit.jupiter.api.Test;
-import static org.assertj.core.api.Assertions.assertThat;
-import jakarta.validation.Validation;
-import jakarta.validation.Validator;
-import jakarta.validation.ValidatorFactory;
-import jakarta.validation.ConstraintViolation;
 import java.time.LocalDate;
-import java.util.Set;
+import static org.junit.jupiter.api.Assertions.*;
 
 class RegistrationRequestTest {
 
-    private final Validator validator;
-
-    public RegistrationRequestTest() {
-        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
-        this.validator = factory.getValidator();
-    }
-
     @Test
-    void testRegistrationRequestValid() {
+    void testGettersAndSetters() {
+        // Arrange
         RegistrationRequest request = new RegistrationRequest();
-        request.setEmail("user@example.com");
-        request.setPassword("securePassword");
-        request.setName("John Doe");
-        request.setBirthdate(LocalDate.of(1995, 5, 10));
-
-        Set<ConstraintViolation<RegistrationRequest>> violations = validator.validate(request);
-        assertThat(violations).isEmpty();
-    }
-
-    @Test
-    void testRegistrationRequestMissingFields() {
-        RegistrationRequest request = new RegistrationRequest(); // Missing required fields
-
-        Set<ConstraintViolation<RegistrationRequest>> violations = validator.validate(request);
-        assertThat(violations)
-                .isNotEmpty()
-                .hasSize(4); // Email, password, name, and birthdate should all be invalid
+        String email = "test@example.com";
+        String password = "Password123";
+        String name = "Test User";
+        LocalDate birthdate = LocalDate.of(1990, 1, 1);
+
+        // Act
+        request.setEmail(email);
+        request.setPassword(password);
+        request.setName(name);
+        request.setBirthdate(birthdate);
+
+        // Assert
+        assertEquals(email, request.getEmail());
+        assertEquals(password, request.getPassword());
+        assertEquals(name, request.getName());
+        assertEquals(birthdate, request.getBirthdate());
     }
 }
diff --git a/src/test/java/com/safetypin/authentication/dto/SocialLoginRequestTest.java b/src/test/java/com/safetypin/authentication/dto/SocialLoginRequestTest.java
index fe4a2a68ff908394936cc3f3b187054577c34d24..ca7759815416a3b3edbe4f7e72f025adaa73a459 100644
--- a/src/test/java/com/safetypin/authentication/dto/SocialLoginRequestTest.java
+++ b/src/test/java/com/safetypin/authentication/dto/SocialLoginRequestTest.java
@@ -1,44 +1,36 @@
 package com.safetypin.authentication.dto;
 
 import org.junit.jupiter.api.Test;
-import static org.assertj.core.api.Assertions.assertThat;
-import jakarta.validation.Validation;
-import jakarta.validation.Validator;
-import jakarta.validation.ValidatorFactory;
-import jakarta.validation.ConstraintViolation;
 import java.time.LocalDate;
-import java.util.Set;
+import static org.junit.jupiter.api.Assertions.*;
 
 class SocialLoginRequestTest {
 
-    private final Validator validator;
-
-    public SocialLoginRequestTest() {
-        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
-        this.validator = factory.getValidator();
-    }
-
     @Test
-    void testSocialLoginRequestValid() {
+    void testGettersAndSetters() {
+        // Arrange
         SocialLoginRequest request = new SocialLoginRequest();
-        request.setProvider("GOOGLE");
-        request.setSocialToken("validToken");
-        request.setEmail("socialuser@example.com");
-        request.setName("Social User");
-        request.setBirthdate(LocalDate.of(2000, 1, 1));
-        request.setSocialId("123456789");
-
-        Set<ConstraintViolation<SocialLoginRequest>> violations = validator.validate(request);
-        assertThat(violations).isEmpty();
-    }
-
-    @Test
-    void testSocialLoginRequestMissingFields() {
-        SocialLoginRequest request = new SocialLoginRequest(); // Missing required fields
-
-        Set<ConstraintViolation<SocialLoginRequest>> violations = validator.validate(request);
-        assertThat(violations)
-                .isNotEmpty()
-                .hasSize(6); // All fields should be invalid
+        String provider = "GOOGLE";
+        String socialToken = "token123";
+        String email = "test@example.com";
+        String name = "Test User";
+        LocalDate birthdate = LocalDate.of(1990, 1, 1);
+        String socialId = "social123";
+
+        // Act
+        request.setProvider(provider);
+        request.setSocialToken(socialToken);
+        request.setEmail(email);
+        request.setName(name);
+        request.setBirthdate(birthdate);
+        request.setSocialId(socialId);
+
+        // Assert
+        assertEquals(provider, request.getProvider());
+        assertEquals(socialToken, request.getSocialToken());
+        assertEquals(email, request.getEmail());
+        assertEquals(name, request.getName());
+        assertEquals(birthdate, request.getBirthdate());
+        assertEquals(socialId, request.getSocialId());
     }
 }
diff --git a/src/test/java/com/safetypin/authentication/model/RoleTest.java b/src/test/java/com/safetypin/authentication/model/RoleTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..007deeb7922beef9025c72ec019a88f69d4b82b2
--- /dev/null
+++ b/src/test/java/com/safetypin/authentication/model/RoleTest.java
@@ -0,0 +1,41 @@
+package com.safetypin.authentication.model;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class RoleTest {
+
+    @Test
+    void testEnumValues() {
+        // Test that the enum has the expected values
+        assertEquals(3, Role.values().length);
+        assertEquals(Role.REGISTERED_USER, Role.valueOf("REGISTERED_USER"));
+        assertEquals(Role.PREMIUM_USER, Role.valueOf("PREMIUM_USER"));
+        assertEquals(Role.MODERATOR, Role.valueOf("MODERATOR"));
+    }
+
+    @Test
+    void testEnumOrdinals() {
+        // Test the ordinals (mostly for coverage)
+        assertEquals(0, Role.REGISTERED_USER.ordinal());
+        assertEquals(1, Role.PREMIUM_USER.ordinal());
+        assertEquals(2, Role.MODERATOR.ordinal());
+    }
+
+    @Test
+    void testEnumToString() {
+        // Test the toString method
+        assertEquals("REGISTERED_USER", Role.REGISTERED_USER.toString());
+        assertEquals("PREMIUM_USER", Role.PREMIUM_USER.toString());
+        assertEquals("MODERATOR", Role.MODERATOR.toString());
+    }
+
+    @Test
+    void testEnumValueOf() {
+        // Test the valueOf method
+        assertEquals(Role.REGISTERED_USER, Role.valueOf("REGISTERED_USER"));
+        assertEquals(Role.PREMIUM_USER, Role.valueOf("PREMIUM_USER"));
+        assertEquals(Role.MODERATOR, Role.valueOf("MODERATOR"));
+    }
+}
diff --git a/src/test/java/com/safetypin/authentication/model/UserTest.java b/src/test/java/com/safetypin/authentication/model/UserTest.java
index 43dc6c4913014c982caa458567bc527047c49cef..cfc7b2a3711b22d2ecbe63e87b40e355072e60c9 100644
--- a/src/test/java/com/safetypin/authentication/model/UserTest.java
+++ b/src/test/java/com/safetypin/authentication/model/UserTest.java
@@ -1,6 +1,5 @@
 package com.safetypin.authentication.model;
 
-import com.safetypin.authentication.dto.UserResponse;
 import org.junit.jupiter.api.Test;
 
 import java.time.LocalDate;
@@ -32,7 +31,7 @@ class UserTest {
         String password = "secret";
         String name = "Test User";
         boolean verified = true;
-        String role = "ADMIN";
+        Role role = Role.REGISTERED_USER;
         LocalDate birthdate = LocalDate.of(2000, 1, 1);
         String provider = "GOOGLE";
 
@@ -61,7 +60,7 @@ class UserTest {
         String password = "password123";
         String name = "Another User";
         boolean verified = false;
-        String role = "USER";
+        Role role = Role.MODERATOR;
         LocalDate birthdate = LocalDate.of(1995, 5, 15);
         String provider = "EMAIL";
 
@@ -88,36 +87,110 @@ class UserTest {
 
     @Test
     void testGenerateUserResponse() {
-        // Setup
         User user = new User();
-        UUID id = UUID.randomUUID();
-        String email = "test@example.com";
-        String password = "secret";  // This shouldn't be in the response
-        String name = "Test User";
-        boolean verified = true;
-        String role = "ADMIN";
-        LocalDate birthdate = LocalDate.of(2000, 1, 1);
-        String provider = "GOOGLE";
+        user.setEmail("test@example.com");
+        user.setName("Test User");
+        user.setRole(Role.REGISTERED_USER);
+
+        var response = user.generateUserResponse();
+        assertEquals("REGISTERED_USER", response.getRole());
+    }
 
+    @Test
+    void testRoleEnumValues() {
+        User userRegistered = new User();
+        User userPremium = new User();
+        User userModerator = new User();
+
+        // Test REGISTERED_USER role
+        userRegistered.setRole(Role.REGISTERED_USER);
+        assertEquals(Role.REGISTERED_USER, userRegistered.getRole());
+        assertEquals("REGISTERED_USER", userRegistered.getRole().name());
+
+        // Test PREMIUM_USER role
+        userPremium.setRole(Role.PREMIUM_USER);
+        assertEquals(Role.PREMIUM_USER, userPremium.getRole());
+        assertEquals("PREMIUM_USER", userPremium.getRole().name());
+
+        // Test MODERATOR role
+        userModerator.setRole(Role.MODERATOR);
+        assertEquals(Role.MODERATOR, userModerator.getRole());
+        assertEquals("MODERATOR", userModerator.getRole().name());
+    }
+
+    @Test
+    void testUserResponseWithDifferentRoles() {
+        // Test UserResponse generation with each role
+        User registeredUser = new User();
+        registeredUser.setRole(Role.REGISTERED_USER);
+        assertEquals("REGISTERED_USER", registeredUser.generateUserResponse().getRole());
+
+        User premiumUser = new User();
+        premiumUser.setRole(Role.PREMIUM_USER);
+        assertEquals("PREMIUM_USER", premiumUser.generateUserResponse().getRole());
+
+        User moderatorUser = new User();
+        moderatorUser.setRole(Role.MODERATOR);
+        assertEquals("MODERATOR", moderatorUser.generateUserResponse().getRole());
+    }
+
+    @Test
+    void testUserWithNullRole() {
+        // Test case for null role
+        User user = new User();
+        assertNull(user.getRole());
+        assertNull(user.generateUserResponse().getRole());
+    }
+
+    @Test
+    void testCompleteUserResponseGeneration() {
+        // Test UserResponse generation with all fields set
+        User user = new User();
+        UUID id = UUID.randomUUID();
         user.setId(id);
-        user.setEmail(email);
-        user.setPassword(password);
-        user.setName(name);
-        user.setVerified(verified);
-        user.setRole(role);
-        user.setBirthdate(birthdate);
-        user.setProvider(provider);
+        user.setEmail("test@example.com");
+        user.setName("Test User");
+        user.setRole(Role.PREMIUM_USER);
+        user.setVerified(true);
+        user.setBirthdate(LocalDate.of(1990, 1, 1));
+        user.setProvider("GOOGLE");
+
+        var response = user.generateUserResponse();
+        assertEquals(id, response.getId());
+        assertEquals("test@example.com", response.getEmail());
+        assertEquals("Test User", response.getName());
+        assertEquals("PREMIUM_USER", response.getRole());
+        assertTrue(response.isVerified());
+        assertEquals(LocalDate.of(1990, 1, 1), response.getBirthdate());
+        assertEquals("GOOGLE", response.getProvider());
+    }
+
+    @Test
+    void testUserResponseWithNullFields() {
+        // Test UserResponse generation with some null fields
+        User user = new User();
+        user.setEmail("test@example.com");
+        user.setName("Test User");
+        // Role, birthdate, and provider are null
+
+        var response = user.generateUserResponse();
+        assertEquals("test@example.com", response.getEmail());
+        assertEquals("Test User", response.getName());
+        assertNull(response.getRole());
+        assertFalse(response.isVerified());
+        assertNull(response.getBirthdate());
+        assertNull(response.getProvider());
+    }
+
+    @Test
+    void testVerificationMethodsSetter() {
+        User user = new User();
+        assertFalse(user.isVerified());
+
+        user.setVerified(true);
+        assertTrue(user.isVerified());
 
-        // Execute
-        UserResponse response = user.generateUserResponse();
-
-        // Verify
-        assertEquals(id, response.getId(), "ID should match");
-        assertEquals(email, response.getEmail(), "Email should match");
-        assertEquals(name, response.getName(), "Name should match");
-        assertEquals(verified, response.isVerified(), "Verification status should match");
-        assertEquals(role, response.getRole(), "Role should match");
-        assertEquals(birthdate, response.getBirthdate(), "Birthdate should match");
-        assertEquals(provider, response.getProvider(), "Provider should match");
+        user.setVerified(false);
+        assertFalse(user.isVerified());
     }
 }
diff --git a/src/test/java/com/safetypin/authentication/repository/UserRepositoryTest.java b/src/test/java/com/safetypin/authentication/repository/UserRepositoryTest.java
index fd7e4ff0de472cd55392cdb8ba9b5430095be556..f32c7e276907a4bdf9dce7a8607719c879860333 100644
--- a/src/test/java/com/safetypin/authentication/repository/UserRepositoryTest.java
+++ b/src/test/java/com/safetypin/authentication/repository/UserRepositoryTest.java
@@ -1,11 +1,14 @@
 package com.safetypin.authentication.repository;
 
+import com.safetypin.authentication.model.Role;
 import com.safetypin.authentication.model.User;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
 
+import java.util.List;
+
 import static org.junit.jupiter.api.Assertions.*;
 
 @DataJpaTest
@@ -18,22 +21,32 @@ class UserRepositoryTest {
     void setUp() {
         userRepository.deleteAll();
 
-        // Create and save a User entity
-        User user = new User();
-        user.setEmail("test@example.com");
-        user.setPassword("password");
-        user.setName("Test User");
-        user.setRole("USER");
-        userRepository.save(user);
+        // Create and save users with different roles
+        User registeredUser = new User();
+        registeredUser.setEmail("registered@example.com");
+        registeredUser.setPassword("password");
+        registeredUser.setName("Registered User");
+        registeredUser.setRole(Role.REGISTERED_USER);
+        userRepository.save(registeredUser);
+
+        User premiumUser = new User();
+        premiumUser.setEmail("premium@example.com");
+        premiumUser.setPassword("password");
+        premiumUser.setName("Premium User");
+        premiumUser.setRole(Role.PREMIUM_USER);
+        userRepository.save(premiumUser);
+
+        // No moderator user yet - we'll test for missing role
     }
 
     @Test
     void testFindByEmailWhenUserExists() {
         // Retrieve the user by email
-        User foundUser = userRepository.findByEmail("test@example.com");
+        User foundUser = userRepository.findByEmail("registered@example.com");
         assertNotNull(foundUser, "Expected to find a user with the given email");
-        assertEquals("test@example.com", foundUser.getEmail());
-        assertEquals("Test User", foundUser.getName());
+        assertEquals("registered@example.com", foundUser.getEmail());
+        assertEquals("Registered User", foundUser.getName());
+        assertEquals(Role.REGISTERED_USER, foundUser.getRole());
     }
 
     @Test
@@ -43,4 +56,29 @@ class UserRepositoryTest {
         assertNull(foundUser, "Expected no user to be found for a non-existent email");
     }
 
+    @Test
+    void testFindByRolesExisting() {
+        // Test finding users by different existing roles
+        User registeredUser = userRepository.findByRole(Role.REGISTERED_USER);
+        assertNotNull(registeredUser);
+        assertEquals("registered@example.com", registeredUser.getEmail());
+
+        User premiumUser = userRepository.findByRole(Role.PREMIUM_USER);
+        assertNotNull(premiumUser);
+        assertEquals("premium@example.com", premiumUser.getEmail());
+    }
+
+    @Test
+    void testFindByRoleNonExistent() {
+        // Test finding by role that no user has
+        User moderator = userRepository.findByRole(Role.MODERATOR);
+        assertNull(moderator, "No user should be found with MODERATOR role");
+    }
+
+    @Test
+    void testFindAll() {
+        // Test finding all users
+        List<User> users = userRepository.findAll();
+        assertEquals(2, users.size());
+    }
 }
diff --git a/src/test/java/com/safetypin/authentication/seeder/DevDataSeederTest.java b/src/test/java/com/safetypin/authentication/seeder/DevDataSeederTest.java
index 72f7cb32c157897980f0e3133b74c0a08be191b6..33caa25146cd47b6cf90e9390774cae75f7c6c83 100644
--- a/src/test/java/com/safetypin/authentication/seeder/DevDataSeederTest.java
+++ b/src/test/java/com/safetypin/authentication/seeder/DevDataSeederTest.java
@@ -1,5 +1,6 @@
 package com.safetypin.authentication.seeder;
 
+import com.safetypin.authentication.model.Role;
 import com.safetypin.authentication.model.User;
 import com.safetypin.authentication.repository.UserRepository;
 import jakarta.transaction.Transactional;
@@ -47,7 +48,7 @@ class DevDataSeederTest {
         user.setPassword(passwordEncoder.encode("test"));
         user.setName("Existing User");
         user.setVerified(true);
-        user.setRole("admin");
+        user.setRole(Role.MODERATOR);
         user.setBirthdate(LocalDate.of(1990, 1, 1));
         user.setProvider("EMAIL");
         userRepository.save(user);
diff --git a/src/test/java/com/safetypin/authentication/service/AuthenticationServiceTest.java b/src/test/java/com/safetypin/authentication/service/AuthenticationServiceTest.java
index 24bf8cb601296ca52e54459644a34434608ba01d..67358617ca0adcb807c47c55c196c98b43e77452 100644
--- a/src/test/java/com/safetypin/authentication/service/AuthenticationServiceTest.java
+++ b/src/test/java/com/safetypin/authentication/service/AuthenticationServiceTest.java
@@ -3,6 +3,7 @@ package com.safetypin.authentication.service;
 import com.safetypin.authentication.dto.RegistrationRequest;
 import com.safetypin.authentication.exception.InvalidCredentialsException;
 import com.safetypin.authentication.exception.UserAlreadyExistsException;
+import com.safetypin.authentication.model.Role;
 import com.safetypin.authentication.model.User;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -91,7 +92,7 @@ class AuthenticationServiceTest {
         savedUser.setPassword("encodedPassword");
         savedUser.setName("Test User");
         savedUser.setVerified(false);
-        savedUser.setRole("USER");
+        savedUser.setRole(Role.REGISTERED_USER);
         savedUser.setBirthdate(request.getBirthdate());
         savedUser.setProvider("EMAIL");
 
@@ -129,7 +130,7 @@ class AuthenticationServiceTest {
         user.setPassword("encodedPassword");
         user.setName("Test User");
         user.setVerified(true);
-        user.setRole("USER");
+        user.setRole(Role.REGISTERED_USER);
         user.setBirthdate(LocalDate.now().minusYears(20));
         user.setProvider("EMAIL");
 
@@ -150,7 +151,7 @@ class AuthenticationServiceTest {
         user.setPassword("encodedPassword");
         user.setName("Test User");
         user.setVerified(true);
-        user.setRole("USER");
+        user.setRole(Role.REGISTERED_USER);
         user.setBirthdate(LocalDate.now().minusYears(20));
         user.setProvider("EMAIL");
 
@@ -179,7 +180,7 @@ class AuthenticationServiceTest {
         user.setPassword("encodedPassword");
         user.setName("Test User");
         user.setVerified(false);
-        user.setRole("USER");
+        user.setRole(Role.REGISTERED_USER);
         user.setBirthdate(LocalDate.now().minusYears(20));
         user.setProvider("EMAIL");
 
@@ -224,7 +225,7 @@ class AuthenticationServiceTest {
         user.setPassword("encodedPassword");
         user.setName("Test User");
         user.setVerified(true);
-        user.setRole("USER");
+        user.setRole(Role.REGISTERED_USER);
         user.setBirthdate(LocalDate.now().minusYears(20));
         user.setProvider("EMAIL");
 
@@ -251,7 +252,7 @@ class AuthenticationServiceTest {
         user.setPassword(null);
         user.setName("Social User");
         user.setVerified(true);
-        user.setRole("USER");
+        user.setRole(Role.REGISTERED_USER);
         user.setBirthdate(LocalDate.now().minusYears(25));
         user.setProvider("GOOGLE");
 
diff --git a/src/test/java/com/safetypin/authentication/service/EmailServiceTest.java b/src/test/java/com/safetypin/authentication/service/EmailServiceTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..a35de63b1a57d3f944cb33e31bc869036d4465a9
--- /dev/null
+++ b/src/test/java/com/safetypin/authentication/service/EmailServiceTest.java
@@ -0,0 +1,67 @@
+package com.safetypin.authentication.service;
+
+import com.icegreen.greenmail.configuration.GreenMailConfiguration;
+import com.icegreen.greenmail.junit5.GreenMailExtension;
+import com.icegreen.greenmail.store.FolderException;
+import com.icegreen.greenmail.util.ServerSetup;
+import jakarta.mail.MessagingException;
+import jakarta.mail.internet.MimeMessage;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.io.IOException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+
+// Email integration test
+@SpringBootTest
+@ActiveProfiles("test")
+@RunWith(SpringRunner.class)
+class EmailServiceTest {
+    @RegisterExtension
+    static GreenMailExtension greenMail = new GreenMailExtension(
+            new ServerSetup(2525, "127.0.0.1", "smtp"))
+            .withConfiguration(GreenMailConfiguration.aConfig().withUser("username", "secret123"))
+            .withPerMethodLifecycle(false);
+
+    @Autowired
+    private EmailService emailService;
+
+    @AfterEach
+    void cleanup() throws FolderException {
+        greenMail.purgeEmailFromAllMailboxes();
+    }
+
+    @Test
+    void testSendOTPMail_Success() throws MessagingException, IOException, ExecutionException, InterruptedException {
+        String otp = "123456";
+        CompletableFuture<Boolean> future = emailService.sendOTPMail("username@test.com", otp);
+        boolean status = future.get();
+        assertTrue(status);
+
+        MimeMessage[] receivedMessages = greenMail.getReceivedMessages();
+        assertEquals(1, receivedMessages.length);
+        MimeMessage receivedMessage = receivedMessages[0];
+        assertTrue(receivedMessage.getSubject().contains("OTP"));
+        assertTrue(receivedMessage.getContent().toString().contains(otp));
+    }
+
+    @Test
+    void testSendOTPMail_MailServerDown() throws ExecutionException, InterruptedException {
+        greenMail.stop();
+
+        String otp = "123456";
+        CompletableFuture<Boolean> future = emailService.sendOTPMail("username@test.com", otp);
+        boolean status = future.get();
+        assertFalse(status);
+    }
+}
diff --git a/src/test/java/com/safetypin/authentication/service/OTPServiceTest.java b/src/test/java/com/safetypin/authentication/service/OTPServiceTest.java
index cfca094d53014f45858935dfa0f1c97eb354ac48..f2e9b97facb5feb5ad0bc3860d88b81e76beb1f4 100644
--- a/src/test/java/com/safetypin/authentication/service/OTPServiceTest.java
+++ b/src/test/java/com/safetypin/authentication/service/OTPServiceTest.java
@@ -1,48 +1,127 @@
 package com.safetypin.authentication.service;
 
+import com.safetypin.authentication.exception.OTPException;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
 
 import java.lang.reflect.Constructor;
 import java.time.LocalDateTime;
+import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
 
 import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.when;
 
+@ExtendWith(MockitoExtension.class)
 class OTPServiceTest {
+    @InjectMocks
+    private OTPService otpService;
+
+    @Mock
+    private EmailService emailService;
+
+    /**
+     * Helper method to generate an OTP different from the input
+     */
+    private String generateDifferentOTP(String originalOTP) {
+        if (originalOTP.equals("000000")) {
+            return "000001";
+        } else {
+            return "000000";
+        }
+    }
 
     @Test
     void testGenerateOTP() {
-        OTPService otpService = new OTPService();
+        when(emailService.sendOTPMail(anyString(), anyString()))
+                .thenReturn(CompletableFuture.completedFuture(true));
+
         String email = "user@example.com";
-        String otp = otpService.generateOTP(email);
-        assertNotNull(otp, "OTP should not be null");
-        assertEquals(6, otp.length(), "OTP should be 6 characters long");
-        assertTrue(otp.matches("\\d{6}"), "OTP should consist of 6 digits");
+        String generatedOTP = otpService.generateOTP(email);
+
+        assertNotNull(generatedOTP, "Generated OTP should not be null");
+        assertEquals(6, generatedOTP.length(), "OTP should be 6 digits long");
     }
 
     @Test
-    void testVerifyOTPSuccess() {
-        OTPService otpService = new OTPService();
+    void testVerifyOTPWrongOtp() {
+        when(emailService.sendOTPMail(anyString(), anyString()))
+                .thenReturn(CompletableFuture.completedFuture(true));
+
         String email = "user@example.com";
-        String otp = otpService.generateOTP(email);
-        // Immediately verify the generated OTP; it should succeed.
-        boolean result = otpService.verifyOTP(email, otp);
-        assertTrue(result, "The OTP should verify successfully");
+        String generatedOTP = otpService.generateOTP(email);
+
+        // Generate a different OTP guaranteed to be different from the one generated
+        String wrongOTP = generateDifferentOTP(generatedOTP);
+
+        boolean result = otpService.verifyOTP(email, wrongOTP);
+        assertFalse(result, "Verification should fail for an incorrect OTP");
     }
 
     @Test
-    void testVerifyOTPWrongOtp() {
-        OTPService otpService = new OTPService();
+    void testMultipleOTPGenerations() {
+        when(emailService.sendOTPMail(anyString(), anyString()))
+                .thenReturn(CompletableFuture.completedFuture(true));
+
         String email = "user@example.com";
-        otpService.generateOTP(email);
-        // Try verifying with an incorrect OTP.
-        boolean result = otpService.verifyOTP(email, "000000");
-        assertFalse(result, "Verification should fail for an incorrect OTP");
+        String firstOTP = otpService.generateOTP(email);
+        String secondOTP = otpService.generateOTP(email);
+
+        assertNotEquals(firstOTP, secondOTP, "Generated OTPs should be different");
+    }
+
+    @Test
+    void testVerifyOTPAfterSecondGeneration() {
+        when(emailService.sendOTPMail(anyString(), anyString()))
+                .thenReturn(CompletableFuture.completedFuture(true));
+
+        String email = "user@example.com";
+        String firstOTP = otpService.generateOTP(email);
+        String secondOTP = otpService.generateOTP(email);
+
+        boolean result = otpService.verifyOTP(email, firstOTP);
+        assertFalse(result, "First OTP should not verify after second generation");
+
+        boolean secondResult = otpService.verifyOTP(email, secondOTP);
+        assertTrue(secondResult, "Latest OTP should verify successfully");
+    }
+
+    @Test
+    void testVerifyOTPMultipleTimes() {
+        when(emailService.sendOTPMail(anyString(), anyString()))
+                .thenReturn(CompletableFuture.completedFuture(true));
+
+        String email = "user@example.com";
+        String otp = otpService.generateOTP(email);
+
+        boolean firstTry = otpService.verifyOTP(email, otp);
+        assertTrue(firstTry, "First verification should succeed");
+
+        boolean secondTry = otpService.verifyOTP(email, otp);
+        assertFalse(secondTry, "Second verification should fail as OTP should be consumed");
+    }
+
+    @Test
+    void testNullParameters() {
+        assertThrows(NullPointerException.class, () -> {
+            otpService.verifyOTP(null, "123456");
+        }, "Should throw exception when email is null");
+
+        assertThrows(NullPointerException.class, () -> {
+            otpService.verifyOTP("user@example.com", null);
+        }, "Should throw exception when OTP is null");
     }
 
     @Test
-    void testVerifyOTPExpired() throws Exception {
-        OTPService otpService = new OTPService();
+    void testOTPExpiration() throws Exception {
+        when(emailService.sendOTPMail(anyString(), anyString()))
+                .thenReturn(CompletableFuture.completedFuture(true));
+
         String email = "user@example.com";
         String otp = otpService.generateOTP(email);
 
@@ -72,9 +151,64 @@ class OTPServiceTest {
 
     @Test
     void testVerifyOTPWhenNotGenerated() {
-        OTPService otpService = new OTPService();
         // No OTP was generated for this email, so verification should return false.
         boolean result = otpService.verifyOTP("nonexistent@example.com", "123456");
         assertFalse(result, "Verification should fail when no OTP is generated for the given email");
     }
-}
+
+    @Test
+    void testGenerateOTPEmailServiceReturnsFalse() {
+        // Mock email service to return false
+        when(emailService.sendOTPMail(anyString(), anyString()))
+                .thenReturn(CompletableFuture.completedFuture(false));
+
+        String email = "user@example.com";
+
+        // Verify that OTPException is thrown
+        OTPException exception = assertThrows(OTPException.class, () -> {
+            otpService.generateOTP(email);
+        }, "Should throw OTPException when email service returns false");
+
+        assertEquals("Failed to send OTP", exception.getMessage());
+    }
+
+    @Test
+    void testGenerateOTPInterruptedException() {
+        // Mock email service to throw InterruptedException
+        CompletableFuture<Boolean> future = new CompletableFuture<>();
+        future.completeExceptionally(new InterruptedException("Test interrupted"));
+        when(emailService.sendOTPMail(anyString(), anyString())).thenReturn(future);
+
+        String email = "user@example.com";
+
+        // Verify that OTPException is thrown
+        OTPException exception = assertThrows(OTPException.class, () -> {
+            otpService.generateOTP(email);
+        }, "Should throw OTPException when InterruptedException occurs");
+
+        assertTrue(exception.getMessage().contains("Failed to send OTP"));
+
+        // Verify that thread was interrupted
+        assertTrue(Thread.currentThread().isInterrupted(), "Thread should be interrupted");
+
+        // Clear the interrupted status for other tests
+        Thread.interrupted();
+    }
+
+    @Test
+    void testGenerateOTPExecutionException() {
+        // Mock email service to throw ExecutionException
+        CompletableFuture<Boolean> future = new CompletableFuture<>();
+        future.completeExceptionally(new ExecutionException("Test execution failed", new RuntimeException("Email service error")));
+        when(emailService.sendOTPMail(anyString(), anyString())).thenReturn(future);
+
+        String email = "user@example.com";
+
+        // Verify that OTPException is thrown
+        OTPException exception = assertThrows(OTPException.class, () -> {
+            otpService.generateOTP(email);
+        }, "Should throw OTPException when ExecutionException occurs");
+
+        assertTrue(exception.getMessage().contains("Failed to send OTP"));
+    }
+}
\ No newline at end of file
diff --git a/src/test/java/com/safetypin/authentication/service/TokenExpirationTest.java b/src/test/java/com/safetypin/authentication/service/TokenExpirationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..099681cb485a60e35e7405a7b08920f5d008b5b3
--- /dev/null
+++ b/src/test/java/com/safetypin/authentication/service/TokenExpirationTest.java
@@ -0,0 +1,108 @@
+package com.safetypin.authentication.service;
+
+import com.safetypin.authentication.dto.UserResponse;
+import com.safetypin.authentication.exception.InvalidCredentialsException;
+import com.safetypin.authentication.model.User;
+import com.safetypin.authentication.repository.UserRepository;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.JwtException;
+import io.jsonwebtoken.Jwts;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+import java.util.Date;
+import java.util.Optional;
+import java.util.UUID;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.when;
+
+public class TokenExpirationTest {
+
+
+    @Mock
+    private UserRepository userRepository;
+
+    @Mock
+    private PasswordEncoder passwordEncoder;
+
+    @Mock
+    private UserService userService;
+
+    @Mock
+    private OTPService otpService;
+
+    @Mock
+    private JwtService jwtService;
+
+
+    @BeforeEach
+    void setUp() {
+        MockitoAnnotations.openMocks(this);
+    }
+
+    @Test
+    void testExpiredTokenThrowsCorrectException() {
+        // Create a special test-only version of AuthenticationService
+        TestAuthenticationService testService = new TestAuthenticationService(
+                userService, passwordEncoder, otpService, jwtService);
+
+        // Create a UUID for our test
+        UUID userId = UUID.randomUUID();
+        User mockUser = new User();
+        mockUser.setId(userId);
+        
+        // Configure repository to return our user
+        when(userRepository.findById(userId)).thenReturn(Optional.of(mockUser));
+        
+        // Call our test method that forces the isExpired check to be true
+        InvalidCredentialsException exception = assertThrows(
+                InvalidCredentialsException.class,
+                () -> testService.testTokenExpiration(userId)
+        );
+        
+        // Verify we get the exact "Token expired" exception message
+        assertEquals("Token expired", exception.getMessage(), 
+                "The exception message should be 'Token expired' when a token is expired");
+    }
+
+    // This class extends AuthenticationService to allow us to test specific code paths
+    private class TestAuthenticationService extends AuthenticationService {
+        public TestAuthenticationService(UserService userService,
+                                       PasswordEncoder passwordEncoder, 
+                                       OTPService otpService,
+                                         JwtService jwtService) {
+            super(userService, passwordEncoder, otpService, jwtService);
+        }
+
+        // This method simulates the token expiration check portion of getUserFromJwtToken
+        public UserResponse testTokenExpiration(UUID userId) {
+            try {
+                // Mock a Claims object with an expired date
+                Claims claims = Jwts.claims()
+                        .setSubject(userId.toString())
+                        .setIssuedAt(new Date(System.currentTimeMillis() - 200000))
+                        .setExpiration(new Date(System.currentTimeMillis() - 100000)); // Expired!
+                
+                // This is the exact code from the main method that checks expiration
+                boolean isExpired = claims.getExpiration().before(new Date(System.currentTimeMillis()));
+                
+                if (isExpired) {
+                    throw new InvalidCredentialsException("Token expired");
+                }
+
+                // Get user from repository (this won't execute in our test)
+                Optional<User> user = userRepository.findById(userId);
+                if (user.isEmpty()) {
+                    throw new InvalidCredentialsException("User not found");
+                }
+                return user.get().generateUserResponse();
+            } catch (JwtException | IllegalArgumentException e) {
+                throw new InvalidCredentialsException("Invalid token");
+            }
+        }
+    }
+}
diff --git a/src/test/resources/application-dev.properties b/src/test/resources/application-dev.properties
index e42e68fd7cebc1b0e033fbdaadfad2e93ffa1545..2ca37e4a61400d18e5a4003082895632093751bb 100644
--- a/src/test/resources/application-dev.properties
+++ b/src/test/resources/application-dev.properties
@@ -1,14 +1,11 @@
 # src/test/resources/application-dev.properties
-
 # Configure H2 in-memory database
 spring.datasource.url=jdbc:h2:mem:devdb;DB_CLOSE_DELAY=-1
 spring.datasource.driverClassName=org.h2.Driver
 spring.datasource.username=sa
 spring.datasource.password=
-
 # JPA/Hibernate configurations
 spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
 spring.jpa.hibernate.ddl-auto=create-drop
-
 # (Optional) Enable SQL logging
-spring.jpa.show-sql=true
+spring.jpa.show-sql=true
\ No newline at end of file
diff --git a/src/test/resources/application-test.properties b/src/test/resources/application-test.properties
new file mode 100644
index 0000000000000000000000000000000000000000..18850ac55369aafd59d4bbaad0c9b35d2bd2d35f
--- /dev/null
+++ b/src/test/resources/application-test.properties
@@ -0,0 +1,7 @@
+spring.mail.host=127.0.0.1
+spring.mail.port=2525
+spring.mail.username=username
+spring.mail.password=secret123
+spring.mail.properties.mail.smtp.auth=true
+spring.mail.properties.mail.smtp.starttls.enable=false
+spring.mail.properties.mail.smtp.starttls.required=false