Skip to content

Commit 6794c9f

Browse files
Changes:
- Proper Javax/Jakarta(Angus) mail implementation. - Corrections when reading JNDI context
1 parent 53186dd commit 6794c9f

File tree

4 files changed

+228
-135
lines changed

4 files changed

+228
-135
lines changed
Binary file not shown.

src/main/java/ch/autumo/beetroot/mailing/AbstractMailer.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,13 @@ public abstract class AbstractMailer implements Mailer {
7676

7777

7878
/**
79-
* Load mail configuration.
79+
* Initialize mail configuration; some are store in the returned properties
80+
* and some attributes are initialized.
8081
*
81-
* @return configuration
82+
* @return mail configuration
8283
* @throws Exception if configuration loading fails
8384
*/
84-
protected Properties getProperties() throws Exception {
85+
protected Properties initialize() throws Exception {
8586
final Properties props = System.getProperties();
8687
mailformats = BeetRootConfigurationManager.getInstance().getSepValues("mail_formats");
8788
if (mailformats.length < 1)
@@ -124,6 +125,22 @@ protected Properties getProperties() throws Exception {
124125
return props;
125126
}
126127

128+
/**
129+
* Load language translated templates with variables replaced.
130+
*
131+
* @param templateName template name
132+
* @param session HTTPS session
133+
* @param variables variables
134+
* @param format mail format
135+
* @return replaced template
136+
* @throws Exception
137+
*/
138+
protected String loadTemplateWithVariables(String templateName, BeetRootHTTPSession session, Map<String, String> variables, String format) throws Exception {
139+
String template = this.loadTemplate(templateName, session, format);
140+
template = this.replaceAllVariables(template, variables, format);
141+
return this.replaceAllLanguageVariables(template, session, format);
142+
}
143+
127144
/**
128145
* Load mail template.
129146
*
@@ -254,15 +271,13 @@ protected String replaceAllLanguageVariables(String template, BeetRootHTTPSessio
254271
* @return replaced templates
255272
*/
256273
protected String replaceAllVariables(String template, Map<String, String> variables, String extension) {
257-
258274
String baseUrl = BeetRootConfigurationManager.getInstance().getString(Constants.KEY_WS_URL);
259275
String baseUrlPort = BeetRootConfigurationManager.getInstance().getString(Constants.KEY_WS_PORT);
260276
String base = null;
261277
if (baseUrlPort != null)
262278
base = baseUrl + ":" + baseUrlPort;
263279
else
264280
base = baseUrl ;
265-
266281
String servletName = null;
267282
final ServletContext context = BeetRootConfigurationManager.getInstance().getServletContext();
268283
if (context != null) {
@@ -271,12 +286,10 @@ protected String replaceAllVariables(String template, Map<String, String> variab
271286
base += ("/" + servletName);
272287
}
273288
}
274-
275289
// we have no URLs pointing to images in TXT, only HTML
276290
if (extension.equalsIgnoreCase("html")&& template.contains("{$ws_url}")) {
277291
template = template.replaceAll("\\{\\$ws_url\\}", base);
278292
}
279-
280293
final Set<String> names = variables.keySet();
281294
for (Iterator<String> iterator = names.iterator(); iterator.hasNext();) {
282295
final String name = iterator.next();

src/main/java/ch/autumo/beetroot/mailing/JakartaMailer.java

Lines changed: 102 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@
2020
import java.util.Arrays;
2121
import java.util.Collections;
2222
import java.util.Map;
23-
import java.util.Properties;
2423

2524
import javax.naming.InitialContext;
25+
import javax.naming.NamingException;
2626

2727
import org.slf4j.Logger;
2828
import org.slf4j.LoggerFactory;
@@ -36,7 +36,6 @@
3636
import jakarta.mail.PasswordAuthentication;
3737
import jakarta.mail.Session;
3838
import jakarta.mail.Transport;
39-
import jakarta.mail.URLName;
4039
import jakarta.mail.internet.InternetAddress;
4140
import jakarta.mail.internet.MimeBodyPart;
4241
import jakarta.mail.internet.MimeMessage;
@@ -50,76 +49,117 @@ public class JakartaMailer extends AbstractMailer {
5049

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

53-
@Override
54-
public void mail(String to[], String subject, Map<String, String> variables, String templateName, BeetRootHTTPSession session) throws Exception {
55-
final Properties props = super.getProperties();
56-
Session mailSession = null;
57-
String msname = BeetRootDatabaseManager.getInstance().getProperty("mail.session.name");
58-
if (msname == null || msname.length() == 0) {
59-
msname = BeetRootConfigurationManager.getInstance().getString("mail_session_name");
60-
if (msname == null || msname.length() == 0) {
61-
// Customized mail session
62-
if (auth) {
63-
mailSession = Session.getInstance(props, new Authenticator() {
64-
protected PasswordAuthentication getPasswordAuthentication() {
65-
return new PasswordAuthentication(user, password);
66-
}
67-
});
68-
} else {
69-
mailSession = Session.getDefaultInstance(props);
70-
}
71-
} else {
72-
// JNDI mail session
73-
final InitialContext ic = new InitialContext();
74-
mailSession = (Session) ic.lookup(msname);
75-
if (auth) {
76-
mailSession.setPasswordAuthentication(
77-
new URLName("smtp", host, -1, null, user, null),
78-
new PasswordAuthentication(user, password)
79-
);
80-
}
81-
LOG.info("External Mail-session '{}' (from {}) has been configured.", msname, BeetRootConfigurationManager.getInstance().getConfigFileNme());
82-
}
83-
} else {
84-
final InitialContext ic = new InitialContext();
85-
mailSession = (Session) ic.lookup(msname);
86-
if (auth) {
87-
mailSession.setPasswordAuthentication(
88-
new URLName("smtp", host, -1, null, user, null),
89-
new PasswordAuthentication(user, password)
90-
);
91-
}
92-
LOG.info("External Mail-session '{}' (from database) has been configured.", msname);
93-
}
52+
/**
53+
* Create a custom mail session with authentication or none.
54+
*
55+
* @param auth authentication?
56+
* @param user user or null (no authentication)
57+
* @param password password or null (no authentication)
58+
* @return mail session
59+
* @throws Exception
60+
*/
61+
private Session createCustomMailSession(boolean auth, String user, String password) throws Exception {
62+
Authenticator authenticator = null;
63+
if (auth) {
64+
authenticator = new Authenticator() {
65+
protected PasswordAuthentication getPasswordAuthentication() {
66+
return new PasswordAuthentication(user, password);
67+
}
68+
};
69+
}
70+
Session mailSession = null;
71+
if (auth) {
72+
mailSession = Session.getInstance(super.initialize(), authenticator);
73+
LOG.info("Custom Mail-session with authentication has been created.");
74+
} else {
75+
mailSession = Session.getDefaultInstance(super.initialize());
76+
LOG.info("Custom Mail-session without authentication has been created.");
77+
}
78+
return mailSession;
79+
}
9480

95-
final MimeMessage message = new MimeMessage(mailSession);
81+
/**
82+
* Lookup JNDI context.
83+
*
84+
* @param jndiContextName JNDI context name (or mail session name)
85+
* @return mail session
86+
* @throws Exception
87+
*/
88+
private Session lookupJndiMailSession(String jndiContextName) throws Exception {
89+
// We still load properties from default configuration, because we still need some value, e.g., 'from'
90+
super.initialize();
91+
final InitialContext ic = new InitialContext();
92+
return (Session) ic.lookup(jndiContextName);
93+
}
94+
95+
/**
96+
* Send MIME message.
97+
*
98+
* @param message MIME message
99+
* @param to email receivers
100+
* @param subject email subject
101+
* @param variables variables to parse in templates
102+
* @param templateName template name
103+
* @param session HTTP session or null if not called within a servlet context (default language used)
104+
* @throws Exception exception
105+
*/
106+
private void send(MimeMessage message, String to[], String subject, Map<String, String> variables, String templateName, BeetRootHTTPSession session) throws Exception {
96107
message.setFrom(new InternetAddress(from));
97-
// process receivers
98-
for (int i = 0; i < to.length; i++) {
99-
message.addRecipient(Message.RecipientType.TO, new InternetAddress(to[i]));
100-
LOG.info("Sending mail to '{}'.", to[i]);
101-
}
108+
// Process recipients
109+
for (String recipient : to) {
110+
message.addRecipient(Message.RecipientType.TO, new InternetAddress(recipient));
111+
LOG.info("Sending mail to '{}'.", recipient);
112+
}
102113
message.setSubject(subject, "UTF-8");
103-
104114
final Multipart multipart = new MimeMultipart();
105115
// TXT must be first always !
106116
Arrays.sort(mailformats, Collections.reverseOrder());
107-
MimeBodyPart messageBodyPart = null;
108-
for (int i = 0; i < mailformats.length; i++) {
109-
String template = super.loadTemplate(templateName, session, mailformats[i]);
110-
template = super.replaceAllVariables(template, variables, mailformats[i]);
111-
template = super.replaceAllLanguageVariables(template, session, mailformats[i]);
112-
messageBodyPart = new MimeBodyPart();
113-
if (mailformats[i].equalsIgnoreCase("html"))
114-
messageBodyPart.setContent(template, "text/html; charset=UTF-8");
115-
else
116-
messageBodyPart.setText(template, "UTF-8");
117-
multipart.addBodyPart(messageBodyPart);
118-
}
117+
for (String format : mailformats) {
118+
final String template = loadTemplateWithVariables(templateName, session, variables, format);
119+
final MimeBodyPart messageBodyPart = new MimeBodyPart();
120+
if (format.equalsIgnoreCase("html")) {
121+
messageBodyPart.setContent(template, "text/html; charset=UTF-8");
122+
} else {
123+
messageBodyPart.setText(template, "UTF-8");
124+
}
125+
multipart.addBodyPart(messageBodyPart);
126+
}
119127
message.setContent(multipart);
120128
message.saveChanges();
121129
// Send message
122130
Transport.send(message);
123131
}
132+
133+
@Override
134+
public void mail(String to[], String subject, Map<String, String> variables, String templateName, BeetRootHTTPSession session) throws Exception {
135+
Session mailSession = null;
136+
try {
137+
String jndiName = BeetRootDatabaseManager.getInstance().getProperty("mail.session.name");
138+
if (jndiName == null || jndiName.isEmpty()) {
139+
jndiName = BeetRootConfigurationManager.getInstance().getString("mail_session_name");
140+
if (jndiName == null || jndiName.isEmpty()) {
141+
// No JNDI session name provided, create a custom session programmatically
142+
mailSession = this.createCustomMailSession(auth, user, password);
143+
} else {
144+
// JNDI mail session
145+
mailSession = this.lookupJndiMailSession(jndiName);
146+
LOG.info("External Mail-session (JNDI) '{}' has been configured from configuration file '{}'.", jndiName, BeetRootConfigurationManager.getInstance().getConfigFileNme());
147+
}
148+
} else {
149+
// Retrieve session name from database and create JNDI context
150+
mailSession = this.lookupJndiMailSession(jndiName);
151+
LOG.info("External Mail-session (JNDI) '{}' has been configured from database.", jndiName);
152+
}
153+
154+
this.send(new MimeMessage(mailSession), to, subject, variables, templateName, session);
155+
156+
} catch (NamingException e) {
157+
LOG.error("Error looking up mail session via JNDI.", e);
158+
throw new RuntimeException("JNDI lookup failed for mail session", e);
159+
} catch (Exception e) {
160+
LOG.error("Error configuring mail session.", e);
161+
throw new RuntimeException("Error configuring mail session", e);
162+
}
163+
}
124164

125165
}

0 commit comments

Comments
 (0)