Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 61 additions & 59 deletions framework/src/play/mvc/Mailer.java
Original file line number Diff line number Diff line change
Expand Up @@ -482,12 +482,6 @@ public static Future<Boolean> send(Object... args) {
}
}

// Recipients
List<String> recipientList = (List<String>) infos.get().get("recipients");
// From
String from = (String) infos.get().get("from");
String replyTo = (String) infos.get().get("replyTo");

Email email;
if (infos.get().get("attachments") == null && infos.get().get("datasources") == null
&& infos.get().get("inlineEmbeds") == null) {
Expand Down Expand Up @@ -540,76 +534,84 @@ public static Future<Boolean> send(Object... args) {
}
}
}
email.setCharset("utf-8");
setAddresses(email);
if (!StringUtils.isEmpty(charset)) {
email.setCharset(charset);
}

if (from != null) {
try {
InternetAddress iAddress = new InternetAddress(from);
email.setFrom(iAddress.getAddress(), iAddress.getPersonal());
} catch (Exception e) {
email.setFrom(from);
}
email.setSubject(subject);
email.updateContentType(contentType);

if (headers != null) {
for (String key : headers.keySet()) {
email.addHeader(key, headers.get(key));
}
}

if (replyTo != null) {
try {
InternetAddress iAddress = new InternetAddress(replyTo);
email.addReplyTo(iAddress.getAddress(), iAddress.getPersonal());
} catch (Exception e) {
email.addReplyTo(replyTo);
}
return Mail.send(email);
} catch (EmailException ex) {
throw new MailException("Cannot send email", ex);
}
}

static void setAddresses(Email email) throws EmailException {
email.setCharset("utf-8");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why forced the charset to utf-8 here ? in the upper code you only set the charset if define ?
Do you mean that a default value is need ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xael-fry
This encoding fix was originally written, in line 543.
This line appears to have been moved to the setAddresses () method as it relates to setting addresses.

Copy link

@irxground irxground Oct 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is to keep the behavior of the original code.

In the original code, the encoding is changed to UTF-8 before setting the from, reply-to, to, cc, and bcc addresses, and is changed to charset before setting the subject.

(I'm a co-worker of @ken-takagi and @yuba )

String from = (String) infos.get().get("from");
if (from != null) {
try {
InternetAddress iAddress = new InternetAddress(from);
email.setFrom(iAddress.getAddress(), iAddress.getPersonal());
} catch (Exception e) {
email.setFrom(from);
}
}

if (recipientList != null) {
for (String recipient : recipientList) {
try {
InternetAddress iAddress = new InternetAddress(recipient);
email.addTo(iAddress.getAddress(), iAddress.getPersonal());
} catch (Exception e) {
email.addTo(recipient);
}
}
} else {
throw new MailException("You must specify at least one recipient.");
String replyTo = (String) infos.get().get("replyTo");
if (replyTo != null) {
try {
InternetAddress iAddress = new InternetAddress(replyTo);
email.addReplyTo(iAddress.getAddress(), iAddress.getPersonal());
} catch (Exception e) {
email.addReplyTo(replyTo);
}
}

List<String> ccsList = (List<String>) infos.get().get("ccs");
if (ccsList != null) {
for (String cc : ccsList) {
email.addCc(cc);
List<String> recipientList = (List<String>) infos.get().get("recipients");
if (recipientList != null) {
for (String recipient : recipientList) {
try {
InternetAddress iAddress = new InternetAddress(recipient);
email.addTo(iAddress.getAddress(), iAddress.getPersonal());
} catch (Exception e) {
email.addTo(recipient);
}
}
} else {
throw new MailException("You must specify at least one recipient.");
}

List<String> bccsList = (List<String>) infos.get().get("bccs");
if (bccsList != null) {

for (String bcc : bccsList) {
try {
InternetAddress iAddress = new InternetAddress(bcc);
email.addBcc(iAddress.getAddress(), iAddress.getPersonal());
} catch (Exception e) {
email.addBcc(bcc);
}
List<String> ccsList = (List<String>) infos.get().get("ccs");
if (ccsList != null) {
for (final String cc : ccsList) {
try {
final InternetAddress iAddress = new InternetAddress(cc);
email.addCc(iAddress.getAddress(), iAddress.getPersonal());
} catch (final Exception e) {
email.addCc(cc);
}
}
if (!StringUtils.isEmpty(charset)) {
email.setCharset(charset);
}

email.setSubject(subject);
email.updateContentType(contentType);
}

if (headers != null) {
for (String key : headers.keySet()) {
email.addHeader(key, headers.get(key));
List<String> bccsList = (List<String>) infos.get().get("bccs");
if (bccsList != null) {
for (String bcc : bccsList) {
try {
InternetAddress iAddress = new InternetAddress(bcc);
email.addBcc(iAddress.getAddress(), iAddress.getPersonal());
} catch (Exception e) {
email.addBcc(bcc);
}
}

return Mail.send(email);
} catch (EmailException ex) {
throw new MailException("Cannot send email", ex);
}
}

Expand Down
98 changes: 98 additions & 0 deletions framework/test-src/play/mvc/MailerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package play.mvc;

import org.apache.commons.mail.Email;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.SimpleEmail;
import org.junit.Test;

import java.util.HashMap;

import static org.junit.Assert.assertEquals;

public class MailerTest {
static class MailInitializer extends Mailer {
/**
* The method annotated with @Before seems to be executed in a separate thread from the test method.
* This method initializes thread-local variables and must be called at the beginning of the test method.
*/
public static void init() {
infos.set(new HashMap<>());
}
public static void clear() {
infos.remove();
}
}

private static String exampleAddress = "user@example.com";
private static String multibyteCharAddress = "Eva Nováková <eva@example.com>";
private static String encodedAddress = "=?UTF-8?Q?Eva_Nov=C3=A1kov=C3=A1?= <eva@example.com>";

@Test
public void mailFromSupportsMultibyteCharAddress() throws EmailException {
MailInitializer.init();
try {
Email email = new SimpleEmail();
Mailer.addRecipient(exampleAddress);
Mailer.setFrom(multibyteCharAddress);
Mailer.setAddresses(email);
assertEquals(encodedAddress, email.getFromAddress().toString());
} finally {
MailInitializer.clear();
}
}

@Test
public void mailReplyToSupportsMultibyteCharAddress() throws EmailException {
MailInitializer.init();
try {
Email email = new SimpleEmail();
Mailer.addRecipient(exampleAddress);
Mailer.setReplyTo(multibyteCharAddress);
Mailer.setAddresses(email);
assertEquals(encodedAddress, email.getReplyToAddresses().get(0).toString());
} finally {
MailInitializer.clear();
}
}

@Test
public void mailToSupportsMultibyteCharAddress() throws EmailException {
MailInitializer.init();
try {
Email email = new SimpleEmail();
Mailer.addRecipient(multibyteCharAddress);
Mailer.setAddresses(email);
assertEquals(encodedAddress, email.getToAddresses().get(0).toString());
} finally {
MailInitializer.clear();
}
}

@Test
public void mailCcSupportsMultibyteCharAddress() throws EmailException {
MailInitializer.init();
try {
Email email = new SimpleEmail();
Mailer.addRecipient(exampleAddress);
Mailer.addCc(multibyteCharAddress);
Mailer.setAddresses(email);
assertEquals(encodedAddress, email.getCcAddresses().get(0).toString());
} finally {
MailInitializer.clear();
}
}

@Test
public void mailBccSupportsMultibyteCharAddress() throws EmailException {
MailInitializer.init();
try {
Email email = new SimpleEmail();
Mailer.addRecipient(exampleAddress);
Mailer.addBcc(multibyteCharAddress);
Mailer.setAddresses(email);
assertEquals(encodedAddress, email.getBccAddresses().get(0).toString());
} finally {
MailInitializer.clear();
}
}
}