package ru.soune.nocopy.service.mail; import jakarta.mail.MessagingException; import jakarta.mail.internet.MimeMessage; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.ClassPathResource; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import ru.soune.nocopy.entity.user.AuthToken; import ru.soune.nocopy.entity.user.EmailVerificationToken; import ru.soune.nocopy.entity.user.User; import ru.soune.nocopy.repository.EmailVerificationTokenRepository; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.security.SecureRandom; import java.time.LocalDateTime; @Service @RequiredArgsConstructor @Slf4j public class EmailService { private final JavaMailSender mailSender; private final EmailVerificationTokenRepository emailVerificationTokenRepository; @Value("${app.email.verification.standart-subject}") private String standartSubject; @Value("${app.email.verification.standart-address-from}") private String standartAdressFrom; @Value("${app.email.verification.user}") private String user; @Value("${app.email.verification.drop-password-subject}") private String dropPasswordSubject; @Value("${server.baseurl}") private String baseUrl; @Value("${server.front.port}") private String frontPort; public void sendVerificationEmail(User user, String code) throws MessagingException, IOException { MimeMessage message = mailSender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8"); helper.setFrom("noreply@no-copy.ru"); helper.setTo(user.getEmail()); helper.setSubject(standartSubject); String htmlContent = loadAndProcessTemplate(user.getFullName(), code, "templates/email-verification.html"); helper.setText(htmlContent, true); mailSender.send(message); } @Transactional public EmailVerificationToken createEmailVerificationToken(AuthToken authToken) { EmailVerificationToken existingToken = emailVerificationTokenRepository .findByUserId(authToken.getUser().getId()); if (existingToken != null) { emailVerificationTokenRepository.deleteById(existingToken.getId()); } EmailVerificationToken emailToken = new EmailVerificationToken(); emailToken.setUser(authToken.getUser()); emailToken.setToken(generateVerificationCode()); emailToken.setCreatedAt(LocalDateTime.now()); return emailVerificationTokenRepository.save(emailToken); } private String generateVerificationCode() { SecureRandom random = new SecureRandom(); int code = 100000 + random.nextInt(900000); return String.valueOf(code); } private String loadAndProcessTemplate(String username, String code, String templatePath) throws IOException { ClassPathResource resource = new ClassPathResource(templatePath); String template = new String(resource.getInputStream().readAllBytes(), StandardCharsets.UTF_8); String safeUsername = escapeHtml(username != null ? username : user); String safeCode = escapeHtml(code); return template .replace("{{username}}", safeUsername) .replace("{{code}}", safeCode); } private String escapeHtml(String text) { if (text == null) return ""; return text .replace("&", "&") .replace("<", "<") .replace(">", ">") .replace("\"", """) .replace("'", "'"); } public void sendResetPasswordEmail(User user, String code) { try { MimeMessage message = mailSender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8"); helper.setFrom(standartAdressFrom); helper.setTo(user.getEmail()); helper.setSubject(dropPasswordSubject); String htmlContent = loadAndProcessTemplate(user.getFullName(), code, "templates/reset-password.html"); //TODO frontPort убрать после настройки редиректа nginx String resetLink = escapeHtml(baseUrl + frontPort + "/reset-password?email=" + user.getEmail()); htmlContent = htmlContent.replace("{{resetLink}}", resetLink); helper.setText(htmlContent, true); mailSender.send(message); log.info("Email sent to: {}", user.getEmail()); } catch (Exception e) { log.error("Failed to send email: {}", e.getMessage()); } } }