diff --git a/.github/workflows/quickstart_mail_ci.yml b/.github/workflows/quickstart_mail_ci.yml new file mode 100644 index 0000000000..5313a12376 --- /dev/null +++ b/.github/workflows/quickstart_mail_ci.yml @@ -0,0 +1,17 @@ +name: WildFly Mail Quickstart CI + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + paths: + - 'mail/**' + - '.github/workflows/quickstart_ci.yml' + +jobs: + call-quickstart_ci: + uses: ./.github/workflows/quickstart_ci.yml + with: + QUICKSTART_PATH: mail + TEST_PROVISIONED_SERVER: true + TEST_OPENSHIFT: false + MATRIX_OS: '"ubuntu-latest"' diff --git a/.github/workflows/quickstart_mail_ci_before.sh b/.github/workflows/quickstart_mail_ci_before.sh new file mode 100755 index 0000000000..66cf6ff715 --- /dev/null +++ b/.github/workflows/quickstart_mail_ci_before.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +# Start apache James with the required configuration +docker run -d --rm --name "apache-james" \ + -p 1465:465 \ + -p 1993:993 \ + -p 1025:25 \ + -p 1110:110 \ + -p 1587:587 \ + -p 1143:143 \ + -v ${GITHUB_WORKSPACE}/quickstarts/mail/mail-server-conf/imapserver.xml:/root/conf/imapserver.xml \ + -v ${GITHUB_WORKSPACE}/quickstarts/mail/mail-server-conf/pop3server.xml:/root/conf/pop3server.xml \ + -v ${GITHUB_WORKSPACE}/quickstarts/mail/mail-server-conf/smtpserver.xml:/root/conf/smtpserver.xml \ + apache/james:demo-3.8.0 diff --git a/mail/README.adoc b/mail/README.adoc index 4ef3b4b792..3a38725adb 100644 --- a/mail/README.adoc +++ b/mail/README.adoc @@ -6,7 +6,7 @@ include::../shared-doc/attributes.adoc[] :technologies: JavaMail, CDI, JSF [abstract] -The `mail` quickstart demonstrates how to send email using CDI and JSF and the default Mail provider that ships with {productName}. +The `mail` quickstart demonstrates how to send and receive emails using CDI and JSF and with custom Mail provider configured in {productName}. :standalone-server-type: default :archiveType: war @@ -14,13 +14,13 @@ The `mail` quickstart demonstrates how to send email using CDI and JSF and the d == What is it? -The `mail` quickstart demonstrates sending email with the use of _CDI_ (Contexts and Dependency Injection) and _JSF_ (JavaServer Faces) in {productNameFull}. +The `mail` quickstart demonstrates sending and receiving emails with the use of _CDI_ (Contexts and Dependency Injection) and _JSF_ (JavaServer Faces) in {productNameFull}. The mail provider is configured in the `mail` subsystem of the `__{jbossHomeName}__/standalone/configuration/standalone.xml` configuration file if you are running a standalone server or in the `__{jbossHomeName}__/domain/configuration/domain.xml` configuration file if you are running in a managed domain. You can use the default mail provider that comes out of the box with {productName}. It uses your local mail relay and the default SMTP port of 25. However, this quickstart demonstrates how to define and use a custom mail provider. -This example is a web application that takes `To`, `From`, `Subject`, and `Message Body` input and sends mail to that address. The front end is a JSF page with a simple POJO backing, leveraging CDI for resource injection. +This example is a web application that takes `To`, `From`, `Subject`, and `Message Body` input and sends mail using SMTP. These emails can be later read by using IMAP or POP3. The front end is a JSF page with a simple POJO backing, leveraging CDI for resource injection. // System Requirements include::../shared-doc/system-requirements.adoc[leveloffset=+1] @@ -28,12 +28,44 @@ include::../shared-doc/system-requirements.adoc[leveloffset=+1] include::../shared-doc/use-of-jboss-home-name.adoc[leveloffset=+1] [[configure_an_smtp_server_on_your_local_machine]] -== Configure an SMTP Server on Your Local Machine +== Configure a Mail Server on Your Local Machine -This quickstart expects that you have an SMTP mail server running on your machine and configured for the default port `localhost:25`. -To configure an SMTP mail server, consult the documentation for your operating system. It is beyond the scope of this quickstart to provide these instructions. +To run the Mail Quickstart, you need a Mail Server configured with the following protocols and ports: -If you do not configure an SMTP mail server on your local machine, you will see the exception `MailConnectException: Couldn't connect to host, port: localhost, 25; timeout -1;` when you access the application and attempt to send an email. +- SMTP port:1025 +- POP3 port:1110 +- IMAP port:1143 + +In addition, the Mail Subsystem configuration and the test cases expect you have the following Mail accounts configured on your Mail Server: + +- user01@james.local +- user02@james.local + +You can use any Mail Server you consider, although to facilitate this task, you will find under the Mail Quickstart root directory a docker compose file prepared to launch an Apache James Mail server with all the required configuration. You will need to have installed a Container Engine capable of work with Docker compose files and Linux images. The following command assumes you have https://podman.io/[Podman] and https://docs.podman.io/en/latest/markdown/podman-compose.1.html[Podman Compose] installed in your local environment. + +To launch the Apache James Mail server, open the terminal and navigate to the Mail Quickstart root directory and execute the following: + +``` +$ podman compose up --wait +>>>> Executing external compose provider "/usr/local/bin/docker-compose". Please refer to the documentation for details. <<<< + +[+] Running 1/1 + ✔ Container apache-james Healthy +``` + +NOTE: The Apache James server is configured without allowing the relay of the emails to external addresses that are not configured in the server. When you are sending / receiving emails with this server, you have to use the accounts shipped with the apache James demo image. These are the accounts available out of the box: user01@james.local, user02@james.local and user03@james.local. +All accounts use the same password: `1234` + +Once you have finished with the Mail Quickstart, you can shutdown and remove the Apache James Mail server with the following command: + +``` +$ podman compose down --volumes +>>>> Executing external compose provider "/usr/local/bin/docker-compose". Please refer to the documentation for details. <<<< + +[+] Running 2/1 + ✔ Container apache-james Removed + ✔ Network mail_default Removed +``` // Back Up the {productName} Standalone Server Configuration include::../shared-doc/back-up-server-standalone-configuration.adoc[leveloffset=+1] @@ -50,7 +82,7 @@ You configure the custom mail session in {productName} by running Management CLI * xref:back_up_standalone_server_configuration[Back up the {productName} standalone server configuration] as described above. * xref:start_the_eap_standalone_server[Start the {productName} server with the standalone default profile] as described above. -. Review the `configure-mail-session.cli` file in the root of this quickstart directory. This script creates custom outbound socket binding port for SMTP, POP3, and IMAP. It then creates the custom `MyOtherMail` mail session and configures it to use the custom outbound socket binding ports. +. Review the `configure-mail-session.cli` file in the root of this quickstart directory. This script creates custom outbound socket binding port for SMTP, POP3, and IMAP. It then creates the custom `MyOtherMail` mail session and configures it to use the custom outbound socket binding ports and default user credentials for SMTP and IMAP. . Open a new terminal, navigate to the root directory of this quickstart, and run the following command, replacing `__{jbossHomeName}__` with the path to your server: + [source,subs="+quotes,attributes+",options="nowrap"] @@ -82,14 +114,14 @@ The following `outbound-socket-binding` groups are added to the `standard-socket ... - - + + - + - - + + ---- @@ -102,10 +134,10 @@ The `MyOtherMail` mail session is added to the `mail` subsystem and configured t - - - - + + + + ---- @@ -115,9 +147,14 @@ include::../shared-doc/build-and-deploy-the-quickstart.adoc[leveloffset=+1] == Access the Application -The application will be running at the following URL: http://localhost:8080/{artifactId}/. +The application will be running at the following URL: http://localhost:8080/{artifactId}/[http://localhost:8080/{artifactId}/^]. + +NOTE: If you see `Error processing request` in the browser when you access the application and attempt to send email, followed by `jakarta.servlet.ServletException: MailConnectException: Couldn't connect to host, port: localhost, 1025; timeout -1; nested exception is: java.net.ConnectException: Connection refused`, make sure you followed the instructions above to xref:configure_an_smtp_server_on_your_local_machine[Configure an SMTP Server on Your Local Machine]. -NOTE: If you see `Error processing request` in the browser when you access the application and attempt to send email, followed by `jakarta.servlet.ServletException: MailConnectException: Couldn't connect to host, port: localhost, 25; timeout -1; nested exception is: java.net.ConnectException: Connction refused`, make sure you followed the instructions above to xref:configure_an_smtp_server_on_your_local_machine[Configure an SMTP Server on Your Local Machine]. +NOTE: If you are using the Mail server shipped with this Quickstart and see `Error sending the Email. Invalid Addresses` in the browser when you attempt to send email, make sure you are sending your email to an existing account configured in the Mail Server since by default Apache James demo image is shipped with relay disabled. By default, Apache James demo image has the following accounts configured: user01@james.local, user02@james.local and user03@james.local. + +// Server Distribution Testing +include::../shared-doc/run-integration-tests-with-server-distribution.adoc[leveloffset=+2] // Undeploy the Quickstart include::../shared-doc/undeploy-the-quickstart.adoc[leveloffset=+1] @@ -148,6 +185,11 @@ include::../shared-doc/run-the-quickstart-in-jboss-developer-studio.adoc[levelof // Debug the Application include::../shared-doc/debug-the-application.adoc[leveloffset=+1] +// Build and run sections for other environments/builds +ifndef::ProductRelease,EAPXPRelease[] +include::../shared-doc/build-and-run-the-quickstart-with-provisioned-server.adoc[leveloffset=+1] +endif::[] + //************************************************* // Product Release content only //************************************************* @@ -156,4 +198,4 @@ ifdef::ProductRelease[] // Quickstart not compatible with OpenShift include::../shared-doc/openshift-incompatibility.adoc[leveloffset=+1] -endif::[] \ No newline at end of file +endif::[] diff --git a/mail/configure-mail-session.cli b/mail/configure-mail-session.cli index 19c987de70..e0ed2f5208 100644 --- a/mail/configure-mail-session.cli +++ b/mail/configure-mail-session.cli @@ -7,14 +7,14 @@ batch /subsystem=mail/mail-session=MyOtherMail:add(jndi-name=java:jboss/mail/MyOtherMail,debug=true) # Configure the custom SMTP, POP3, and IMAP socket binding groups -/socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=my-smtp-binding:add(host=localhost,port=25) -/socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=my-pop3-binding:add(host=localhost,port=110) -/socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=my-imap-binding:add(host=localhost,port=143) +/socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=my-smtp-binding:add(host=localhost,port=1025) +/socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=my-pop3-binding:add(host=localhost,port=1110) +/socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=my-imap-binding:add(host=localhost,port=1143) # Add the custom socket binding groups to the custom MyOtherMail mail session -/subsystem=mail/mail-session=MyOtherMail/server=smtp:add(outbound-socket-binding-ref=my-smtp-binding,username=nobody,password=pass,tls=true) +/subsystem=mail/mail-session=MyOtherMail/server=smtp:add(outbound-socket-binding-ref=my-smtp-binding,username="user01@james.local",password=1234) /subsystem=mail/mail-session=MyOtherMail/server=pop3:add(outbound-socket-binding-ref=my-pop3-binding) -/subsystem=mail/mail-session=MyOtherMail/server=imap:add(outbound-socket-binding-ref=my-imap-binding,username=nobody,password=pass) +/subsystem=mail/mail-session=MyOtherMail/server=imap:add(outbound-socket-binding-ref=my-imap-binding, username="user02@james.local",password=1234) # Run the batch commands run-batch diff --git a/mail/docker-compose.yaml b/mail/docker-compose.yaml new file mode 100644 index 0000000000..f20af5c8a5 --- /dev/null +++ b/mail/docker-compose.yaml @@ -0,0 +1,22 @@ +services: + quickstart-mail-server: + image: "apache/james:demo-3.8.0" + container_name: "apache-james" + hostname: "james.local" + ports: + - "1465:465" + - "1993:993" + - "1025:25" + - "1110:110" + - "1587:587" + - "1143:143" + volumes: + - ./mail-server-conf/imapserver.xml:/root/conf/imapserver.xml + - ./mail-server-conf/pop3server.xml:/root/conf/pop3server.xml + - ./mail-server-conf/smtpserver.xml:/root/conf/smtpserver.xml + healthcheck: + test: [ "CMD-SHELL", "/bin/james-cli -h 127.0.0.1 -p 9999 ListUsers | grep -q 'user03@james.local'" ] + interval: 5s + timeout: 1m + retries: 5 + start_period: 20s diff --git a/mail/mail-server-conf/imapserver.xml b/mail/mail-server-conf/imapserver.xml new file mode 100644 index 0000000000..c7e3d1afe2 --- /dev/null +++ b/mail/mail-server-conf/imapserver.xml @@ -0,0 +1,17 @@ + + + + + imapserver + 0.0.0.0:143 + 200 + + file://conf/private.key + file://conf/private.csr + + 0 + 0 + false + false + + diff --git a/mail/mail-server-conf/pop3server.xml b/mail/mail-server-conf/pop3server.xml new file mode 100644 index 0000000000..e43e368be9 --- /dev/null +++ b/mail/mail-server-conf/pop3server.xml @@ -0,0 +1,19 @@ + + + + + pop3server + 0.0.0.0:110 + 200 + + file://conf/private.key + file://conf/private.csr + + 1200 + 0 + 0 + + + + + diff --git a/mail/mail-server-conf/smtpserver.xml b/mail/mail-server-conf/smtpserver.xml new file mode 100644 index 0000000000..c2a5b4d2ef --- /dev/null +++ b/mail/mail-server-conf/smtpserver.xml @@ -0,0 +1,28 @@ + + + + + smtpserver-global + 0.0.0.0:25 + 200 + + file://conf/private.key + file://conf/private.csr + + 360 + 0 + 0 + + never + false + + false + 0 + true + Apache JAMES awesome SMTP Server + + + + + + diff --git a/mail/pom.xml b/mail/pom.xml index fb38b1dd3f..6df6c2de8c 100644 --- a/mail/pom.xml +++ b/mail/pom.xml @@ -44,8 +44,15 @@ - - 30.0.0.Final + + 30.0.0.Final + + ${version.server} + 5.0.0.Final + 4.2.0.Final + + 4.15.0 + 5.6.2 @@ -109,7 +116,7 @@ org.wildfly.bom wildfly-ee-with-tools - ${version.server.bom} + ${version.bom.ee} pom import @@ -117,7 +124,6 @@ - jakarta.mail jakarta.mail-api @@ -139,5 +145,121 @@ jakarta.faces-api provided + + + + junit + junit + test + + + org.seleniumhq.selenium + selenium-java + ${version.org.seleniumhq.selenium} + test + + + + io.github.bonigarcia + webdrivermanager + ${version.webdrivermanager} + + + + + + + org.wildfly.plugins + wildfly-maven-plugin + ${version.plugin.wildfly} + + true + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 11 + 11 + + + + + + + + provisioned-server + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + + + core-tools + core-server + mail + jsf + + + ROOT.war + + + + + + + false + + + + + + + package + + + + + + + + + + integration-testing + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + **/*IT + + + + + + integration-test + verify + + + + + + + + + diff --git a/mail/src/main/java/org/jboss/as/quickstarts/mail/Email.java b/mail/src/main/java/org/jboss/as/quickstarts/mail/Email.java index dbb51b2616..0e76b078da 100644 --- a/mail/src/main/java/org/jboss/as/quickstarts/mail/Email.java +++ b/mail/src/main/java/org/jboss/as/quickstarts/mail/Email.java @@ -16,18 +16,24 @@ */ package org.jboss.as.quickstarts.mail; -import java.io.Serializable; - import jakarta.annotation.Resource; import jakarta.enterprise.context.SessionScoped; +import jakarta.faces.application.FacesMessage; +import jakarta.faces.context.FacesContext; import jakarta.inject.Named; import jakarta.mail.Address; +import jakarta.mail.Folder; import jakarta.mail.Message; +import jakarta.mail.MessagingException; import jakarta.mail.Session; +import jakarta.mail.Store; import jakarta.mail.Transport; import jakarta.mail.internet.InternetAddress; import jakarta.mail.internet.MimeMessage; +import java.io.IOException; +import java.io.Serializable; + /** *

* {@link Email} contains all the business logic for the application, and also serves as the controller for the JSF view. @@ -36,11 +42,13 @@ * It contains address, subject, and content for the email to be sent. *

*

- * The {@link #send()} method provides the business logic to send the email + * The {@link #send()} method provides the business logic to send the email. + * The {@link #retrievePop3()} method retrieves all the emails sent to a specific email account using POP3. + * The {@link #retrieveImap()} method retrieves all the emails sent to an account whose credentials are configured in + * the Mail subsystem using IMAP. *

* * @author Joel Tosi - * */ @Named @@ -56,14 +64,138 @@ public class Email implements Serializable { @Resource(mappedName = "java:jboss/mail/MyOtherMail") private Session mySession; - private String to; + private String to = "user02@james.local"; - private String from; + private String from = "user01@james.local"; private String subject; private String body; + private String pop3User = "user02@james.local"; + + private String pop3Password = "1234"; + + private String pop3Emails; + + private String imapEmails; + + /** + * Method to send the email based upon values entered in the JSF view. Exception should be handled in a production usage but + * is not handled in this example. + */ + public void send() { + try { + Message message = new MimeMessage(mySession); + message.setFrom(new InternetAddress(from)); + Address toAddress = new InternetAddress(to); + message.addRecipient(Message.RecipientType.TO, toAddress); + message.setSubject(subject); + message.setContent(body, "text/plain"); + Transport.send(message); + + FacesContext context = FacesContext.getCurrentInstance(); + FacesMessage facesMessage = new FacesMessage("Email sent to " + to); + context.addMessage(null, facesMessage); + } catch (Exception e) { + FacesContext context = FacesContext.getCurrentInstance(); + FacesMessage facesMessage = new FacesMessage("Error sending the Email. " + e.getMessage()); + context.addMessage(null, facesMessage); + } + } + + public void resetSmtp() { + from = "user01@james.local"; + to = "user02@james.local"; + subject = null; + body = null; + } + + public void retrievePop3() throws Exception { + try { + pop3Emails = retrieveEmails("pop3", pop3User, pop3Password); + if (pop3Emails == null) { + FacesContext context = FacesContext.getCurrentInstance(); + FacesMessage facesMessage = new FacesMessage("No message found."); + context.addMessage(null, facesMessage); + } + } catch (Exception e) { + FacesContext context = FacesContext.getCurrentInstance(); + FacesMessage facesMessage = new FacesMessage("Error retrieving emails using POP3. " + e.getMessage()); + context.addMessage(null, facesMessage); + } + } + + public void resetPop3() { + pop3User = "user02@james.local"; + pop3Password = "1234"; + pop3Emails = null; + } + + public void retrieveImap() throws Exception { + try { + imapEmails = retrieveEmails("imap"); + if (imapEmails == null) { + FacesContext context = FacesContext.getCurrentInstance(); + FacesMessage facesMessage = new FacesMessage("No message found."); + context.addMessage(null, facesMessage); + } + } catch (Exception e) { + FacesContext context = FacesContext.getCurrentInstance(); + FacesMessage facesMessage = new FacesMessage("Error retrieving emails using IMAP. " + e.getMessage()); + context.addMessage(null, facesMessage); + } + } + + public void resetImap() { + imapEmails = null; + } + + private String retrieveEmails(String protocol) throws MessagingException, IOException { + return retrieveEmails(protocol, null, null); + } + + private String retrieveEmails(String protocol, String user, String password) throws MessagingException, IOException { + Store store = mySession.getStore(protocol); + if (user != null && !user.trim().isEmpty()) { + store.connect(user, password); + } else { + // Users the credentials configured in the Mail Subsystem + store.connect(); + } + + Folder inbox = store.getFolder("Inbox"); + inbox.open(Folder.READ_ONLY); + + // get the list of inbox messages + Message[] messages = inbox.getMessages(); + + if (messages.length == 0) { + return null; + } + + StringBuilder sb = new StringBuilder("Emails retrieved via ").append(protocol).append("\n"); + for (int i = 0; i < messages.length; i++) { + // stop after listing ten messages + if (i > 10) { + inbox.close(true); + store.close(); + } + + sb.append("Message ").append((i + 1)).append("\n"); + sb.append("From : ").append(messages[i].getFrom()[0]).append("\n"); + sb.append("Subject : ").append(messages[i].getSubject()).append("\n"); + sb.append("Body : ").append(messages[i].getContent().toString()).append("\n"); + sb.append("Sent Date : ").append(messages[i].getSentDate()).append("\n"); + sb.append("----------------------------------").append("\n"); + } + + inbox.close(true); + store.close(); + + return sb.toString(); + } + public String getTo() { return to; } @@ -96,19 +228,35 @@ public void setBody(String body) { this.body = body; } - /** - * Method to send the email based upon values entered in the JSF view. Exception should be handled in a production usage but - * is not handled in this example. - * - * @throws Exception - */ - public void send() throws Exception { - Message message = new MimeMessage(mySession); - message.setFrom(new InternetAddress(from)); - Address toAddress = new InternetAddress(to); - message.addRecipient(Message.RecipientType.TO, toAddress); - message.setSubject(subject); - message.setContent(body, "text/plain"); - Transport.send(message); + public String getPop3User() { + return pop3User; + } + + public void setPop3User(String pop3User) { + this.pop3User = pop3User; + } + + public String getPop3Password() { + return pop3Password; + } + + public void setPop3Password(String pop3Password) { + this.pop3Password = pop3Password; + } + + public String getPop3Emails() { + return pop3Emails; + } + + public void setPop3Emails(String pop3Emails) { + this.pop3Emails = pop3Emails; + } + + public String getImapEmails() { + return imapEmails; + } + + public void setImapEmails(String imapEmails) { + this.imapEmails = imapEmails; } } diff --git a/mail/src/main/webapp/WEB-INF/beans.xml b/mail/src/main/webapp/WEB-INF/beans.xml index b0ec37c799..8c79e8f755 100644 --- a/mail/src/main/webapp/WEB-INF/beans.xml +++ b/mail/src/main/webapp/WEB-INF/beans.xml @@ -15,7 +15,6 @@ See the License for the specific language governing permissions and limitations under the License. --> - diff --git a/mail/src/main/webapp/home.xhtml b/mail/src/main/webapp/home.xhtml index 50577d66cb..7461ff12fb 100644 --- a/mail/src/main/webapp/home.xhtml +++ b/mail/src/main/webapp/home.xhtml @@ -15,40 +15,120 @@ limitations under the License. --> - - - - -mail - - - -
-

Send an email

- - -
- Send someone an email -
- - - -
- To: - - From: - - Subject: - - Body: - - -
-
- -
-
-
-
- - \ No newline at end of file + + + + + mail + + + + +

WildFly Email Quickstart

+ +

+ Send someone an email using SMTP: +

+ + + + + +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + + + + +
+ + +
+ + +

+ Retrieve emails using POP3: +

+ + + +
+ + + +
+ +
+ + + +
+ +
+ + +
+ +
+ + + + + + +
+ + +
+ + +

+ Retrieve emails for the user01@james.local account using IMAP: +

+ + + +
+ + +
+ +
+ + + + + + +
+ + +
+
+ diff --git a/mail/src/main/webapp/resources/css/main.css b/mail/src/main/webapp/resources/css/main.css new file mode 100644 index 0000000000..068809bb0f --- /dev/null +++ b/mail/src/main/webapp/resources/css/main.css @@ -0,0 +1,36 @@ +.form { + display: flex; + flex-direction: column; + align-items: flex-start; +} + +.form label { + margin-right: 10px; + white-space: nowrap; + width: 100px; +} + +.form input { + width: 200px; + margin-right: 10px +} + +.form textarea { + resize: inline; + min-height: 100px; + vertical-align: bottom; + display: flex; + width: 530px; + margin-right: 10px +} + +.form .form-group { + display: flex; + flex-direction: row; + margin-bottom: 10px; + margin-top: 10px; +} + +.form .error { + color: red; +} diff --git a/mail/src/test/java/org/jboss/as/quickstarts/mail/BasicRuntimeIT.java b/mail/src/test/java/org/jboss/as/quickstarts/mail/BasicRuntimeIT.java new file mode 100644 index 0000000000..7a0f2ce380 --- /dev/null +++ b/mail/src/test/java/org/jboss/as/quickstarts/mail/BasicRuntimeIT.java @@ -0,0 +1,59 @@ +/* + * Copyright 2022 JBoss by Red Hat. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jboss.as.quickstarts.mail; + +import org.junit.Test; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; + +import static org.junit.Assert.assertEquals; + +/** + * The very basic runtime integration testing. + * @author Emmanuel Hugonnet + * @author emartins + */ +public class BasicRuntimeIT { + + private static final String DEFAULT_SERVER_HOST = "http://localhost:8080/mail"; + + @Test + public void testHTTPEndpointIsAvailable() throws IOException, InterruptedException, URISyntaxException { + String serverHost = System.getenv("SERVER_HOST"); + if (serverHost == null) { + serverHost = System.getProperty("server.host"); + } + if (serverHost == null) { + serverHost = DEFAULT_SERVER_HOST; + } + final HttpRequest request = HttpRequest.newBuilder() + .uri(new URI(serverHost)) + .GET() + .build(); + final HttpClient client = HttpClient.newBuilder() + .followRedirects(HttpClient.Redirect.ALWAYS) + .connectTimeout(Duration.ofMinutes(1)) + .build(); + final HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + } +} diff --git a/mail/src/test/java/org/jboss/as/quickstarts/mail/MailTestCaseIT.java b/mail/src/test/java/org/jboss/as/quickstarts/mail/MailTestCaseIT.java new file mode 100644 index 0000000000..fde3fd784e --- /dev/null +++ b/mail/src/test/java/org/jboss/as/quickstarts/mail/MailTestCaseIT.java @@ -0,0 +1,143 @@ +package org.jboss.as.quickstarts.mail; + +import io.github.bonigarcia.wdm.WebDriverManager; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; +import org.openqa.selenium.By; +import org.openqa.selenium.StaleElementReferenceException; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.chrome.ChromeOptions; +import org.openqa.selenium.support.ui.Wait; +import org.openqa.selenium.support.ui.WebDriverWait; + +import java.time.Duration; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class MailTestCaseIT { + + private static final String DEFAULT_SERVER_HOST = "http://localhost:8080/mail"; + + private WebDriver driver; + + @Before + public void testSetup() { + WebDriverManager.chromedriver().setup(); + + ChromeOptions options = new ChromeOptions(); + options.addArguments("--no-sandbox"); + options.addArguments("--disable-dev-shm-usage"); + options.addArguments("--headless"); + + driver = new ChromeDriver(options); + driver.manage().window().maximize(); + + String serverHost = System.getenv("SERVER_HOST"); + if (serverHost == null) { + serverHost = System.getProperty("server.host"); + } + if (serverHost == null) { + serverHost = DEFAULT_SERVER_HOST; + } + + driver.get(serverHost); + driver.manage().timeouts().implicitlyWait(Duration.ofMillis(500)); + } + + @After + public void cleanUp() { + if (driver != null) { + driver.close(); + } + } + + @Test + public void a_testSMTP() { + Wait wait = new WebDriverWait(driver, Duration.ofSeconds(15)); + + WebElement from = driver.findElement(By.id("smtp_from")); + WebElement to = driver.findElement(By.id("smtp_to")); + WebElement subject = driver.findElement(By.id("smtp_subject")); + WebElement body = driver.findElement(By.id("smtp_body")); + + from.clear(); + from.sendKeys("user01@james.local"); + + to.clear(); + to.sendKeys("user02@james.local"); + + subject.clear(); + subject.sendKeys("This is a test"); + + body.clear(); + body.sendKeys("Hello user02, I've sent an email."); + + WebElement submitButton = driver.findElement(By.id("smtp_send_btn")); + submitButton.click(); + + WebElement message = driver.findElement(By.xpath("//ul[@id='smtp_messages']/li")); + wait.until(d -> message.isDisplayed()); + + Assert.assertEquals("Unexpected result messages after sending an email via SMTP.", "Email sent to user02@james.local", message.getText()); + } + + @Test + public void b_retrievePOP3() { + Wait wait = new WebDriverWait(driver, Duration.ofSeconds(15)); + + WebElement user = driver.findElement(By.id("pop3_user")); + WebElement password = driver.findElement(By.id("pop3_password")); + + user.clear(); + user.sendKeys("user02@james.local"); + + password.clear(); + password.sendKeys("1234"); + + WebElement submitButton = driver.findElement(By.id("pop3_get_emails_btn")); + submitButton.click(); + + wait.until(d -> { + try { + WebElement emails = driver.findElement(By.id("pop3_emails")); + return !emails.getText().isEmpty(); + } catch (StaleElementReferenceException sere) { + return false; + } + }); + + WebElement emails = driver.findElement(By.id("pop3_emails")); + Assert.assertTrue("Expected From not found: " + emails.getText(), emails.getText().contains("From : user01@james.local")); + Assert.assertTrue("Expected Subject not found: " + emails.getText(), emails.getText().contains("Subject : This is a test")); + Assert.assertTrue("Expected Body not found : " + emails.getText(), emails.getText().contains("Body : Hello user02, I've sent an email.")); + } + + + @Test + public void c_retrieveIMAP() { + Wait wait = new WebDriverWait(driver, Duration.ofSeconds(15)); + + WebElement submitButton = driver.findElement(By.id("imap_get_emails_btn")); + submitButton.click(); + + wait.until(d -> { + try { + WebElement emails = driver.findElement(By.id("imap_emails")); + return !emails.getText().isEmpty(); + } catch (StaleElementReferenceException sere) { + return false; + } + }); + + WebElement emails = driver.findElement(By.id("imap_emails")); + Assert.assertNotNull("IMAP No messages found.", emails.getText()); + Assert.assertTrue("Expected email not found.", emails.getText().contains("From : user01@james.local")); + Assert.assertTrue("Expected email not found.", emails.getText().contains("Subject : This is a test")); + Assert.assertTrue("Expected email not found.", emails.getText().contains("Body : Hello user02, I've sent an email.")); + } +}