From 6fb7824d8ae62c14c14876fc75a64e82a79e041b Mon Sep 17 00:00:00 2001 From: Bernhard Luedtke Date: Fri, 9 Jul 2021 17:13:51 +0200 Subject: [PATCH] Transfer of mailing execution to actual mailservice --- .../controller/MailController.java | 115 +++++++----------- .../de/fswiai/klausurenmodul/model/Email.java | 51 +++++++- .../klausurenmodul/service/MailService.java | 112 +++++++++++++---- 3 files changed, 183 insertions(+), 95 deletions(-) diff --git a/src/main/java/de/fswiai/klausurenmodul/controller/MailController.java b/src/main/java/de/fswiai/klausurenmodul/controller/MailController.java index a09cf7b..a9abfde 100644 --- a/src/main/java/de/fswiai/klausurenmodul/controller/MailController.java +++ b/src/main/java/de/fswiai/klausurenmodul/controller/MailController.java @@ -1,101 +1,74 @@ package de.fswiai.klausurenmodul.controller; import de.fswiai.klausurenmodul.model.Email; +import de.fswiai.klausurenmodul.service.MailService; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import javax.mail.*; -import javax.mail.internet.InternetAddress; -import javax.mail.internet.MimeBodyPart; -import javax.mail.internet.MimeMessage; -import javax.mail.internet.MimeMultipart; -import java.util.Properties; import java.util.concurrent.atomic.AtomicLong; @RestController public class MailController { + //DEPRECATED private static final String template = "Hello %s! This is a test mail from the Fachschaft WIAI."; - private static final String user = ""; - private static final String pw = ""; + + //TODO controllers should be stateless. This certainly is not. Solve differently. private final AtomicLong counter = new AtomicLong(); //from the tutorial... deprc @GetMapping("/mail") public Email showDefaultMail(@RequestParam(value="recipientName", defaultValue = "Student") String recipientName){ - return new Email(counter.incrementAndGet(),"defaultMailDestination", "defaultMailSource", String.format(template, recipientName)); + return new Email(counter.incrementAndGet(),"defaultMailDestination", "defaultMailSource", String.format(template, recipientName), "defaultSubject"); } - //void for now only + //TODO Return datatype does not make sense yet -> Ask the frontend people @PostMapping("/mail") public Email sendMail( @RequestParam(value = "recipientName", defaultValue = "") String recipientName, @RequestParam(value = "toMail", defaultValue = "") String toMail, - @RequestParam(value = "fromMail", defaultValue = "") String fromMail) + @RequestParam(value = "fromMail", defaultValue = "") String fromMail, + @RequestParam(value = "subject", defaultValue = "") String subject, + @RequestParam(value = "body", defaultValue = "") String body, + @RequestParam(value = "mailConfig", defaultValue = "") String mailConfig) { - Email mail = new Email(counter.incrementAndGet(), toMail, fromMail, String.format(template, recipientName)); - - Properties prop = new Properties(); - prop.put("mail.smtp.auth", true); - prop.put("mail.smtp.starttls.enable", "true"); - prop.put("mail.smtp.starttls.required", "true"); - prop.put("mail.smtp.host", "exhub.uni-bamberg.de"); - prop.put("mail.smtp.port", "587"); - prop.put("mail.smtp.ssl.protocols", "TLSv1.2"); - prop.put("mail.smtp.ssl.trust", "exhub.uni-bamberg.de"); - - - Session session = Session.getInstance(prop, new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(user, pw); - } - }); - System.out.println("- Attempting to send Mail:"); - System.out.println(" Recipient Name: " + recipientName); - System.out.println(" ToMail: " + toMail); - System.out.println(" FromMail: " + fromMail); - if(toMail.isEmpty() || fromMail.isEmpty()){ System.out.println("Abort Mail sending"); - return new Email(-1, "", "", ""); + return new Email(-1, "", "", "", ""); } - try { - Message message = new MimeMessage(session); - message.setFrom(new InternetAddress(mail.getSourceAddress())); - - // Stupid array. How is there not a method to only parse one address? TODO fix - message.setRecipient(Message.RecipientType.TO, InternetAddress.parse(mail.getDestinationAddress())[0]); - message.setSubject("Altklausuren-Anfrage"); - - final String body = mail.getBody(); - - MimeBodyPart mimeBodyPart = new MimeBodyPart(); - mimeBodyPart.setContent(body,"text/html"); - - Multipart multipart = new MimeMultipart(); - multipart.addBodyPart(mimeBodyPart); - - //TODO add the watermarked exams here - //MimeBodyPart attachmentBodyPart = new MimeBodyPart(); - //attachmentBodyPart.attachFile(new File("path/to/file")); - //multipart.addBodyPart(attachmentBodyPart); - - message.setContent(multipart); - Transport.send(message); - System.out.println("- Mail Sent Successfully"); - - return mail; - } catch (javax.mail.internet.AddressException jMailException) { - System.err.println("Address Exception whilst sending the mail"); - jMailException.printStackTrace(); - return new Email(-1, "", "", ""); - - } catch (javax.mail.MessagingException jMailException) { - System.err.println("Messaging Exception whilst sending the mail"); - jMailException.printStackTrace(); - return new Email(-1, "", "", ""); - + + Email mail = new Email(counter.incrementAndGet(), toMail, fromMail, body, subject); + // TODO add all the exam file stuff via another service, i.e. WatermarkingService + // ... + // TODO Mail Validate + if(mail.validateFields()){ + try { + // TODO load the mail config file dep. on the given name in mailConfig and load that config. + MailService mailService = new MailService(); + //For now... + mailService.loadDevelopmentDefault(); + //mailService.loadFromConfig(); + + // Send the mail via the mailService + boolean sendResult = mailService.sendMail(mail); + + //TODO Properly handle return value from sendMail + if(sendResult){ + System.out.println("Mail was sent successfully."); + } + return mail; + } catch (javax.mail.internet.AddressException jMailException) { + System.err.println("Address Exception whilst sending the mail"); + jMailException.printStackTrace(); + return new Email(-1, "", "", "", ""); + } catch (javax.mail.MessagingException jMailException) { + System.err.println("Messaging Exception whilst sending the mail"); + jMailException.printStackTrace(); + return new Email(-1, "", "", "", ""); + } + } else { + System.err.println("Mail is not valid."); + return new Email(-1, "", "", "", ""); } } } diff --git a/src/main/java/de/fswiai/klausurenmodul/model/Email.java b/src/main/java/de/fswiai/klausurenmodul/model/Email.java index c17e478..0a45d34 100644 --- a/src/main/java/de/fswiai/klausurenmodul/model/Email.java +++ b/src/main/java/de/fswiai/klausurenmodul/model/Email.java @@ -1,24 +1,44 @@ package de.fswiai.klausurenmodul.model; +import java.io.File; +import java.util.List; + public class Email { private final long id; private String destinationAddress; private String sourceAddress; private String body; - // Appended documents? - // bool 'sent'? + private String subject; + private List fileList; - public Email(long id, String destinationAddress, String sourceAddress, String body){ + public Email(long id, String destinationAddress, String sourceAddress, String body, String subject, List fileList) { this.id = id; this.destinationAddress = destinationAddress; this.sourceAddress = sourceAddress; this.body = body; + this.subject = subject; + this.fileList = fileList; + } + + public Email(long id, String destinationAddress, String sourceAddress, String body, String subject) { + this.id = id; + this.destinationAddress = destinationAddress; + this.sourceAddress = sourceAddress; + this.body = body; + this.subject = subject; + fileList = null; } public long getId() { return id; } + public boolean hasFiles() { + if(fileList == null){ + return false; + } else return (!fileList.isEmpty()); + } + public String getDestinationAddress() { return destinationAddress; } @@ -42,4 +62,29 @@ public class Email { public void setBody(String body) { this.body = body; } + + public String getSubject() { + return subject; + } + + public void setSubject(String subject) { + this.subject = subject; + } + + public List getFileList() { + return fileList; + } + + public void setFileList(List fileList) { + this.fileList = fileList; + } + + public boolean validateFields(){ + if(sourceAddress.isEmpty() || destinationAddress.isEmpty() || subject.isEmpty() || body.isEmpty()){ + System.err.println("attribute(s) in mail are missing."); + return false; + } else { + return true; + } + } } diff --git a/src/main/java/de/fswiai/klausurenmodul/service/MailService.java b/src/main/java/de/fswiai/klausurenmodul/service/MailService.java index 37880e2..e2867a8 100644 --- a/src/main/java/de/fswiai/klausurenmodul/service/MailService.java +++ b/src/main/java/de/fswiai/klausurenmodul/service/MailService.java @@ -1,9 +1,15 @@ package de.fswiai.klausurenmodul.service; -import javax.mail.Authenticator; -import javax.mail.PasswordAuthentication; -import javax.mail.Session; +import de.fswiai.klausurenmodul.model.Email; + +import javax.mail.*; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeBodyPart; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; import java.io.File; +import java.io.IOException; +import java.util.List; import java.util.Properties; public class MailService { @@ -14,6 +20,9 @@ public class MailService { private String tlsVersion = "TLSv1.2"; //maybe already use 1.3? private boolean useSTARTTLS = true; + public MailService() { + } + public MailService(String username, String password, int smtpPort, String smtpHost, String tlsVersion, boolean useSTARTTLS) { this.username = username; this.password = password; @@ -23,35 +32,96 @@ public class MailService { this.useSTARTTLS = useSTARTTLS; } - //TODO switch boolean to some result class - public boolean sendSimpleMail(String subject, String body) - throws javax.mail.internet.AddressException, javax.mail.MessagingException { - - return true; + public void loadFromConfig(String configJSON){ + //TODO First Idea for how we handle mail accounts/configurations. + // -> Build some parser for a JSON schema (or something else, idc) that will set username, password and so on. + } + + public void loadDevelopmentDefault(){ + this.username = "ex311199c"; + this.password = ""; + this.smtpPort = 587; + this.smtpHost = "exhub.uni-bamberg.de"; + this.tlsVersion = "TLSv1.2"; + this.useSTARTTLS = true; } //TODO switch boolean to some result class - public boolean sendMailWithAttachments(String subject, String body, File[] files) - throws javax.mail.internet.AddressException, javax.mail.MessagingException { + //TODO switch to a proper logging framework + public boolean sendMail(Email mail) + throws javax.mail.internet.AddressException, javax.mail.MessagingException + { + System.out.println("- Attempting to send Mail:"); + System.out.println(" From: " + mail.getSourceAddress()); + System.out.println(" To: " + mail.getDestinationAddress()); - return true; + // Open the session and generate the basic message + Session session = getNewSession(); + Message message = generateBaseMessage(session, mail); + + if(message != null){ + // Add the message body as a mime body part. + MimeBodyPart mimeBodyPart = new MimeBodyPart(); + mimeBodyPart.setContent(mail.getBody(),"text/html"); + Multipart multipart = new MimeMultipart(); + multipart.addBodyPart(mimeBodyPart); + + // If the Email Object contains files to append, then append them. + if(mail.hasFiles()){ + // Add the files to append + mail.getFileList().forEach(file -> { + try { + MimeBodyPart attachmentBodyPart = new MimeBodyPart(); + attachmentBodyPart.attachFile(file); + multipart.addBodyPart(attachmentBodyPart); + } catch (IOException e) { + System.err.println("File Attachment IO Exception"); + e.printStackTrace(); + } catch (MessagingException e) { + System.err.println("File Attachment Message Exception"); + e.printStackTrace(); + } + }); + } + + // Set the prepared Mime Multipart as the message content + message.setContent(multipart); + + // Send the message + Transport.send(message); + return true; + + } else { + System.err.println("Unable to send a mail (mail message creation failed)."); + return false; + } } - private Session configureSession(){ + private Message generateBaseMessage(Session session, Email mail){ + try { + Message message = new MimeMessage(session); + message.setFrom(new InternetAddress(mail.getSourceAddress())); + message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(mail.getDestinationAddress())); + message.setSubject(mail.getSubject()); + return message; + } catch (javax.mail.internet.AddressException jMailException) { + System.err.println("Address Exception whilst generating the mail message"); + } catch (javax.mail.MessagingException jMailException) { + System.err.println("Messaging Exception whilst generating the mail message"); + } + return null; + } + + + private Session getNewSession(){ Properties prop = new Properties(); prop.put("mail.smtp.auth", true); - if(this.useSTARTTLS){ - prop.put("mail.smtp.starttls.enable", "true"); - prop.put("mail.smtp.starttls.required", "true"); - } else { - prop.put("mail.smtp.starttls.enable", "false"); - prop.put("mail.smtp.starttls.required", "false"); - } - + prop.put("mail.smtp.starttls.enable", this.useSTARTTLS ? "true" : "false"); + prop.put("mail.smtp.starttls.required", this.useSTARTTLS ? "true" : "false"); prop.put("mail.smtp.host", this.smtpHost); prop.put("mail.smtp.port", this.smtpPort); prop.put("mail.smtp.ssl.protocols", this.tlsVersion); - prop.put("mail.smtp.ssl.trust", "exhub.uni-bamberg.de"); + prop.put("mail.smtp.ssl.trust", this.smtpHost); Session session = Session.getInstance(prop, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() {