Skip to content

Commit

Permalink
Allows multiple reply-to addresses.
Browse files Browse the repository at this point in the history
This change to not break the API. The only difference is if you pass multiple reply-to address, the getReplyTo will get a comma-separated list (as indicated by the RFC).

Fix #17308
  • Loading branch information
cescoffier committed May 19, 2021
1 parent 5bad4ab commit b28f88c
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class Mail {
private List<String> bcc = new ArrayList<>();
private List<String> cc = new ArrayList<>();
private String from;
private String replyTo;
private List<String> replyTo = new ArrayList<>();
private String bounceAddress;
private String subject;
private String text;
Expand Down Expand Up @@ -163,20 +163,52 @@ public Mail setFrom(String from) {
}

/**
* @return the reply-to address.
* @return the reply-to address. In the case of multiple addresses, the comma-separated list is returned, following
* the https://datatracker.ietf.org/doc/html/rfc5322#section-3.6.2 recommendation. If no reply-to address has been
* set, it returns {@code null}.
*/
public String getReplyTo() {
return replyTo;
if (replyTo == null || replyTo.isEmpty()) {
return null;
}
return String.join(",", replyTo);
}

/**
* Adds a reply-to address.
*
* @param replyTo the address to use as reply-to. Must be a valid email address.
* @return the current {@link Mail}
* @see #setReplyTo(String)
*/
public Mail addReplyTo(String replyTo) {
this.replyTo.add(replyTo);
return this;
}

/**
* Sets the reply-to address.
*
* @param replyTo the address to use as reply-to. Must be a valid email address.
* @return the current {@link Mail}
* @see #setReplyTo(String[])
*/
public Mail setReplyTo(String replyTo) {
this.replyTo = replyTo;
this.replyTo.clear();
this.replyTo.add(replyTo);
return this;
}

/**
* Sets the reply-to addresses.
*
* @param replyTo the addresses to use as reply-to. Must contain valid email addresses, must contain at least
* one address.
* @return the current {@link Mail}
*/
public Mail setReplyTo(String... replyTo) {
this.replyTo.clear();
Collections.addAll(this.replyTo, replyTo);
return this;
}

Expand Down Expand Up @@ -436,7 +468,8 @@ public Mail addAttachment(String name, byte[] data, String contentType, String d
* @param disposition the disposition of the attachment
* @return the current {@link Mail}
*/
public Mail addAttachment(String name, Publisher<Byte> data, String contentType, String description, String disposition) {
public Mail addAttachment(String name, Publisher<Byte> data, String contentType, String description,
String disposition) {
this.attachments.add(new Attachment(name, data, contentType, description, disposition));
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ interface MailTemplateInstance {

MailTemplateInstance replyTo(String replyTo);

MailTemplateInstance replyTo(String... replyTo);

MailTemplateInstance bounceAddress(String bounceAddress);

MailTemplateInstance addInlineAttachment(String name, File file, String contentType, String contentId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ public MailTemplateInstance replyTo(String replyTo) {
return this;
}

@Override
public MailTemplateInstance replyTo(String... replyTo) {
this.mail.setReplyTo(replyTo);
return this;
}

@Override
public MailTemplateInstance bounceAddress(String bounceAddress) {
this.mail.setBounceAddress(bounceAddress);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ private Uni<MailMessage> toMailMessage(Mail mail) {
message.setHtml(mail.getHtml());
message.setHeaders(toMultimap(mail.getHeaders()));
if (mail.getReplyTo() != null) {
// getReplyTo produces the comma-separated list.
message.addHeader("Reply-To", mail.getReplyTo());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,32 @@ void testHeaders() {
assertThat(mail.getHeaders()).isEmpty();
}

@Test
void testMultipleReplyTo() {
Mail mail = new Mail().addTo(TO_ADDRESS).setSubject("test").setText(BEGINNING)
.setFrom("from@quarkus.io")
.setReplyTo("reply-to@quarkus.io", "another@quarkus.io")
.setBounceAddress("bounce@quarkus.io");
assertThat(mail.getTo()).containsExactly(TO_ADDRESS);
assertThat(mail.getSubject()).isEqualTo("test");
assertThat(mail.getText()).isEqualTo(BEGINNING);
assertThat(mail.getHtml()).isNull();
assertThat(mail.getFrom()).isEqualTo("from@quarkus.io");
assertThat(mail.getReplyTo()).isEqualTo("reply-to@quarkus.io,another@quarkus.io");
assertThat(mail.getBounceAddress()).isEqualTo("bounce@quarkus.io");

mail = new Mail().addTo(TO_ADDRESS).setSubject("test").setText(BEGINNING)
.setFrom("from@quarkus.io")
.addReplyTo("another@quarkus.io")
.addReplyTo("reply-to@quarkus.io")
.setBounceAddress("bounce@quarkus.io");
assertThat(mail.getTo()).containsExactly(TO_ADDRESS);
assertThat(mail.getSubject()).isEqualTo("test");
assertThat(mail.getText()).isEqualTo(BEGINNING);
assertThat(mail.getHtml()).isNull();
assertThat(mail.getFrom()).isEqualTo("from@quarkus.io");
assertThat(mail.getReplyTo()).isEqualTo("another@quarkus.io,reply-to@quarkus.io");
assertThat(mail.getBounceAddress()).isEqualTo("bounce@quarkus.io");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ public Byte next() {

@Test
void testInlineAttachment() throws MessagingException, IOException {
String cid = UUID.randomUUID().toString() + "@acme";
String cid = UUID.randomUUID() + "@acme";
mailer.send(Mail.withHtml(TO, "Test", "testInlineAttachment")
.addInlineAttachment("inline.txt", "my inlined text".getBytes(StandardCharsets.UTF_8), TEXT_CONTENT_TYPE, cid))
.await().indefinitely();
Expand Down Expand Up @@ -210,6 +210,19 @@ void testReplyToHeaderIsSet() throws MessagingException {
assertThat(msg.getReplyTo()).containsExactly(InternetAddress.parse("reply-to@quarkus.io"));
}

@Test
void testMultipleReplyToHeaderIsSet() throws MessagingException {
mailer.send(Mail.withText(TO, "Test", "testHeaders")
.setReplyTo("reply-to@quarkus.io", "another@quarkus.io"))
.await().indefinitely();
assertThat(wiser.getMessages()).hasSize(1);
WiserMessage actual = wiser.getMessages().get(0);
MimeMessage msg = actual.getMimeMessage();
assertThat(msg.getHeader("Reply-To")).containsExactly("reply-to@quarkus.io,another@quarkus.io");
assertThat(msg.getReplyTo()).hasSize(2).contains(InternetAddress.parse("reply-to@quarkus.io"))
.contains(InternetAddress.parse("another@quarkus.io"));
}

private String getContent(WiserMessage msg) {
try {
Object content = msg.getMimeMessage().getContent();
Expand Down Expand Up @@ -279,24 +292,4 @@ private String getTextFromMimeMultipart(
return result.toString();
}

private List<String> getContentTypesFromMimeMultipart(
MimeMultipart mimeMultipart) throws MessagingException, IOException {
List<String> types = new ArrayList<>();
int count = mimeMultipart.getCount();
for (int i = 0; i < count; i++) {
BodyPart bodyPart = mimeMultipart.getBodyPart(i);
if (bodyPart.getContent() instanceof MimeMultipart) {
types.addAll(getContentTypesFromMimeMultipart((MimeMultipart) bodyPart.getContent()));
} else {
types.add(bodyPart.getContentType());
}
}
return types;
}

private List<String> getContentTypesFromMimeMultipart(
String content) throws MessagingException, IOException {
return Collections.singletonList(content);
}

}

0 comments on commit b28f88c

Please sign in to comment.