keycloak-uncached
Changes
forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_de.properties 6(+6 -0)
forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_en.properties 10(+8 -2)
forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_pt_BR.properties 6(+6 -0)
forms/email-freemarker/src/main/java/org/keycloak/email/freemarker/FreeMarkerEmailProvider.java 60(+48 -12)
testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionEmailVerificationTest.java 41(+29 -12)
Details
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/html/email-verification.ftl b/forms/common-themes/src/main/resources/theme/keycloak/email/html/email-verification.ftl
new file mode 100644
index 0000000..eb7682a
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/html/email-verification.ftl
@@ -0,0 +1,5 @@
+<html>
+<body>
+${msg("emailVerificationBodyHtml",link, linkExpiration, realmName)}
+</body>
+</html>
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/html/event-login_error.ftl b/forms/common-themes/src/main/resources/theme/keycloak/email/html/event-login_error.ftl
new file mode 100644
index 0000000..d314103
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/html/event-login_error.ftl
@@ -0,0 +1,5 @@
+<html>
+<body>
+${msg("eventLoginErrorBodyHtml",event.date,event.ipAddress)}
+</body>
+</html>
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/html/event-remove_totp.ftl b/forms/common-themes/src/main/resources/theme/keycloak/email/html/event-remove_totp.ftl
new file mode 100644
index 0000000..91699ea
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/html/event-remove_totp.ftl
@@ -0,0 +1,5 @@
+<html>
+<body>
+${msg("eventRemoveTotpBodyHtml",event.date, event.ipAddress)}
+</body>
+</html>
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/html/event-update_password.ftl b/forms/common-themes/src/main/resources/theme/keycloak/email/html/event-update_password.ftl
new file mode 100644
index 0000000..8a6da60
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/html/event-update_password.ftl
@@ -0,0 +1,5 @@
+<html>
+<body>
+${msg("eventUpdatePasswordBodyHtml",event.date, event.ipAddress)}
+</body>
+</html>
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/html/event-update_totp.ftl b/forms/common-themes/src/main/resources/theme/keycloak/email/html/event-update_totp.ftl
new file mode 100644
index 0000000..c0190c7
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/html/event-update_totp.ftl
@@ -0,0 +1,5 @@
+<html>
+<body>
+${msg("eventUpdateTotpBodyHtml",event.date, event.ipAddress)}
+</body>
+</html>
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/html/password-reset.ftl b/forms/common-themes/src/main/resources/theme/keycloak/email/html/password-reset.ftl
new file mode 100644
index 0000000..846b45d
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/html/password-reset.ftl
@@ -0,0 +1,5 @@
+<html>
+<body>
+${msg("passwordResetBodyHtml",link, linkExpiration, realmName)}
+</body>
+</html>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_de.properties b/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_de.properties
index 0256640..91337c4 100644
--- a/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_de.properties
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_de.properties
@@ -1,12 +1,18 @@
emailVerificationSubject=E-Mail verifizieren
passwordResetSubject=Passwort zur\u00FCckzusetzen
passwordResetBody=Jemand hat angefordert Ihr {2} Passwort zur\u00FCckzusetzen. Falls das Sie waren, dann klicken Sie auf den folgenden Link um das Passwort zur\u00FCckzusetzen.\n\n{0}\n\nDieser Link wird in {1} Minuten ablaufen.\n\nFalls Sie das Passwort nicht zur\u00FCcksetzen m\u00F6chten, dann k\u00F6nnen Sie diese E-Mail ignorieren.
+passwordResetBodyHtml=<p>Jemand hat angefordert Ihr {2} Passwort zur\u00FCckzusetzen. Falls das Sie waren, dann klicken Sie auf den folgenden Link um das Passwort zur\u00FCckzusetzen.</p><p><a href="{0}">{0}</a></p><p>Dieser Link wird in {1} Minuten ablaufen.</p><p>Falls Sie das Passwort nicht zur\u00FCcksetzen m\u00F6chten, dann k\u00F6nnen Sie diese E-Mail ignorieren.</p>
emailVerificationBody=Jemand hat ein {2} Konto mit dieser E-Mail Adresse erstellt. Fall das Sie waren, dann klicken Sie auf den Link um die E-Mail Adresse zu verifizieren.\n\n{0}\n\nDieser Link wird in {1} Minuten ablaufen.\n\nFalls Sie dieses Konto nicht erstellt haben, dann k\u00F6nnen sie diese Nachricht ignorieren.
+emailVerificationBodyHtml=<p>Jemand hat ein {2} Konto mit dieser E-Mail Adresse erstellt. Fall das Sie waren, dann klicken Sie auf den Link um die E-Mail Adresse zu verifizieren.</p><p><a href="{0}">{0}</a></p><p>Dieser Link wird in {1} Minuten ablaufen.</p><p>Falls Sie dieses Konto nicht erstellt haben, dann k\u00F6nnen sie diese Nachricht ignorieren.</p>
eventLoginErrorSubject=Fehlgeschlagene Anmeldung
eventLoginErrorBody=Jemand hat um {0} von {1} versucht sich mit ihrem Konto anzumelden. Falls das nicht Sie waren, dann kontaktieren Sie bitte Ihren Admin.
+eventLoginErrorBodyHtml=<p>Jemand hat um {0} von {1} versucht sich mit ihrem Konto anzumelden. Falls das nicht Sie waren, dann kontaktieren Sie bitte Ihren Admin.</p>
eventRemoveTotpSubject=TOTP Entfernt
eventRemoveTotpBody=TOTP wurde von ihrem Konto am {0} von {1} entfernt. Falls das nicht Sie waren, dann kontaktieren Sie bitte Ihren Admin.
+eventRemoveTotpBodyHtml=<p>TOTP wurde von ihrem Konto am {0} von {1} entfernt. Falls das nicht Sie waren, dann kontaktieren Sie bitte Ihren Admin.</p>
eventUpdatePasswordSubject=Passwort Aktualisiert
eventUpdatePasswordBody=Ihr Passwort wurde am {0} von {1} ge\u00E4ndert. Falls das nicht Sie waren, dann kontaktieren Sie bitte Ihren Admin.
+eventUpdatePasswordBodyHtml=<p>Ihr Passwort wurde am {0} von {1} ge\u00E4ndert. Falls das nicht Sie waren, dann kontaktieren Sie bitte Ihren Admin.</p>
eventUpdateTotpSubject=TOTP Aktualisiert
eventUpdateTotpBody=TOTP wurde am {0} von {1} ge\u00E4ndert. Falls das nicht Sie waren, dann kontaktieren Sie bitte Ihren Admin.
+eventUpdateTotpBodyHtml=<p>TOTP wurde am {0} von {1} ge\u00E4ndert. Falls das nicht Sie waren, dann kontaktieren Sie bitte Ihren Admin.</p>
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_en.properties b/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_en.properties
index c0afc9c..7a3ac65 100755
--- a/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_en.properties
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_en.properties
@@ -1,12 +1,18 @@
emailVerificationSubject=Verify email
emailVerificationBody=Someone has created a {2} account with this email address. If this was you, click the link below to verify your email address\n\n{0}\n\nThis link will expire within {1} minutes.\n\nIf you didn''t create this account, just ignore this message.
+emailVerificationBodyHtml=<p>Someone has created a {2} account with this email address. If this was you, click the link below to verify your email address</p><p><a href="{0}">{0}</a></p><p>This link will expire within {1} minutes.</p><p>If you didn''t create this account, just ignore this message.</p>
passwordResetSubject=Reset password
passwordResetBody=Someone just requested to change your {2} account''s password. If this was you, click on the link below to set a new password\n\n{0}\n\nThis link will expire within {1} minutes.\n\nIf you don''t want to reset your password, just ignore this message and nothing will be changed.
+passwordResetBodyHtml=<p>Someone just requested to change your {2} account''s password. If this was you, click on the link below to set a new password</p><p><a href="{0}">{0}</a></p><p>This link will expire within {1} minutes.</p><p>If you don''t want to reset your password, just ignore this message and nothing will be changed.</p>
eventLoginErrorSubject=Login error
-eventLoginErrorBody=A failed login attempt was dettected to your account on {0} from {1}. If this was not you, please contact an admin.
+eventLoginErrorBody=A failed login attempt was detected to your account on {0} from {1}. If this was not you, please contact an admin.
+eventLoginErrorBodyHtml=<p>A failed login attempt was detected to your account on {0} from {1}. If this was not you, please contact an admin.</p>
eventRemoveTotpSubject=Remove TOTP
eventRemoveTotpBody=TOTP was removed from your account on {0} from {1}. If this was not you, please contact an admin.
+eventRemoveTotpBodyHtml=<p>TOTP was removed from your account on {0} from {1}. If this was not you, please contact an admin.</p>
eventUpdatePasswordSubject=Update password
eventUpdatePasswordBody=Your password was changed on {0} from {1}. If this was not you, please contact an admin.
+eventUpdatePasswordBodyHtml=<p>Your password was changed on {0} from {1}. If this was not you, please contact an admin.</p>
eventUpdateTotpSubject=Update TOTP
-eventUpdateTotpBody=TOTP was updated for your account on {0} from {1}. If this was not you, please contact an admin.
\ No newline at end of file
+eventUpdateTotpBody=TOTP was updated for your account on {0} from {1}. If this was not you, please contact an admin.
+eventUpdateTotpBodyHtml=<p>TOTP was updated for your account on {0} from {1}. If this was not you, please contact an admin.</p>
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_pt_BR.properties b/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_pt_BR.properties
index 0316e19..fff7e10 100644
--- a/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_pt_BR.properties
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_pt_BR.properties
@@ -1,12 +1,18 @@
emailVerificationSubject=Verifica\u00E7\u00E3o de e-mail
emailVerificationBody=Algu\u00E9m criou uma conta {2} com este endere\u00E7o de e-mail. Se foi voc\u00EA, clique no link abaixo para verificar o seu endere\u00E7o de email\n\n{0}\n\nEste link ir\u00E1 expirar dentro de {1} minutos.\n\nSe n\u00E3o foi voc\u00EA que criou esta conta, basta ignorar esta mensagem.
+emailVerificationBodyHtml=<p>Algu\u00E9m criou uma conta {2} com este endere\u00E7o de e-mail. Se foi voc\u00EA, clique no link abaixo para verificar o seu endere\u00E7o de email</p><p><a href="{0}">{0}</a></p><p>Este link ir\u00E1 expirar dentro de {1} minutos.</p><p>Se n\u00E3o foi voc\u00EA que criou esta conta, basta ignorar esta mensagem.</p>
passwordResetSubject=Redefini\u00E7\u00E3o de senha
passwordResetBody=Algu\u00E9m pediu para mudar a senha de sua conta {2}. Se foi voc\u00EA, clique no link abaixo para definir uma nova senha\n\n{0}\n\nEste link ir\u00E1 expirar dentro de {1} minutos.\n\nSe voc\u00EA n\u00E3o deseja redefinir sua senha, basta ignorar esta mensagem e nada ser\u00E1 mudado.
+passwordResetBodyHtml=<p>Algu\u00E9m pediu para mudar a senha de sua conta {2}. Se foi voc\u00EA, clique no link abaixo para definir uma nova senha</p><p><a href="{0}">{0}</a></p><p>Este link ir\u00E1 expirar dentro de {1} minutos.</p><p>Se voc\u00EA n\u00E3o deseja redefinir sua senha, basta ignorar esta mensagem e nada ser\u00E1 mudado.</p>
eventLoginErrorSubject=Erro de login
eventLoginErrorBody=Uma tentativa de login mal sucedida para a sua conta foi detectada em {0} de {1}. Se n\u00E3o foi voc\u00EA, por favor, entre em contato com um administrador.
+eventLoginErrorBodyHtml=<p>Uma tentativa de login mal sucedida para a sua conta foi detectada em {0} de {1}. Se n\u00E3o foi voc\u00EA, por favor, entre em contato com um administrador.</p>
eventRemoveTotpSubject=Remover TOTP
eventRemoveTotpBody=TOTP foi removido da sua conta em {0} de {1}. Se n\u00E3o foi voc\u00EA, por favor, entre em contato com um administrador.
+eventRemoveTotpBodyHtml=<p>TOTP foi removido da sua conta em {0} de {1}. Se n\u00E3o foi voc\u00EA, por favor, entre em contato com um administrador.</p>
eventUpdatePasswordSubject=Atualiza\u00E7\u00E3o de senha
eventUpdatePasswordBody=Sua senha foi alterada em {0} de {1}. Se n\u00E3o foi voc\u00EA, por favor, entre em contato com um administrador.
+eventUpdatePasswordBodyHtml=<p>Sua senha foi alterada em {0} de {1}. Se n\u00E3o foi voc\u00EA, por favor, entre em contato com um administrador.</p>
eventUpdateTotpSubject=Atualiza\u00E7\u00E3o TOTP
eventUpdateTotpBody=TOTP foi atualizado para a sua conta em {0} de {1}. Se n\u00E3o foi voc\u00EA, por favor, entre em contato com um administrador.
+eventUpdateTotpBodyHtml=<p>TOTP foi atualizado para a sua conta em {0} de {1}. Se n\u00E3o foi voc\u00EA, por favor, entre em contato com um administrador.</p>
diff --git a/forms/email-freemarker/src/main/java/org/keycloak/email/freemarker/FreeMarkerEmailProvider.java b/forms/email-freemarker/src/main/java/org/keycloak/email/freemarker/FreeMarkerEmailProvider.java
index 95f55f3..79080de 100755
--- a/forms/email-freemarker/src/main/java/org/keycloak/email/freemarker/FreeMarkerEmailProvider.java
+++ b/forms/email-freemarker/src/main/java/org/keycloak/email/freemarker/FreeMarkerEmailProvider.java
@@ -1,11 +1,28 @@
package org.keycloak.email.freemarker;
+import java.text.MessageFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.mail.Message;
+import javax.mail.Multipart;
+import javax.mail.Session;
+import javax.mail.Transport;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+
import org.jboss.logging.Logger;
import org.keycloak.email.EmailException;
import org.keycloak.email.EmailProvider;
import org.keycloak.email.freemarker.beans.EventBean;
import org.keycloak.events.Event;
import org.keycloak.events.EventType;
+import org.keycloak.freemarker.FreeMarkerException;
import org.keycloak.freemarker.FreeMarkerUtil;
import org.keycloak.freemarker.LocaleHelper;
import org.keycloak.freemarker.Theme;
@@ -15,14 +32,6 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
-import javax.mail.Message;
-import javax.mail.Session;
-import javax.mail.Transport;
-import javax.mail.internet.InternetAddress;
-import javax.mail.internet.MimeMessage;
-import java.text.MessageFormat;
-import java.util.*;
-
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
@@ -93,16 +102,29 @@ public class FreeMarkerEmailProvider implements EmailProvider {
Properties rb = theme.getMessages(locale);
attributes.put("msg", new MessageFormatterMethod(locale, rb));
String subject = new MessageFormat(rb.getProperty(subjectKey,subjectKey),locale).format(new Object[0]);
- String body = freeMarker.processTemplate(attributes, template, theme);
+ String textTemplate = String.format("text/%s", template);
+ String textBody;
+ try {
+ textBody = freeMarker.processTemplate(attributes, textTemplate, theme);
+ } catch (final FreeMarkerException e ) {
+ textBody = null;
+ }
+ String htmlTemplate = String.format("html/%s", template);
+ String htmlBody;
+ try {
+ htmlBody = freeMarker.processTemplate(attributes, htmlTemplate, theme);
+ } catch (final FreeMarkerException e ) {
+ htmlBody = null;
+ }
- send(subject, body);
+ send(subject, textBody, htmlBody);
} catch (Exception e) {
throw new EmailException("Failed to template email", e);
}
}
- private void send(String subject, String body) throws EmailException {
+ private void send(String subject, String textBody, String htmlBody) throws EmailException {
try {
String address = user.getEmail();
Map<String, String> config = realm.getSmtpConfig();
@@ -135,11 +157,25 @@ public class FreeMarkerEmailProvider implements EmailProvider {
Session session = Session.getInstance(props);
+ Multipart multipart = new MimeMultipart("alternative");
+
+ if(textBody != null) {
+ MimeBodyPart textPart = new MimeBodyPart();
+ textPart.setText(textBody, "UTF-8");
+ multipart.addBodyPart(textPart);
+ }
+
+ if(htmlBody != null) {
+ MimeBodyPart htmlPart = new MimeBodyPart();
+ htmlPart.setContent(htmlBody, "text/html; charset=UTF-8");
+ multipart.addBodyPart(htmlPart);
+ }
+
Message msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(from));
msg.setHeader("To", address);
msg.setSubject(subject);
- msg.setText(body);
+ msg.setContent(multipart);
msg.saveChanges();
msg.setSentDate(new Date());
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionEmailVerificationTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionEmailVerificationTest.java
index 0d6b4cf..4b167cb 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionEmailVerificationTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionEmailVerificationTest.java
@@ -49,7 +49,9 @@ import org.keycloak.testsuite.rule.WebRule;
import org.openqa.selenium.WebDriver;
import javax.mail.MessagingException;
+import javax.mail.Multipart;
import javax.mail.internet.MimeMessage;
+
import java.io.IOException;
import static org.junit.Assert.assertEquals;
@@ -119,9 +121,8 @@ public class RequiredActionEmailVerificationTest {
Assert.assertEquals(1, greenMail.getReceivedMessages().length);
MimeMessage message = greenMail.getReceivedMessages()[0];
-
- String body = (String) message.getContent();
- String verificationUrl = MailUtil.getLink(body);
+
+ String verificationUrl = getPasswordResetEmailLink(message);
AssertEvents.ExpectedEvent emailEvent = events.expectRequiredAction(EventType.SEND_VERIFY_EMAIL).detail("email", "test-user@localhost");
Event sendEvent = emailEvent.assertEvent();
@@ -154,14 +155,12 @@ public class RequiredActionEmailVerificationTest {
MimeMessage message = greenMail.getReceivedMessages()[0];
- String body = (String) message.getContent();
-
Event sendEvent = events.expectRequiredAction(EventType.SEND_VERIFY_EMAIL).user(userId).detail("username", "verifyEmail").detail("email", "email@mail.com").assertEvent();
String sessionId = sendEvent.getSessionId();
String mailCodeId = sendEvent.getDetails().get(Details.CODE_ID);
- String verificationUrl = MailUtil.getLink(body);
+ String verificationUrl = getPasswordResetEmailLink(message);
driver.navigate().to(verificationUrl.trim());
@@ -192,11 +191,9 @@ public class RequiredActionEmailVerificationTest {
MimeMessage message = greenMail.getReceivedMessages()[1];
- String body = (String) message.getContent();
-
events.expectRequiredAction(EventType.SEND_VERIFY_EMAIL).session(sessionId).detail("email", "test-user@localhost").assertEvent(sendEvent);
- String verificationUrl = MailUtil.getLink(body);
+ String verificationUrl = getPasswordResetEmailLink(message);
driver.navigate().to(verificationUrl.trim());
@@ -218,8 +215,7 @@ public class RequiredActionEmailVerificationTest {
MimeMessage message = greenMail.getReceivedMessages()[0];
- String body = (String) message.getContent();
- String verificationUrl = MailUtil.getLink(body);
+ String verificationUrl = getPasswordResetEmailLink(message);
AssertEvents.ExpectedEvent emailEvent = events.expectRequiredAction(EventType.SEND_VERIFY_EMAIL).detail("email", "test-user@localhost");
Event sendEvent = emailEvent.assertEvent();
@@ -242,6 +238,27 @@ public class RequiredActionEmailVerificationTest {
assertTrue(loginPage.isCurrent());
}
-
+
+ private String getPasswordResetEmailLink(MimeMessage message) throws IOException, MessagingException {
+ Multipart multipart = (Multipart) message.getContent();
+
+ final String textContentType = multipart.getBodyPart(0).getContentType();
+
+ assertEquals("text/plain; charset=UTF-8", textContentType);
+
+ final String textBody = (String) multipart.getBodyPart(0).getContent();
+ final String textChangePwdUrl = MailUtil.getLink(textBody);
+
+ final String htmlContentType = multipart.getBodyPart(1).getContentType();
+
+ assertEquals("text/html; charset=UTF-8", htmlContentType);
+
+ final String htmlBody = (String) multipart.getBodyPart(1).getContent();
+ final String htmlChangePwdUrl = MailUtil.getLink(htmlBody);
+
+ assertEquals(htmlChangePwdUrl, textChangePwdUrl);
+
+ return htmlChangePwdUrl;
+ }
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java
index e82744f..f6f7345 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/broker/AbstractIdentityProviderTest.java
@@ -53,6 +53,7 @@ import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import javax.mail.MessagingException;
+import javax.mail.Multipart;
import javax.mail.internet.MimeMessage;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
@@ -187,8 +188,7 @@ public abstract class AbstractIdentityProviderTest {
// read email to take verification link from
Assert.assertEquals(1, greenMail.getReceivedMessages().length);
MimeMessage message = greenMail.getReceivedMessages()[0];
- String body = (String) message.getContent();
- String verificationUrl = MailUtil.getLink(body);
+ String verificationUrl = getVerificationEmailLink(message);
driver.navigate().to(verificationUrl.trim());
@@ -805,4 +805,26 @@ public abstract class AbstractIdentityProviderTest {
}
}
}
+
+ private String getVerificationEmailLink(MimeMessage message) throws IOException, MessagingException {
+ Multipart multipart = (Multipart) message.getContent();
+
+ final String textContentType = multipart.getBodyPart(0).getContentType();
+
+ assertEquals("text/plain; charset=UTF-8", textContentType);
+
+ final String textBody = (String) multipart.getBodyPart(0).getContent();
+ final String textVerificationUrl = MailUtil.getLink(textBody);
+
+ final String htmlContentType = multipart.getBodyPart(1).getContentType();
+
+ assertEquals("text/html; charset=UTF-8", htmlContentType);
+
+ final String htmlBody = (String) multipart.getBodyPart(1).getContent();
+ final String htmlVerificationUrl = MailUtil.getLink(htmlBody);
+
+ assertEquals(htmlVerificationUrl, textVerificationUrl);
+
+ return htmlVerificationUrl;
+ }
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java
index ed94502..26b1f79 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/ResetPasswordTest.java
@@ -52,7 +52,9 @@ import org.keycloak.util.Time;
import org.openqa.selenium.WebDriver;
import javax.mail.MessagingException;
+import javax.mail.Multipart;
import javax.mail.internet.MimeMessage;
+
import java.io.IOException;
import java.util.Collections;
@@ -146,9 +148,8 @@ public class ResetPasswordTest {
assertEquals(1, greenMail.getReceivedMessages().length);
MimeMessage message = greenMail.getReceivedMessages()[0];
-
- String body = (String) message.getContent();
- String changePasswordUrl = MailUtil.getLink(body);
+
+ final String changePasswordUrl = getPasswordResetEmailLink(message);
driver.navigate().to(changePasswordUrl.trim());
@@ -211,8 +212,7 @@ public class ResetPasswordTest {
MimeMessage message = greenMail.getReceivedMessages()[0];
- String body = (String) message.getContent();
- String changePasswordUrl = MailUtil.getLink(body);
+ String changePasswordUrl = getPasswordResetEmailLink(message);
driver.navigate().to(changePasswordUrl.trim());
@@ -256,8 +256,7 @@ public class ResetPasswordTest {
MimeMessage message = greenMail.getReceivedMessages()[greenMail.getReceivedMessages().length - 1];
- String body = (String) message.getContent();
- String changePasswordUrl = MailUtil.getLink(body);
+ String changePasswordUrl = getPasswordResetEmailLink(message);
driver.navigate().to(changePasswordUrl.trim());
@@ -294,8 +293,7 @@ public class ResetPasswordTest {
MimeMessage message = greenMail.getReceivedMessages()[greenMail.getReceivedMessages().length - 1];
- String body = (String) message.getContent();
- String changePasswordUrl = MailUtil.getLink(body);
+ String changePasswordUrl = getPasswordResetEmailLink(message);
driver.navigate().to(changePasswordUrl.trim());
@@ -364,8 +362,7 @@ public class ResetPasswordTest {
MimeMessage message = greenMail.getReceivedMessages()[0];
- String body = (String) message.getContent();
- String changePasswordUrl = MailUtil.getLink(body);
+ String changePasswordUrl = getPasswordResetEmailLink(message);
Time.setOffset(350);
@@ -513,8 +510,7 @@ public class ResetPasswordTest {
MimeMessage message = greenMail.getReceivedMessages()[0];
- String body = (String) message.getContent();
- String changePasswordUrl = MailUtil.getLink(body);
+ String changePasswordUrl = getPasswordResetEmailLink(message);
String sessionId = events.expectRequiredAction(EventType.SEND_RESET_PASSWORD).user(userId).detail(Details.USERNAME, "login-test").detail(Details.EMAIL, "login@test.com").assertEvent().getSessionId();
@@ -609,8 +605,7 @@ public class ResetPasswordTest {
MimeMessage message = greenMail.getReceivedMessages()[0];
- String body = (String) message.getContent();
- String changePasswordUrl = MailUtil.getLink(body);
+ String changePasswordUrl = getPasswordResetEmailLink(message);
driver.manage().deleteAllCookies();
@@ -629,5 +624,27 @@ public class ResetPasswordTest {
assertTrue(loginPage.isCurrent());
}
+
+ private String getPasswordResetEmailLink(MimeMessage message) throws IOException, MessagingException {
+ Multipart multipart = (Multipart) message.getContent();
+
+ final String textContentType = multipart.getBodyPart(0).getContentType();
+
+ assertEquals("text/plain; charset=UTF-8", textContentType);
+
+ final String textBody = (String) multipart.getBodyPart(0).getContent();
+ final String textChangePwdUrl = MailUtil.getLink(textBody);
+
+ final String htmlContentType = multipart.getBodyPart(1).getContentType();
+
+ assertEquals("text/html; charset=UTF-8", htmlContentType);
+
+ final String htmlBody = (String) multipart.getBodyPart(1).getContent();
+ final String htmlChangePwdUrl = MailUtil.getLink(htmlBody);
+
+ assertEquals(htmlChangePwdUrl, textChangePwdUrl);
+
+ return htmlChangePwdUrl;
+ }
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/MailUtil.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/MailUtil.java
index 9691301..f29ae4e 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/MailUtil.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/MailUtil.java
@@ -8,7 +8,7 @@ import java.util.regex.Pattern;
*/
public class MailUtil {
- private static Pattern mailPattern = Pattern.compile("http[^\\s]*");
+ private static Pattern mailPattern = Pattern.compile("http[^\\s\"]*");
public static String getLink(String body) {
Matcher matcher = mailPattern.matcher(body);