Skip to content

Commit

Permalink
feat: move smtp settings to .env
Browse files Browse the repository at this point in the history
  • Loading branch information
astappiev committed Sep 16, 2024
1 parent b9696f8 commit 3ac9faf
Show file tree
Hide file tree
Showing 19 changed files with 293 additions and 190 deletions.
4 changes: 4 additions & 0 deletions src/main/java/de/l3s/learnweb/app/ConfigProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,10 @@ public boolean getPropertyBoolean(final String key) {
return "true".equalsIgnoreCase(properties.getProperty(key));
}

public boolean getPropertyBoolean(final String key, final String defaultValue) {
return "true".equalsIgnoreCase(properties.getProperty(key, defaultValue));
}

public String getEnvironment() {
if (environment == null) {
if (!isDevelopment()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import de.l3s.learnweb.user.UserDao;
import de.l3s.mail.Mail;
import de.l3s.mail.MailFactory;
import de.l3s.mail.MailService;
import de.l3s.util.bean.BeanHelper;

@Named
Expand All @@ -48,6 +49,9 @@ public class AdminNotificationBean extends ApplicationBean {
@Inject
private MessageDao messageDao;

@Inject
private MailService mailService;

@PostConstruct
public void init() {
user = getUser();
Expand Down Expand Up @@ -108,8 +112,8 @@ private void sendMail(final ArrayList<String> recipients) {
try {
mail = MailFactory.buildNotificationEmail(title, text, user.getUsername()).build(user.getLocale());
mail.setReplyTo(user.getEmail());
mail.setBccRecipients(recipients);
mail.send();
mail.setRecipientsBcc(recipients);
mailService.send(mail);

addMessage(FacesMessage.SEVERITY_INFO, recipients.size() + " emails send");
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.mail.MessagingException;
import jakarta.validation.constraints.Email;
Expand All @@ -15,6 +16,7 @@
import de.l3s.learnweb.user.User;
import de.l3s.mail.Mail;
import de.l3s.mail.MailFactory;
import de.l3s.mail.MailService;

@Named
@RequestScoped
Expand All @@ -32,6 +34,9 @@ public class ContactBean extends ApplicationBean implements Serializable {
@NotBlank
private String message;

@Inject
private MailService mailService;

@PostConstruct
public void init() {
User user = getUser();
Expand All @@ -45,9 +50,9 @@ public void init() {
public void sendMail() {
try {
Mail mail = MailFactory.buildContactFormEmail(name, email, message).build(getLocale());
mail.setRecipient(config().getSupportEmail());
mail.addRecipient(config().getSupportEmail());
mail.setReplyTo(email);
mail.send();
mailService.send(mail);

clearForm();
} catch (MessagingException e) {
Expand Down
8 changes: 6 additions & 2 deletions src/main/java/de/l3s/learnweb/forum/ForumNotificator.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import de.l3s.learnweb.user.UserDao;
import de.l3s.mail.Mail;
import de.l3s.mail.MailFactory;
import de.l3s.mail.MailService;
import de.l3s.util.HashHelper;

public class ForumNotificator implements Runnable, Serializable {
Expand All @@ -33,6 +34,9 @@ public class ForumNotificator implements Runnable, Serializable {
@Inject
private ForumTopicDao forumTopicDao;

@Inject
private MailService mailService;

@Override
public void run() {
try {
Expand Down Expand Up @@ -68,8 +72,8 @@ private void sendMailWithNewTopics(User user, List<ForumTopic> topics) throws Me
List<ForumTopic> otherTopics = topics.stream().filter(topic -> topic.getUserId() != user.getId()).toList();

Mail mail = MailFactory.buildForumNotificationEmail(user.getUsername(), userTopics, otherTopics, getHash(user)).build(user.getLocale());
mail.setRecipient(user.getEmail());
mail.send();
mail.addRecipient(user.getEmail());
mailService.send(mail);
}

public static String getHash(User user) {
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/de/l3s/learnweb/user/ConfirmRequiredBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ public class ConfirmRequiredBean extends ApplicationBean implements Serializable
@Inject
private UserDao userDao;

@Inject
private EmailConfirmationBean emailConfirmationBean;

@Override
public User getUser() {
if (super.getUser() != null) {
Expand All @@ -47,7 +50,7 @@ public void onSubmitNewEmail() {
userDao.save(user);
}

if (user.sendEmailConfirmation()) {
if (emailConfirmationBean.sendEmailConfirmation(user)) {
addMessage(FacesMessage.SEVERITY_INFO, "email_has_been_sent");
} else {
addMessage(FacesMessage.SEVERITY_FATAL, "We were not able to send a confirmation mail");
Expand Down
53 changes: 53 additions & 0 deletions src/main/java/de/l3s/learnweb/user/EmailConfirmationBean.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package de.l3s.learnweb.user;

import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;

import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import jakarta.mail.MessagingException;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import de.l3s.learnweb.app.Learnweb;
import de.l3s.mail.Mail;
import de.l3s.mail.MailFactory;
import de.l3s.mail.MailService;
import de.l3s.util.StringHelper;

@RequestScoped
public class EmailConfirmationBean implements Serializable {
@Serial
private static final long serialVersionUID = -1427221214029851844L;
private static final Logger log = LogManager.getLogger(EmailConfirmationBean.class);

@Inject
private TokenDao tokenDao;

@Inject
private MailService mailService;

/**
* @return FALSE if an error occurred while sending this message
*/
public boolean sendEmailConfirmation(User user) {
try {
String token = RandomStringUtils.secure().nextAlphanumeric(32);
int tokenId = tokenDao.override(user.getId(), Token.TokenType.EMAIL_CONFIRMATION, token, LocalDateTime.now().plusYears(1));

String confirmEmailUrl = Learnweb.config().getServerUrl() + "/lw/user/confirm_email.jsf?" +
"email=" + StringHelper.urlEncode(user.getEmail()) + "&token=" + tokenId + ":" + token;

Mail mail = MailFactory.buildConfirmEmail(user.getUsername(), confirmEmailUrl).build(user.getLocale());
mail.addRecipient(user.getEmail());
mailService.send(mail);
return true;
} catch (MessagingException e) {
log.error("Can't send confirmation mail to {}", this, e);
}
return false;
}
}
8 changes: 6 additions & 2 deletions src/main/java/de/l3s/learnweb/user/PasswordBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import de.l3s.learnweb.exceptions.HttpException;
import de.l3s.mail.Mail;
import de.l3s.mail.MailFactory;
import de.l3s.mail.MailService;
import de.l3s.util.HashHelper;

@Named
Expand All @@ -32,6 +33,9 @@ public class PasswordBean extends ApplicationBean implements Serializable {
@Inject
private TokenDao tokenDao;

@Inject
private MailService mailService;

public void submit() {
try {
List<User> users = new ArrayList<>();
Expand All @@ -50,8 +54,8 @@ public void submit() {
String link = url + tokenId + ":" + token;

Mail mail = MailFactory.buildPasswordChangeEmail(user.getDisplayName(), user.getEmail(), link).build(user.getLocale());
mail.setRecipient(user.getEmail());
mail.send();
mail.addRecipient(user.getEmail());
mailService.send(mail);
}

addMessage(FacesMessage.SEVERITY_INFO, "email_has_been_sent");
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/de/l3s/learnweb/user/ProfileBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ public class ProfileBean extends ApplicationBean implements Serializable {
@Inject
private GroupDao groupDao;

@Inject
private EmailConfirmationBean emailConfirmationBean;

public void onLoad() {
User loggedInUser = getUser();
BeanAssert.authorized(loggedInUser);
Expand Down Expand Up @@ -142,7 +145,7 @@ public void onSaveProfile() {
if (StringUtils.isNotEmpty(email) && !StringUtils.equals(selectedUser.getEmail(), email)) {
selectedUser.setEmail(email);

if (selectedUser.sendEmailConfirmation()) {
if (emailConfirmationBean.sendEmailConfirmation(selectedUser)) {
addMessage(FacesMessage.SEVERITY_INFO, "email_has_been_sent");
} else {
addMessage(FacesMessage.SEVERITY_FATAL, "We were not able to send a confirmation mail");
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/de/l3s/learnweb/user/RegistrationBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ public class RegistrationBean extends ApplicationBean implements Serializable {
@Inject
private ConfirmRequiredBean confirmRequiredBean;

@Inject
private EmailConfirmationBean emailConfirmationBean;

public String onLoad() {
if (StringUtils.isNotEmpty(wizard)) {
course = courseDao.findByWizard(wizard).orElseThrow(() -> new BadRequestHttpException("register_invalid_wizard_error"));
Expand Down Expand Up @@ -178,7 +181,7 @@ public String register() {
}

if ((mailRequired || StringUtils.isNotEmpty(email)) && !user.isEmailConfirmed()) {
user.sendEmailConfirmation();
emailConfirmationBean.sendEmailConfirmation(user);

if (mailRequired) {
confirmRequiredBean.setLoggedInUser(user);
Expand Down
26 changes: 0 additions & 26 deletions src/main/java/de/l3s/learnweb/user/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,10 @@
import java.util.Objects;
import java.util.Optional;

import jakarta.mail.MessagingException;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
Expand All @@ -34,13 +32,10 @@
import de.l3s.learnweb.resource.Resource;
import de.l3s.learnweb.resource.Tag;
import de.l3s.learnweb.user.Organisation.Option;
import de.l3s.mail.Mail;
import de.l3s.mail.MailFactory;
import de.l3s.util.Deletable;
import de.l3s.util.HasId;
import de.l3s.util.PBKDF2;
import de.l3s.util.ProfileImageHelper;
import de.l3s.util.StringHelper;

public class User implements Comparable<User>, Deletable, HasId, Serializable {
private static final Logger log = LogManager.getLogger(User.class);
Expand Down Expand Up @@ -393,27 +388,6 @@ public int compareTo(User o) {
return getUsername().compareTo(o.getUsername());
}

/**
* @return FALSE if an error occurred while sending this message
*/
public boolean sendEmailConfirmation() {
try {
String token = RandomStringUtils.secure().nextAlphanumeric(32);
int tokenId = Learnweb.dao().getTokenDao().override(id, Token.TokenType.EMAIL_CONFIRMATION, token, LocalDateTime.now().plusYears(1));

String confirmEmailUrl = Learnweb.config().getServerUrl() + "/lw/user/confirm_email.jsf?" +
"email=" + StringHelper.urlEncode(getEmail()) + "&token=" + tokenId + ":" + token;

Mail mail = MailFactory.buildConfirmEmail(getUsername(), confirmEmailUrl).build(getLocale());
mail.setRecipient(getEmail());
mail.send();
return true;
} catch (MessagingException e) {
log.error("Can't send confirmation mail to {}", this, e);
}
return false;
}

public boolean isAdmin() {
return admin;
}
Expand Down
34 changes: 28 additions & 6 deletions src/main/java/de/l3s/learnweb/web/BounceManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,18 @@
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import jakarta.enterprise.context.Dependent;
import jakarta.inject.Inject;
import jakarta.mail.Authenticator;
import jakarta.mail.Flags;
import jakarta.mail.Folder;
import jakarta.mail.Message;
import jakarta.mail.MessagingException;
import jakarta.mail.Session;
import jakarta.mail.Store;
import jakarta.mail.search.ComparisonTerm;
import jakarta.mail.search.ReceivedDateTerm;
Expand All @@ -26,7 +29,8 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import de.l3s.mail.Mail;
import de.l3s.learnweb.app.ConfigProvider;
import de.l3s.mail.PasswordAuthenticator;

/**
* Parses the mailbox every sometime and detects whether bounces are present. Bounced emails are
Expand All @@ -45,8 +49,26 @@ public class BounceManager {
@Inject
private BounceDao bounceDao;

@Inject
private ConfigProvider config;

public Store getStore() throws MessagingException {
return Mail.createSession().getStore("imap");
Properties props = new Properties();
// props.setProperty("mail.debug", "true");
props.setProperty("mail.imap.host", config.getProperty("MAIL_IMAP_HOST", config.getProperty("MAIL_SMTP_HOST")));
props.setProperty("mail.imap.port", config.getProperty("MAIL_IMAP_PORT", "143"));
props.setProperty("mail.imap.socketFactory.port", config.getProperty("MAIL_IMAP_PORT", "143"));
props.setProperty("mail.imap.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.setProperty("mail.imap.auth", "true");
if (config.getPropertyBoolean("MAIL_IMAP_STARTTLS", "true")) {
props.setProperty("mail.imap.starttls.enable", "true");
}

final Authenticator authenticator = new PasswordAuthenticator(
config.getProperty("MAIL_IMAP_USERNAME", config.getProperty("MAIL_SMTP_USERNAME")),
config.getProperty("MAIL_IMAP_PASSWORD", config.getProperty("MAIL_SMTP_PASSWORD"))
);
return Session.getInstance(props, authenticator).getStore("imap");
}

public void parseInbox() throws MessagingException, IOException {
Expand Down Expand Up @@ -102,7 +124,7 @@ private String getText(Message msg) throws MessagingException, IOException {
* @param msg Message to be examined
*/
private boolean parseMessage(Message msg) throws MessagingException, IOException {
//Return path is checked first, since in bounce messages those are usually empty or contain just "<>"
// Return path is checked first, since in bounce messages those are usually empty or contain just "<>"
String[] returnPaths = msg.getHeader("Return-Path");

if (returnPaths != null && returnPaths.length > 0 && returnPaths[0].length() > 3) {
Expand All @@ -111,7 +133,7 @@ private boolean parseMessage(Message msg) throws MessagingException, IOException

log.debug("BOUNCE: {} {}", msg.getSubject(), msg.getReceivedDate());

//Checks the status code
// Checks the status code
String text = getText(msg);
Matcher matcherCode = STATUS_CODE_PATTERN.matcher(text);

Expand All @@ -133,7 +155,7 @@ private boolean parseMessage(Message msg) throws MessagingException, IOException
originalRecipient = matcherRecipient.group(2);
}

//Adds message to database
// Adds message to database
bounceDao.save(originalRecipient, msg.getReceivedDate().toInstant(), code, description);
return true;
}
Expand All @@ -148,7 +170,7 @@ private String getErrorDescription(String errCode) {

String[] codes = errCode.split("\\.", 2);

//Transient or permanent
// Transient or permanent
if ("4".equals(codes[0])) {
description = "Transient Persistent Failure: ";
} else if ("5".equals(codes[0])) {
Expand Down
Loading

0 comments on commit 3ac9faf

Please sign in to comment.