Skip to content

Commit

Permalink
Changes:
Browse files Browse the repository at this point in the history
- Proper Javax/Jakarta(Angus) mail implementation.
- Corrections when reading JNDI context
  • Loading branch information
autumoswitzerland committed Nov 7, 2024
1 parent 53186dd commit 6794c9f
Show file tree
Hide file tree
Showing 4 changed files with 228 additions and 135 deletions.
Binary file not shown.
27 changes: 20 additions & 7 deletions src/main/java/ch/autumo/beetroot/mailing/AbstractMailer.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,13 @@ public abstract class AbstractMailer implements Mailer {


/**
* Load mail configuration.
* Initialize mail configuration; some are store in the returned properties
* and some attributes are initialized.
*
* @return configuration
* @return mail configuration
* @throws Exception if configuration loading fails
*/
protected Properties getProperties() throws Exception {
protected Properties initialize() throws Exception {
final Properties props = System.getProperties();
mailformats = BeetRootConfigurationManager.getInstance().getSepValues("mail_formats");
if (mailformats.length < 1)
Expand Down Expand Up @@ -124,6 +125,22 @@ protected Properties getProperties() throws Exception {
return props;
}

/**
* Load language translated templates with variables replaced.
*
* @param templateName template name
* @param session HTTPS session
* @param variables variables
* @param format mail format
* @return replaced template
* @throws Exception
*/
protected String loadTemplateWithVariables(String templateName, BeetRootHTTPSession session, Map<String, String> variables, String format) throws Exception {
String template = this.loadTemplate(templateName, session, format);
template = this.replaceAllVariables(template, variables, format);
return this.replaceAllLanguageVariables(template, session, format);
}

/**
* Load mail template.
*
Expand Down Expand Up @@ -254,15 +271,13 @@ protected String replaceAllLanguageVariables(String template, BeetRootHTTPSessio
* @return replaced templates
*/
protected String replaceAllVariables(String template, Map<String, String> variables, String extension) {

String baseUrl = BeetRootConfigurationManager.getInstance().getString(Constants.KEY_WS_URL);
String baseUrlPort = BeetRootConfigurationManager.getInstance().getString(Constants.KEY_WS_PORT);
String base = null;
if (baseUrlPort != null)
base = baseUrl + ":" + baseUrlPort;
else
base = baseUrl ;

String servletName = null;
final ServletContext context = BeetRootConfigurationManager.getInstance().getServletContext();
if (context != null) {
Expand All @@ -271,12 +286,10 @@ protected String replaceAllVariables(String template, Map<String, String> variab
base += ("/" + servletName);
}
}

// we have no URLs pointing to images in TXT, only HTML
if (extension.equalsIgnoreCase("html")&& template.contains("{$ws_url}")) {
template = template.replaceAll("\\{\\$ws_url\\}", base);
}

final Set<String> names = variables.keySet();
for (Iterator<String> iterator = names.iterator(); iterator.hasNext();) {
final String name = iterator.next();
Expand Down
164 changes: 102 additions & 62 deletions src/main/java/ch/autumo/beetroot/mailing/JakartaMailer.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.Properties;

import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -36,7 +36,6 @@
import jakarta.mail.PasswordAuthentication;
import jakarta.mail.Session;
import jakarta.mail.Transport;
import jakarta.mail.URLName;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeBodyPart;
import jakarta.mail.internet.MimeMessage;
Expand All @@ -50,76 +49,117 @@ public class JakartaMailer extends AbstractMailer {

private static final Logger LOG = LoggerFactory.getLogger(JakartaMailer.class.getName());

@Override
public void mail(String to[], String subject, Map<String, String> variables, String templateName, BeetRootHTTPSession session) throws Exception {
final Properties props = super.getProperties();
Session mailSession = null;
String msname = BeetRootDatabaseManager.getInstance().getProperty("mail.session.name");
if (msname == null || msname.length() == 0) {
msname = BeetRootConfigurationManager.getInstance().getString("mail_session_name");
if (msname == null || msname.length() == 0) {
// Customized mail session
if (auth) {
mailSession = Session.getInstance(props, new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(user, password);
}
});
} else {
mailSession = Session.getDefaultInstance(props);
}
} else {
// JNDI mail session
final InitialContext ic = new InitialContext();
mailSession = (Session) ic.lookup(msname);
if (auth) {
mailSession.setPasswordAuthentication(
new URLName("smtp", host, -1, null, user, null),
new PasswordAuthentication(user, password)
);
}
LOG.info("External Mail-session '{}' (from {}) has been configured.", msname, BeetRootConfigurationManager.getInstance().getConfigFileNme());
}
} else {
final InitialContext ic = new InitialContext();
mailSession = (Session) ic.lookup(msname);
if (auth) {
mailSession.setPasswordAuthentication(
new URLName("smtp", host, -1, null, user, null),
new PasswordAuthentication(user, password)
);
}
LOG.info("External Mail-session '{}' (from database) has been configured.", msname);
}
/**
* Create a custom mail session with authentication or none.
*
* @param auth authentication?
* @param user user or null (no authentication)
* @param password password or null (no authentication)
* @return mail session
* @throws Exception
*/
private Session createCustomMailSession(boolean auth, String user, String password) throws Exception {
Authenticator authenticator = null;
if (auth) {
authenticator = new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(user, password);
}
};
}
Session mailSession = null;
if (auth) {
mailSession = Session.getInstance(super.initialize(), authenticator);
LOG.info("Custom Mail-session with authentication has been created.");
} else {
mailSession = Session.getDefaultInstance(super.initialize());
LOG.info("Custom Mail-session without authentication has been created.");
}
return mailSession;
}

final MimeMessage message = new MimeMessage(mailSession);
/**
* Lookup JNDI context.
*
* @param jndiContextName JNDI context name (or mail session name)
* @return mail session
* @throws Exception
*/
private Session lookupJndiMailSession(String jndiContextName) throws Exception {
// We still load properties from default configuration, because we still need some value, e.g., 'from'
super.initialize();
final InitialContext ic = new InitialContext();
return (Session) ic.lookup(jndiContextName);
}

/**
* Send MIME message.
*
* @param message MIME message
* @param to email receivers
* @param subject email subject
* @param variables variables to parse in templates
* @param templateName template name
* @param session HTTP session or null if not called within a servlet context (default language used)
* @throws Exception exception
*/
private void send(MimeMessage message, String to[], String subject, Map<String, String> variables, String templateName, BeetRootHTTPSession session) throws Exception {
message.setFrom(new InternetAddress(from));
// process receivers
for (int i = 0; i < to.length; i++) {
message.addRecipient(Message.RecipientType.TO, new InternetAddress(to[i]));
LOG.info("Sending mail to '{}'.", to[i]);
}
// Process recipients
for (String recipient : to) {
message.addRecipient(Message.RecipientType.TO, new InternetAddress(recipient));
LOG.info("Sending mail to '{}'.", recipient);
}
message.setSubject(subject, "UTF-8");

final Multipart multipart = new MimeMultipart();
// TXT must be first always !
Arrays.sort(mailformats, Collections.reverseOrder());
MimeBodyPart messageBodyPart = null;
for (int i = 0; i < mailformats.length; i++) {
String template = super.loadTemplate(templateName, session, mailformats[i]);
template = super.replaceAllVariables(template, variables, mailformats[i]);
template = super.replaceAllLanguageVariables(template, session, mailformats[i]);
messageBodyPart = new MimeBodyPart();
if (mailformats[i].equalsIgnoreCase("html"))
messageBodyPart.setContent(template, "text/html; charset=UTF-8");
else
messageBodyPart.setText(template, "UTF-8");
multipart.addBodyPart(messageBodyPart);
}
for (String format : mailformats) {
final String template = loadTemplateWithVariables(templateName, session, variables, format);
final MimeBodyPart messageBodyPart = new MimeBodyPart();
if (format.equalsIgnoreCase("html")) {
messageBodyPart.setContent(template, "text/html; charset=UTF-8");
} else {
messageBodyPart.setText(template, "UTF-8");
}
multipart.addBodyPart(messageBodyPart);
}
message.setContent(multipart);
message.saveChanges();
// Send message
Transport.send(message);
}

@Override
public void mail(String to[], String subject, Map<String, String> variables, String templateName, BeetRootHTTPSession session) throws Exception {
Session mailSession = null;
try {
String jndiName = BeetRootDatabaseManager.getInstance().getProperty("mail.session.name");
if (jndiName == null || jndiName.isEmpty()) {
jndiName = BeetRootConfigurationManager.getInstance().getString("mail_session_name");
if (jndiName == null || jndiName.isEmpty()) {
// No JNDI session name provided, create a custom session programmatically
mailSession = this.createCustomMailSession(auth, user, password);
} else {
// JNDI mail session
mailSession = this.lookupJndiMailSession(jndiName);
LOG.info("External Mail-session (JNDI) '{}' has been configured from configuration file '{}'.", jndiName, BeetRootConfigurationManager.getInstance().getConfigFileNme());
}
} else {
// Retrieve session name from database and create JNDI context
mailSession = this.lookupJndiMailSession(jndiName);
LOG.info("External Mail-session (JNDI) '{}' has been configured from database.", jndiName);
}

this.send(new MimeMessage(mailSession), to, subject, variables, templateName, session);

} catch (NamingException e) {
LOG.error("Error looking up mail session via JNDI.", e);
throw new RuntimeException("JNDI lookup failed for mail session", e);
} catch (Exception e) {
LOG.error("Error configuring mail session.", e);
throw new RuntimeException("Error configuring mail session", e);
}
}

}
Loading

0 comments on commit 6794c9f

Please sign in to comment.