Skip to content

Commit

Permalink
Sending mails (#61)
Browse files Browse the repository at this point in the history
* basic email system
---------

Co-authored-by: Sundarakrishnan N <[email protected]>
Co-authored-by: SundarakrishnanN <[email protected]>
Co-authored-by: Prajwal P <[email protected]>
  • Loading branch information
4 people authored Jun 14, 2024
1 parent d51b3dc commit 19b19f8
Show file tree
Hide file tree
Showing 11 changed files with 413 additions and 41 deletions.
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,4 @@ out/
.vscode/

.env.prod
/src/main/resources/application-prod.properties

/src/main/resources/application-prod.properties
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-mail'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.modelmapper:modelmapper:3.2.0'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
Expand Down
10 changes: 7 additions & 3 deletions src/main/java/org/ieeervce/gatekeeper/GateKeeperApplication.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
package org.ieeervce.gatekeeper;

import org.ieeervce.gatekeeper.dto.Email.EmailDTO;
import org.ieeervce.gatekeeper.service.EmailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@SpringBootApplication
@RestController
@EnableAsync
public class GateKeeperApplication {

@GetMapping("/")
String index(){
return "GateKeeper";
String index() throws Exception{
return "gatekeeper";
}

public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,28 @@

import static org.ieeervce.gatekeeper.config.SecurityConfiguration.getRequesterDetails;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Optional;
import jakarta.mail.MessagingException;
import org.ieeervce.gatekeeper.dto.Email.EmailDTO;
import org.ieeervce.gatekeeper.dto.RequestForm.RequestDTO;
import org.ieeervce.gatekeeper.dto.RequestForm.RequestFormPdfDTO;
import org.ieeervce.gatekeeper.dto.RequestForm.ResponseRequestFormDTO;
import org.ieeervce.gatekeeper.entity.*;
import org.ieeervce.gatekeeper.exception.InvalidDataException;
import org.ieeervce.gatekeeper.exception.ItemNotFoundException;
import org.ieeervce.gatekeeper.exception.PDFNotConversionException;
import org.ieeervce.gatekeeper.service.RequestFormService;
import org.ieeervce.gatekeeper.service.ReviewLogService;
import org.ieeervce.gatekeeper.service.RoleService;
import org.ieeervce.gatekeeper.service.UserService;
import org.ieeervce.gatekeeper.service.*;
import org.modelmapper.ModelMapper;
import org.modelmapper.PropertyMap;
import org.modelmapper.TypeToken;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
Expand Down Expand Up @@ -50,6 +51,9 @@ public class RequestFormController {
private final RoleService roleService;
private final UserService userService;
private final ReviewLogService reviewLogService;
@Autowired
EmailService emailService ;

PropertyMap<RequestForm, ResponseRequestFormDTO> skipReferencedFieldsMap = new PropertyMap<RequestForm, ResponseRequestFormDTO>() {
@Override
protected void configure() {
Expand Down Expand Up @@ -135,34 +139,28 @@ public void deleteRequestForm(@PathVariable Long requestFormId) throws ItemNotFo
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseRequestFormDTO postRequestForm(@RequestParam("eventTitle") String eventTitle,
@RequestParam("isFinance") boolean isFinance, @RequestParam("formPDF") MultipartFile formPDF)
throws InvalidDataException, PDFNotConversionException {
{
LOGGER.info("in: post request form");
RequestForm savedRequestForm;
RequestForm requestForm = new RequestForm();
requestForm.setEventTitle(eventTitle);
requestForm.setFinance(isFinance);
requestForm.setStatus(FinalStatus.PENDING);

LOGGER.debug("Requester Details: {}", getRequesterDetails());
User optionalUser = userService.getUserByEmail(getRequesterDetails()).get();
requestForm.setRequester(optionalUser);
requestForm.setRequestHierarchy(roleService.generateHierarchy(optionalUser, isFinance));
try {
User optionalUser = userService.getUserByEmail(getRequesterDetails()).get();
requestForm.setRequester(optionalUser);

requestForm.setRequestHierarchy(roleService.generateHierarchy(optionalUser, isFinance));

userService.setPendingRequests(requestForm, requestForm.getRequestHierarchy(),
requestForm.getRequestIndex(), optionalUser);
} catch (Exception e) {
LOGGER.warn("Exception getting user and hierarchy", e);
}

try {
requestForm.setFormPDF(formPDF.getBytes());
} catch (java.io.IOException e) {
throw new PDFNotConversionException("Could not store pdf");
requestForm.setFormPDF(formPDF.getBytes());
}

RequestForm savedRequestForm = requestFormService.save(requestForm);
return modelMapper.map(savedRequestForm, ResponseRequestFormDTO.class);// truncated
catch (IOException e) {
LOGGER.warn("Exception on converting pdf to bytes", e);
}
savedRequestForm = requestFormService.save(requestForm);
userService.setPendingRequests(savedRequestForm, savedRequestForm.getRequestHierarchy(),
savedRequestForm.getRequestIndex(), optionalUser);
return modelMapper.map(savedRequestForm, ResponseRequestFormDTO.class);
}

@PutMapping("/{requestFormId}")
Expand Down Expand Up @@ -205,16 +203,38 @@ public ResponseRequestFormDTO approveRequest(@PathVariable Long requestFormId, S

reviewLogService.addReview(reviewLog);
requestForm.getReviewLogs().add(reviewLog);

//Logic for Sending Mails to Requester
try{
String messageBody = "Your request for Event Titled" + requestForm.getEventTitle() +" has successfully been approved by "+ optionalUser.getName() +".";
User requester = requestForm.getRequester();
EmailDTO emailDTO = new EmailDTO(requester,messageBody,requestForm);
emailDTO.setSubject("Approved By "+optionalUser.getName());
emailService.sendSimpleMail(emailDTO);
}
catch (MessagingException e){
LOGGER.error("Approval Confirmation Mail To Requester Failed");
}

requestForm.setRequestIndex(index + 1);
index++;
if (index < requestForm.getRequestHierarchy().size())
userService.setPendingRequests(requestForm, requestForm.getRequestHierarchy(), index,
requestForm.getRequester());
else {
requestForm.setStatus(FinalStatus.ACCEPTED);
try{
String messageBody = "Your request for Event Titled , " + requestForm.getEventTitle() +" has been approved.";
User requester = requestForm.getRequester();
EmailDTO emailDTO = new EmailDTO(requester,messageBody,requestForm);
emailDTO.setSubject("Event Request Approved");
emailService.sendSimpleMail(emailDTO);
}
catch (MessagingException e)
{
LOGGER.error("ACCEPTED Request Mail Failed");
}
}
// TODO send mails to requester at every step and send mail to the next set of
// users assigned(update setPendingRequests() method to add this)
return modelMapper.map(requestFormService.save(requestForm), ResponseRequestFormDTO.class);// truncated
}

Expand Down Expand Up @@ -250,8 +270,17 @@ public ResponseRequestFormDTO rejectRequest(@PathVariable Long requestFormId, St
reviewLogService.addReview(reviewLog);
requestForm.setStatus(FinalStatus.REJECTED);
requestForm.getReviewLogs().add(reviewLog);
try{
String messageBody = "Your request for Event Titled , " + requestForm.getEventTitle() +" has been rejected.";
User requester = requestForm.getRequester();
EmailDTO emailDTO = new EmailDTO(requester,messageBody,requestForm);
emailDTO.setSubject("Event Request Rejected");
emailService.sendSimpleMail(emailDTO);
}
catch (MessagingException e){
LOGGER.error("Failed To Send Rejection Mail");
}
return modelMapper.map(requestFormService.save(requestForm), ResponseRequestFormDTO.class);// truncated
// TODO update requester with email
}

@GetMapping("/pdf/{requestFormId}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.ieeervce.gatekeeper.entity.Role;
import org.ieeervce.gatekeeper.entity.Society;
import org.ieeervce.gatekeeper.entity.User;
import org.ieeervce.gatekeeper.service.EmailService;
import org.ieeervce.gatekeeper.service.RoleService;
import org.ieeervce.gatekeeper.service.SocietyService;
import org.modelmapper.ModelMapper;
Expand Down Expand Up @@ -47,10 +48,12 @@ public UserController(UserService userService, ModelMapper modelMapper,SocietySe
this.modelMapper.addMappings(skipReferencedFieldsMap);
this.modelMapper.getConfiguration().setAmbiguityIgnored(true);
}
@Autowired
EmailService emailService;

@PostMapping
User addUser(@RequestBody UserDTO userDTO) throws InvalidDataException {
User user = modelMapper.map(userDTO,User.class);
User user = modelMapper.map(userDTO,User.class);
user.setPassword(passwordEncoder.encode(userDTO.getPassword()));
try {
if(userDTO.getSocietyId()!=null) {
Expand All @@ -63,10 +66,9 @@ User addUser(@RequestBody UserDTO userDTO) throws InvalidDataException {
catch (ItemNotFoundException e){
throw new InvalidDataException("Invalid Data");
}



return userService.saveUser(user);
User savedUser = userService.saveUser(user);
emailService.sendUserCredentials(userDTO.getEmail(),userDTO.getPassword());
return savedUser;
}
@GetMapping
public String getUser()
Expand Down
66 changes: 66 additions & 0 deletions src/main/java/org/ieeervce/gatekeeper/dto/Email/EmailDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.ieeervce.gatekeeper.dto.Email;

import org.ieeervce.gatekeeper.entity.RequestForm;
import org.ieeervce.gatekeeper.entity.User;

public class EmailDTO {
private String recipient;
private String messageBody;
private String subject;
private byte[] attachment;
private String name;
private String formLink;
public String getFormLink() {
return formLink;
}
public EmailDTO(User user, String messageBody,RequestForm requestForm){
this.recipient =user.getEmail();
this.messageBody=messageBody;
this.name = user.getName().split(" ")[0];
this.attachment = requestForm.getFormPDF();
this.formLink = "gate.ieee-rvce.org/event/"+requestForm.getRequestFormId();
}
public void setFormLink(String formLink) {
this.formLink = formLink;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getRecipient() {
return recipient;
}

public void setRecipient(String recipient) {
this.recipient = recipient;
}

public String getMessageBody() {
return messageBody;
}

public void setMessageBody(String messageBody) {
this.messageBody = messageBody;
}

public String getSubject() {
return subject;
}

public void setSubject(String subject) {
this.subject = subject;
}

public byte[] getAttachment() {
return attachment;
}

public void setAttachment(byte[] attachment) {
this.attachment = attachment;
}
}
59 changes: 59 additions & 0 deletions src/main/java/org/ieeervce/gatekeeper/service/EmailService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.ieeervce.gatekeeper.service;

import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import org.ieeervce.gatekeeper.dto.Email.EmailDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;


@Service
public class EmailService {
//in this implementation the unchecked exception MailException has not been handled, if anything breaks do check this out too
@Autowired
private JavaMailSender javaMailSender;
@Autowired
private TemplateEngine templateEngine;
@Value("${spring.mail.username}") private String sender;
@Async
public void sendUserCredentials(String userEmail,String userPassword) {
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
simpleMailMessage.setFrom(sender);
simpleMailMessage.setTo(userEmail);
simpleMailMessage.setSubject("GateKeeper Account Successfully Created!");
simpleMailMessage.setText("Dear User,\n Your GateKeeper account has successfully been created!\nPlease login to https://gate.ieee-rvce.org/ and change your password as soon as you can.\n\nEmail: " + userEmail + "\nPassword: "+userPassword+"\n\nThank you,\nIEEE RVCE Web Team");
javaMailSender.send(simpleMailMessage);
}
@Async
public void sendSimpleMail(EmailDTO emailDetails) throws MessagingException{

MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper mimeMessageHelper ;

mimeMessageHelper = new MimeMessageHelper(mimeMessage,true);
mimeMessageHelper.setFrom(sender);
mimeMessageHelper.setTo(emailDetails.getRecipient());
mimeMessageHelper.setSubject(emailDetails.getSubject());
//Setting context of variables for the html file
Context context = new Context();
context.setVariable("header",emailDetails.getSubject());
context.setVariable("name",emailDetails.getName().split(" ")[0]);
context.setVariable("messageBody",emailDetails.getMessageBody());
context.setVariable("linkUrl",emailDetails.getFormLink());

String htmlContent = templateEngine.process("emailTemplate",context);
mimeMessageHelper.setText(htmlContent,true);
mimeMessageHelper.addAttachment("Event PDF.pdf",new ByteArrayResource(emailDetails.getAttachment()));
javaMailSender.send(mimeMessage);

}
}
18 changes: 18 additions & 0 deletions src/main/java/org/ieeervce/gatekeeper/service/UserService.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package org.ieeervce.gatekeeper.service;

import jakarta.mail.MessagingException;
import org.ieeervce.gatekeeper.controller.RequestFormController;
import org.ieeervce.gatekeeper.dto.Email.EmailDTO;
import org.ieeervce.gatekeeper.exception.ItemNotFoundException;
import org.ieeervce.gatekeeper.entity.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.*;
import org.ieeervce.gatekeeper.repository.UserRepository;
Expand All @@ -16,7 +21,11 @@ public class UserService {
private RoleValue roleValue;
private final String ITEM_NOT_FOUND = "User Id not found";

private static final Logger LOGGER = LoggerFactory.getLogger(UserService.class);

private final UserRepository repository;
@Autowired
EmailService emailService ;

public UserService(UserRepository repository) {
this.repository = repository;
Expand Down Expand Up @@ -62,6 +71,15 @@ public void setPendingRequests(RequestForm requestForm, List<Role> requestHierar
}
for (User u : users) {
u.getPendingRequests().add(requestForm);
String messageBody ="Request for approval for the event titled " + requestForm.getEventTitle() + ", submitted by " + u.getName() + ".";
EmailDTO emailDTO = new EmailDTO(u,messageBody,requestForm);
emailDTO.setSubject("Mail For Approval - IEEE Event");
try{
emailService.sendSimpleMail(emailDTO);
}
catch (MessagingException e){
LOGGER.error("Failed To Send Mail For Approval");
}
}
}

Expand Down
Loading

0 comments on commit 19b19f8

Please sign in to comment.