EmailServiceImpl.java
package com.ctrlbuy.webshop.service.impl;
import com.ctrlbuy.webshop.config.EmailProperties;
import com.ctrlbuy.webshop.entity.Order;
import com.ctrlbuy.webshop.security.entity.User;
import com.ctrlbuy.webshop.service.EmailService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import jakarta.mail.internet.MimeMessage;
import java.math.BigDecimal;
@Service
public class EmailServiceImpl implements EmailService {
private static final Logger logger = LoggerFactory.getLogger(EmailServiceImpl.class);
private final JavaMailSender mailSender;
private final EmailProperties emailProperties;
public EmailServiceImpl(JavaMailSender mailSender, EmailProperties emailProperties) {
this.mailSender = mailSender;
this.emailProperties = emailProperties;
}
// ========================================
// USER VERIFICATION & AUTH EMAILS
// ========================================
@Override
public void sendVerificationEmail(User user, String token) {
sendVerificationEmail(user.getEmail(), token, user.getFirstName());
}
@Override
public void sendVerificationEmail(String email, String token, String firstName) {
try {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setTo(email);
helper.setFrom(emailProperties.getFrom(), emailProperties.getFromName());
helper.setSubject("Bekräfta ditt konto - " + emailProperties.getCompany().getName());
helper.setText(buildVerificationEmailHtml(firstName, token), true);
mailSender.send(message);
logger.info("Verification email sent to: {}", email);
} catch (Exception e) {
logger.error("Failed to send verification email to: {}", email, e);
}
}
@Override
public boolean sendVerificationEmail(String email, String token) {
try {
sendVerificationEmail(email, token, "Kund");
return true;
} catch (Exception e) {
logger.error("Failed to send verification email", e);
return false;
}
}
@Override
public void sendWelcomeEmail(User user) {
try {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setTo(user.getEmail());
helper.setFrom(emailProperties.getFrom(), emailProperties.getFromName());
helper.setSubject("Välkommen till " + emailProperties.getCompany().getName() + "!");
helper.setText(buildWelcomeEmailHtml(user.getFirstName()), true);
mailSender.send(message);
logger.info("Welcome email sent to: {}", user.getEmail());
} catch (Exception e) {
logger.error("Failed to send welcome email to: {}", user.getEmail(), e);
}
}
// ========================================
// PASSWORD RESET EMAILS
// ========================================
@Override
public void sendPasswordResetEmail(User user, String resetToken) {
sendPasswordResetEmail(user.getEmail(), resetToken, user.getFirstName());
}
@Override
public void sendPasswordResetEmail(String email, String resetToken, String firstName) {
try {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setTo(email);
helper.setFrom(emailProperties.getFrom(), emailProperties.getFromName());
helper.setSubject("Återställ ditt lösenord - " + emailProperties.getCompany().getName());
helper.setText(buildPasswordResetEmailHtml(firstName, resetToken), true);
mailSender.send(message);
logger.info("Password reset email sent to: {}", email);
} catch (Exception e) {
logger.error("Failed to send password reset email to: {}", email, e);
}
}
@Override
public boolean sendPasswordResetEmail(String email, String resetToken) {
try {
sendPasswordResetEmail(email, resetToken, "Kund");
return true;
} catch (Exception e) {
logger.error("Failed to send password reset email", e);
return false;
}
}
// ========================================
// ORDER CONFIRMATION EMAILS - SIMPLIFIED
// ========================================
@Override
public void sendOrderConfirmationEmail(User user, String orderNumber) {
logger.info("Order confirmation requested for user: {} order: {}", user.getEmail(), orderNumber);
try {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setTo(user.getEmail());
helper.setFrom(emailProperties.getFrom(), emailProperties.getFromName());
helper.setSubject("Orderbekräftelse - Order #" + orderNumber);
helper.setText(buildBasicOrderConfirmationHtml(orderNumber, user.getFirstName()), true);
mailSender.send(message);
logger.info("Basic order confirmation sent to: {}", user.getEmail());
} catch (Exception e) {
logger.error("Failed to send basic order confirmation", e);
}
}
@Override
public void sendOrderConfirmation(com.ctrlbuy.webshop.entity.Order order, String email) {
try {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setTo(email);
helper.setFrom(emailProperties.getFrom(), emailProperties.getFromName());
helper.setSubject("Orderbekräftelse - Order #" + order.getId());
helper.setText(buildModelOrderConfirmationHtml(order, email), true);
mailSender.send(message);
logger.info("Model order confirmation sent for order: {} to: {}", order.getId(), email);
} catch (Exception e) {
logger.error("Failed to send model order confirmation", e);
}
}
@Override
public boolean sendOrderConfirmation(String email, com.ctrlbuy.webshop.entity.Order order) {
try {
sendOrderConfirmation(order, email);
return true;
} catch (Exception e) {
logger.error("Failed to send order confirmation", e);
return false;
}
}
// ========================================
// ACCOUNT MANAGEMENT EMAILS
// ========================================
@Override
public void sendAccountDeletionNotification(User deletedUser, String adminUsername, String reason) {
try {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setTo(deletedUser.getEmail());
helper.setFrom(emailProperties.getFrom(), emailProperties.getFromName());
helper.setSubject("Ditt konto har raderats - " + emailProperties.getCompany().getName());
helper.setText(buildAccountDeletionHtml(deletedUser.getFirstName(), adminUsername, reason), true);
mailSender.send(message);
logger.info("Account deletion notification sent to: {}", deletedUser.getEmail());
} catch (Exception e) {
logger.error("Failed to send account deletion notification", e);
}
}
@Override
public void sendAccountDeactivationNotification(User deactivatedUser, String adminUsername, String reason) {
try {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setTo(deactivatedUser.getEmail());
helper.setFrom(emailProperties.getFrom(), emailProperties.getFromName());
helper.setSubject("Ditt konto har inaktiverats - " + emailProperties.getCompany().getName());
helper.setText(buildAccountDeactivationHtml(deactivatedUser.getFirstName(), adminUsername, reason), true);
mailSender.send(message);
logger.info("Account deactivation notification sent to: {}", deactivatedUser.getEmail());
} catch (Exception e) {
logger.error("Failed to send account deactivation notification", e);
}
}
@Override
public void sendAccountReactivationNotification(User reactivatedUser, String adminUsername) {
try {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setTo(reactivatedUser.getEmail());
helper.setFrom(emailProperties.getFrom(), emailProperties.getFromName());
helper.setSubject("Ditt konto har återaktiverats - " + emailProperties.getCompany().getName());
helper.setText(buildAccountReactivationHtml(reactivatedUser.getFirstName(), adminUsername), true);
mailSender.send(message);
logger.info("Account reactivation notification sent to: {}", reactivatedUser.getEmail());
} catch (Exception e) {
logger.error("Failed to send account reactivation notification", e);
}
}
// ========================================
// ORDER STATUS EMAILS
// ========================================
@Override
public void sendShippingNotification(com.ctrlbuy.webshop.entity.Order order, String customerEmail) {
try {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setTo(customerEmail);
helper.setFrom(emailProperties.getFrom(), emailProperties.getFromName());
helper.setSubject("Din order har skickats - Order #" + order.getId());
helper.setText(buildShippingNotificationHtml(String.valueOf(order.getId())), true);
mailSender.send(message);
logger.info("Shipping notification sent for order: {}", order.getId());
} catch (Exception e) {
logger.error("Failed to send shipping notification", e);
}
}
@Override
public void sendDeliveryConfirmation(com.ctrlbuy.webshop.entity.Order order, String customerEmail) {
try {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setTo(customerEmail);
helper.setFrom(emailProperties.getFrom(), emailProperties.getFromName());
helper.setSubject("Din order har levererats - Order #" + order.getId());
helper.setText(buildDeliveryConfirmationHtml(String.valueOf(order.getId())), true);
mailSender.send(message);
logger.info("Delivery confirmation sent for order: {}", order.getId());
} catch (Exception e) {
logger.error("Failed to send delivery confirmation", e);
}
}
@Override
public void sendOrderCancellation(com.ctrlbuy.webshop.entity.Order order, String customerEmail) {
try {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
helper.setTo(customerEmail);
helper.setFrom(emailProperties.getFrom(), emailProperties.getFromName());
helper.setSubject("Din order har avbrutits - Order #" + order.getId());
helper.setText(buildOrderCancellationHtml(String.valueOf(order.getId())), true);
mailSender.send(message);
logger.info("Order cancellation sent for order: {}", order.getId());
} catch (Exception e) {
logger.error("Failed to send order cancellation", e);
}
}
// ========================================
// UTILITY METHODS
// ========================================
@Override
public boolean testEmailConnection() {
try {
mailSender.createMimeMessage();
logger.info("Email connection test successful");
return true;
} catch (Exception e) {
logger.error("Email connection test failed", e);
return false;
}
}
@Override
public boolean isConfigured() {
return emailProperties != null &&
emailProperties.getFrom() != null &&
!emailProperties.getFrom().isEmpty();
}
// ========================================
// SIMPLE WORKING CURRENCY FORMATTER
// ========================================
private String formatCurrency(BigDecimal amount) {
if (amount == null) {
return "0.00 kr";
}
// Fixed: Use BigDecimal directly, no type conversion needed
return amount + " kr";
}
// Overloaded method to handle Double inputs safely
private String formatCurrency(Double amount) {
if (amount == null) {
return "0.00 kr";
}
return BigDecimal.valueOf(amount) + " kr";
}
// ========================================
// HTML EMAIL TEMPLATES - MINIMAL WORKING VERSIONS
// ========================================
private String buildBasicOrderConfirmationHtml(String orderNumber, String customerName) {
return "<!DOCTYPE html><html><head><meta charset='UTF-8'>" + getEmailStyles() + "</head><body>" +
"<div class='header'>" +
"<h1>" + emailProperties.getCompany().getName() + "</h1>" +
"<h2>Orderbekräftelse</h2>" +
"</div>" +
"<div class='order-info'>" +
"<h3>Orderinformation</h3>" +
"<p><strong>Ordernummer:</strong> #" + orderNumber + "</p>" +
"<p><strong>Kund:</strong> " + customerName + "</p>" +
"</div>" +
getEmailFooter() +
"</body></html>";
}
private String buildModelOrderConfirmationHtml(com.ctrlbuy.webshop.entity.Order order, String customerEmail) {
return "<!DOCTYPE html><html><head><meta charset='UTF-8'>" + getEmailStyles() + "</head><body>" +
"<div class='header'>" +
"<h1>" + emailProperties.getCompany().getName() + "</h1>" +
"<h2>Orderbekräftelse</h2>" +
"</div>" +
"<div class='order-info'>" +
"<h3>Orderinformation</h3>" +
"<p><strong>Ordernummer:</strong> #" + order.getId() + "</p>" +
"<p><strong>E-post:</strong> " + customerEmail + "</p>" +
"<p><strong>Totalt:</strong> " + formatCurrency(order.getTotalAmount()) + "</p>" +
"</div>" +
getEmailFooter() +
"</body></html>";
}
// ========================================
// SIMPLE HTML TEMPLATES
// ========================================
private String buildVerificationEmailHtml(String firstName, String token) {
return "<!DOCTYPE html><html><body>" +
"<h2>Bekräfta ditt konto</h2>" +
"<p>Hej " + firstName + ",</p>" +
"<p>Klicka på länken för att bekräfta ditt konto:</p>" +
"<a href='http://localhost:8080/verify?token=" + token + "'>Bekräfta konto</a>" +
"</body></html>";
}
private String buildWelcomeEmailHtml(String firstName) {
return "<!DOCTYPE html><html><body>" +
"<h2>Välkommen!</h2>" +
"<p>Hej " + firstName + ",</p>" +
"<p>Välkommen till " + emailProperties.getCompany().getName() + "!</p>" +
"</body></html>";
}
private String buildPasswordResetEmailHtml(String firstName, String resetToken) {
return "<!DOCTYPE html><html><body>" +
"<h2>Återställ lösenord</h2>" +
"<p>Hej " + firstName + ",</p>" +
"<p>Klicka på länken för att återställa ditt lösenord:</p>" +
"<a href='http://localhost:8080/reset-password?token=" + resetToken + "'>Återställ lösenord</a>" +
"</body></html>";
}
private String buildAccountDeletionHtml(String firstName, String adminUsername, String reason) {
return "<!DOCTYPE html><html><body>" +
"<h2>Konto raderat</h2>" +
"<p>Hej " + firstName + ",</p>" +
"<p>Ditt konto har raderats av admin: " + adminUsername + "</p>" +
(reason != null ? "<p>Anledning: " + reason + "</p>" : "") +
"</body></html>";
}
private String buildAccountDeactivationHtml(String firstName, String adminUsername, String reason) {
return "<!DOCTYPE html><html><body>" +
"<h2>Konto inaktiverat</h2>" +
"<p>Hej " + firstName + ",</p>" +
"<p>Ditt konto har inaktiverats av admin: " + adminUsername + "</p>" +
(reason != null ? "<p>Anledning: " + reason + "</p>" : "") +
"</body></html>";
}
private String buildAccountReactivationHtml(String firstName, String adminUsername) {
return "<!DOCTYPE html><html><body>" +
"<h2>Konto återaktiverat</h2>" +
"<p>Hej " + firstName + ",</p>" +
"<p>Ditt konto har återaktiverats av admin: " + adminUsername + "</p>" +
"</body></html>";
}
private String buildShippingNotificationHtml(String orderId) {
return "<!DOCTYPE html><html><body>" +
"<h2>Din order har skickats</h2>" +
"<p>Order #" + orderId + " har skickats!</p>" +
"</body></html>";
}
private String buildDeliveryConfirmationHtml(String orderId) {
return "<!DOCTYPE html><html><body>" +
"<h2>Din order har levererats</h2>" +
"<p>Order #" + orderId + " har levererats!</p>" +
"</body></html>";
}
private String buildOrderCancellationHtml(String orderId) {
return "<!DOCTYPE html><html><body>" +
"<h2>Din order har avbrutits</h2>" +
"<p>Order #" + orderId + " har avbrutits.</p>" +
"</body></html>";
}
private String getEmailStyles() {
return "<style>" +
"body { font-family: Arial, sans-serif; margin: 20px; }" +
".header { background-color: #2c3e50; color: white; padding: 20px; text-align: center; }" +
".order-info { background-color: #ecf0f1; padding: 15px; margin: 20px 0; }" +
".total-line { display: flex; justify-content: space-between; margin: 5px 0; }" +
"</style>";
}
private String getEmailFooter() {
return "<div style='margin-top: 30px; text-align: center; color: #7f8c8d;'>" +
"<p>Tack för din beställning!</p>" +
"<p>" + emailProperties.getFromName() + "</p>" +
(emailProperties.getCompany().getSupportEmail() != null ?
"<p>Support: " + emailProperties.getCompany().getSupportEmail() + "</p>" : "") +
"</div>";
}
}