Summary |
Discusses how to create a custom email service for Adobe Experience Manager by using the Java Mail API. In addition, discusses how to style the web client and invoke the custom email service operation. |
Digital Marketing Solution(s) | Adobe Experience Manager (Adobe CQ) |
Audience |
Developer (intermediate) |
Required Skills |
Java, JQuery, SMTP, CSS |
Tested On | Adobe Experience Managerr 5.5, 5.6 |
You can create a custom Adobe Experience Manager email service that lets users send email messages from an Experience Manager web page. To create an Experience Manager email service, you develop an OSGi bundle that uses the Java Mail API. You can also develop a JSP that uses JQuery to call the OSGi service and pass data sent as an email message.

The Java Mail API is used in the OSGi bundle that sends email messages when the client initiates a request. The email application consists of a client developed by using JQuery (shown in the previous illustration) and an OSGi bundle.
Note:
Before following these steps, install Adobe Experience Manager and have it running. In addition, ensure that you have Eclipse 3.6.1 or later. You use Eclipse to create the OSGi bundle that contains the Java Mail API.
Your first step is to create an application folder structure that contains templates, components, and pages by using CRXDE Lite.

- Application name folder: Contains all of the resources that an application uses. The resources can be templates, pages, components, and so on.
- components folder: Contains components that your application uses.
- page folder: Contains page components. A page component is a script such as a JSP file.
- global: Contains global components that your application uses.
- template folder: Contains templates on which you can base page components.
- src folder: Contains source code that defines an OSGi component.
- install folder: Contains a compiled OSGi bundles container.
This illustration shows the folder structure that is created for this Experience Manager application. Notice that the application name is emailapp.

- Go to the welcome page at http://[host name]:[port]; for example, http://localhost:4502.
- Select CRXDE Lite.
- Right-click the apps folder (or the parent folder), select Create, Create Folder.
- Enter the folder name emailapp into the Create Folder dialog box.
- Repeat steps 1-4 for each folder specified in the previous illustration.
- Click Save All.
Note:
Your changes won’t be applied until you click the Save All button.
Using CRXDE Lite, create a template that defines a consistent style for the pages in your application. A template consists of nodes that specify the page structure. For more information about templates, see Templates.
1. Go to the welcome page at http://[host name]:[port]; for example, http://localhost:4502.
2. Select CRXDE Lite.
3. Right-click the template folder (within your application), then select Create, Create Template.
4. Enter the following information into the Create Template dialog box:
- Label: The name of the template to create. Enter emailtemplate.
- Title: The title that is assigned to the template
- Description: The description that is assigned to the template
- Resource Type: The component's path that is assigned to the template and copied to implementing pages. Enter emailapp/components/page/emailtemplate.
- Ranking: The order (ascending) in which this template appears in relation to other templates. Setting this value to 1 ensures that the template appears first in the list.
5. Add a path to Allowed Paths. Click on the plus sign and enter the following value: /content(/.*)?.
6. Click Next for Allowed Parents.
7. Select OK on Allowed Children.
Components are re-usable modules that implement specific application logic to render the content of your web site. You can think of a component as a collection of scripts (for example, JSPs, Java servlets, and so on) that completely realize a specific function. In order to realize this functionality, it is your responsibility as an Experience Manager developer to create scripts that perform specific functionality. For more information, see Components.
1. Go to the welcome page at http://[host name]:[port]; for example, http://localhost:4502.
2. Select CRXDE Lite.
3. Right-click /apps/emailapp/components/page, then select Create, Create Component.
4. Enter the following information into the Create Component dialog box:
- Label: The name of the component. Enter emailtemplate.
- Title: The title that is assigned to the component
- Description: The description that is assigned to the template
- Super Type: foundation/components/page
5. Select Next for Advanced Component Settings and Allowed Parents.
6. Select OK on Allowed Children.
7. Open the emailtemplate.jps located at: /apps/emailapp/components/page/emailtemplate/emailtemplate.jsp.
8. Enter the following HTML code:
<html> <head> <title>Hello World !!!</title> </head> <body> <h1>Email client</h1> <h2>This page will contain an email client </h2> </body> </html>
Note:
This code will be modified in a later step.
You add two CSS files and two JQuery framework files to a cq:ClientLibraryFolder node to define the style of the client JSP. The two JQuery framework files that are required are: jquery-1.6.3.min.js and jquery.loadmask.min.js.
Note:
For more information about using JQuery with Experience Manager, see Integrating the JQuery Framework into Experience Manager.
To add CSS files and the JQuery framework to your component, add a cq:ClientLibraryFolder node to your component. After you create the node, set properties that allow the JSP script to find the CSS files and the JQuery library files.
To add the JQuery framework, add a new node named clientlibs to your component (as discussed later). Add these two properties to this node.
The dependencies property informs Experience Manager to include the CSS and JQuery libraries in the page. The categories property informs Experience Manager which clientlibs must be included.
After you create the Clientlibs folder, add both CSS files, both JQuery library files, and two map text files.

The site.css file is the main CSS file that defines the display style for the JSP (the site.css code is shown in the next section). Add jquery.loadmask.css (the code for this file is also shown in the next section) to the clientlibs folder by following the instructions below.
The site.css file defines the display style for the JSP file that lets the user send email messages. The following code represents the site.css file.
/* reset */ html, body, div, span, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td { margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; } html , body{ line-height: 1; background-color: #334873; background-image: url(../_images/bg-page2.png); } ol, ul { list-style: none; } table { border-collapse: collapse; border-spacing: 0; } /* end reset*/ h1, h2, h3 { font-family: 'ColaborateRegular', Arial, sans-serif; } strong { font-family: 'ColaborateMediumRegular', Arial, sans-serif; } em { font-family: 'ColaborateThinRegular', Arial, sans-serif; } .content { max-width: 760px; margin: 20px 0 0 100px; } .clear:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } .clear { min-height: 1px; } * html .clear { height: 1px; } .header { position: relative; border-top: solid 6px white; padding: 10px 0 10px 0; margin-bottom: 20px; } .main { xxposition: relative; padding-bottom: 1em; border-bottom: solid 1px rgba(255,255,255,.5); xxoverflow:hidden; xxmin-height: 300px; } .main h1 { font-size: 32px; color: white; text-shadow: 1px 1px 1px rgba(0,0,0,.75); border-bottom: solid 1px rgba(255,255,255,.5); margin-bottom: 0.75em; } p , li, legend , form{ font-size: 18px; color: white; font-family: 'ColaborateLightRegular', Arial, sans-serif; line-height: 125%; margin-bottom: 10px; } fieldset { padding: 10px; border: 1px solid white; margin: 25px 0; } .nav { margin: 10px 0 0 100px; } .nav li { display: inline-block; } .nav a:hover, .example:hover{ background-color: rgba(255,255,255,.85); color: rgb(0,0,0); } h3 { font-size: 18px; color: rgb(227,198,133);; } .results h2 { color: rgba(255,255,255,1); } .results div { padding-bottom: 10px; } .results div code { float: right; width: 60%; } input { font-size: 20px; } .form .wide { font-size: 18px; width: 100%; } .resultSection { float: right; width: 45%; margin-left: 20px; } #regexTester { margin-right: 55%; } .sideBySide li { float: left; overflow: hidden; width: 220px; } .clickable { cursor:pointer; margin-bottom: 5px; } .clickable:hover { background-color:#FFC; } .col1 { float: left; width: 75%; } .col2 { float: right; width: 20%; } .col2 ul { margin-left: 20px; list-style: square; } .col2 li { font-size: 90%; } #selectorList { overflow: hidden; } #selector { width: 275px; } form#signup .label { width: 200px; }
The other CSS file defines the JQuery mask effect. The following code represents the jquery.loadmask.css file.
.loadmask { z-index: 100; position: absolute; top:0; left:0; -moz-opacity: 0.5; opacity: .50; filter: alpha(opacity=50); background-color: #CCC; width: 100%; height: 100%; zoom: 1; } .loadmask-msg { z-index: 20001; position: absolute; top: 0; left: 0; border:1px solid #6593cf; background: #c3daf9; padding:2px; } .loadmask-msg div { padding:5px 10px 5px 25px; background: #fbfbfb url('images/loading.gif') no-repeat 5px 5px; line-height: 16px; border:1px solid #a3bad9; color:#222; font:normal 11px tahoma, arial, helvetica, sans-serif; cursor:wait; } .masked { overflow: hidden !important; } .masked-relative { position: relative !important; } .masked-hidden { visibility: hidden !important; }
You have to add two text files to the clientlibs folder. These text files map to the JS files and the CSS files. The names of the text files are: css.txt and js.txt.
The css.txt file contains the two CSS file names:
- site.css
- jquery.loadmask.css
The js.txt file contains the two JS file names:
- jquery-1.6.3.min.js
- jquery.loadmask.min.js
- Right-click /apps/emailapp/components then select New, Node.
- Make sure that the node type is cq:ClientLibraryFolder and name the node clientlibs.
- Right click on clientlibs and select Properties. Add the two properties specified in the previous table to the node.
- On your file system, navigate to the folder where the JQuery JS files are located. Drag and drop the jquery-1.6.3.min.js and jquery.loadmask.min.js files to the clientlibs node by using CRXDE.
- On your file system, navigate where you placed the CSS files. Drag and drop the jquery.loadmask.css and site.css files to the clientlibs folder by using CRXDE.
- Add a TXT file to the clientlibs folder named js.txt. The content of the js.txt file are the JQuery JS file names (the content of this file is shown earlier).
- Add a TXT file to the clientlibs node named css.txt. The content of the css.txt file are the CSS file names (the content of this file is shown earlier).
Create an Eclipse project that creates a Java class that uses the Java Mail API and is able to send email messages. The version of Eclipse that is supported is 3.6.1 or later (this version of Eclipse is used to create a bundle as described in the next step).
Add the Java Mail JAR file to your Eclipse project’s class path. The Java class that is created is named CustomEmailService. The following Java code represents this class. Notice that this class is located in a Java package named com.adobe.cq.sample.email.
package com.adobe.cq.sample.email; import java.util.Properties; import javax.mail.Message; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; public class CustomEmailService { //Specify data members for the EmailServiceImpl //These members correspond to configuration values protected String m_smtpHost; protected String m_smtpUser; protected String m_smtpPassword; //Send the email. public void send(String aHost, String ToAddress, String aSubject, String aMessage ) { try { // Recipient's email ID needs to be mentioned. String to = ToAddress; // Sender's email ID needs to be mentioned String from = "<valid sender email address>"; // Get system properties Properties properties = System.getProperties(); // Setup mail server (Depending upon your // Mail server - you may need more props here properties.setProperty("mail.smtp.host", aHost); properties.setProperty("mail.smtp.user", "<valid SMTP user>"); // Get the default Session object. Session session = Session.getDefaultInstance(properties); // Create a default MimeMessage object. MimeMessage message = new MimeMessage(session); // Set From: header field of the header. message.setFrom(new InternetAddress(from)); // Set To: header field of the header. message.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); // Set Subject: header field message.setSubject(aSubject); // Now set the actual message message.setText(aMessage); // Send message Transport.send(message); System.out.println("Sent message successfully...."); } catch (Exception ex) { ex.printStackTrace(); } } //check If passed in string contains only non whitespace public static boolean isEmpty(String aValue) { return (aValue == null || aValue.trim().length() == 0); } }
Note:
Replace <valid sender email address> with a valid email account and <valid SMTP user> with a valid SMTP user for the Mail Server you use. Also note that depending on your mail server, you may have to use additional properties than shown in this code. For example, if you are using GMail Server, you will have to use authentication. Always test your Mail code in a Java IDE before using the code in Adobe Experience Manager. Once you know the code works, use it in the Send method.
After you create this class, export the eclipse project as a JAR file. This JAR file is placed into the OSGi bundle that is deployed to Experience Manager. The email client application invokes the send method of the CustomEmailService class.
- Create an Eclipse Java project and name the project CQEmailProject.
- Add the Java Mail JAR file to your Eclipse project’s class path.
- Add a new Java class named CustomEmailService to your project. Add the Java code specified in this section to this class.
- Compile and build your Java project.
- Export the project to a Java JAR named CQJavaMail.jar. (This JAR file is bundled into an OSGi bundle in the next step.)
Create an OSGi bundle that contains the CQJavaMail.jar file. After you upload the OSGi bundle to Experience Manager, you can call the send method of the CustomEmailService class. To create the OSGi bundle, you use another Eclipse project that creates an OSGi bundle. An OSGi bundle is essentially a collection of Java files and a MANIFEST.MF file.
Note:
It is unnecessary to include the Java Mail API in the OSGi service container. These classes are already part of the service container. The only class that the OSGi bundle contains is the CustomEmailService class.
1. Start Eclipse (Indigo). The steps below have been tested on Eclipse Java EE IDE for Web Developers version Indigo Service Release 1.
2. Select File, New, Other.
3. Under the Plug-in Development folder, choose Plug-in from Existing JAR Archives. Name your project CQMailBundle.
4. In the JAR selection dialog, click the Add external button, and browse to the CQJavaMail.jar file that you created in the previous step.
5. Click Next.
6. In the Plug-in Project properties dialog, ensure that you check the checkbox for Analyze library contents and add dependencies (see the following illustration).
7. Make sure that the Target Platform is the standard OSGi framework (see the following illustration).
8. Ensure the checkboxes for Unzip the JAR archives into the project and Update references to the JAR files are both checked (see the following illustration).

9. Click Next, and then Finish.
10. Click the Runtime tab.
11. Make sure that the Exported Packages list is populated.
12. Make sure these packages have been added under the Export-Package header in MANIFEST.MF. Remove the version information in the MANIFEST.MF file. Version numbers can cause conflicts when you upload the OSGi bundle.
13. Also make sure that the Import-Package header in MANIFEST.MF is also populated, as shown here.
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: CQMail5 Bundle-SymbolicName: CQMailBundle Bundle-Version: 1.0.0 Export-Package: com.adobe.cq.sample.email Import-Package: javax.mail, javax.mail.internet Bundle-RequiredExecutionEnvironment: JavaSE-1.6
14. Save the project.
15. Build the OSGi bundle by right-clicking the project in the left pane, choose Export, Plug-in Development, Deployable plug-ins and fragments, and click Next.
16. Select a location for the export (C:\TEMP) and click Finish. (Ignore any error messages).
17. In C:\TEMP\plugins, you should now find the OSGi bundle.
18. Login to Apache Felix Web Console at http://server:port/system/console/bundles (default admin user = admin with password= admin).
19. Sort the bundle list by Id and note the Id of the last bundle.
20. Click the Install/Update button.
21. Check the Start Bundle checkbox.
22. Browse to the bundle JAR file you just built. (C:\TEMP\plugins).
23. Click Install.
24. Click the Refresh Packages button.
25. Check the bundle with the highest Id.
26. Your new bundle should now be listed with the status Active.
27. If the status is not Active, check the CQ error.log for exceptions. If you get “org.osgi.framework.BundleException: Unresolved constraint” errors, check the MANIFEST.MF for strict version requirements which might follow: javax.xml.namespace; version=”3.1.0”
28. If the version requirement causes problems, remove it so that the entry looks like this: javax.xml.namespace.
29. If the entry is not required, remove it entirely.
30. Rebuild the bundle
31. Delete the previous bundle and deploy the new one
32. If all goes well, the CQ error.log should have log entries such as follows:
*INFO* [FelixDispatchQueue] com.oracle.jdbc BundleEvent INSTALLED *INFO* [FelixDispatchQueue] com.oracle.jdbc BundleEvent RESOLVED *INFO* [FelixDispatchQueue] com.oracle.jdbc BundleEvent STARTED *INFO* [FelixDispatchQueue] org.apache.felix.framework FrameworkEvent PACKAGES REFRESHED

You can view details, such as the Java packages that are part of the OSGi bundle. For example, notice that the com.adobe.cq.sample.email package is specified in the previous illustration. (Step 18 in the previous procedure described how to login to the Apache Felix Web Console.)
- email2.json.jsp: Contains application logic that calls the OSGI bundle’s send operation.
- emailtemplate.jsp: Contains application logic that defines the JSP that lets a user enter and send email message information.
Note:
The emailtemplate.jsp file was created in an earlier step; however, in this step, you enter new JavaScript code.
In email2.json.jsp, create an CustomEmailService instance and call its send method. Pass the following values to the send method:
- A string value that specifies the email server
- A string value that specifies the email account to which the email message is sent
- A string value that specifies the subject
- A string value that specifies the message body
The CustomEmailService class is defined in the deployed OSGi bunlde. To successfully create this instance, ensure that you specify the following page import statement:
page import="org.apache.sling.commons.json.io.*,com.adobe.cq.sample.email.*"
<%@ page import="org.apache.sling.commons.json.io.*,com.adobe.cq.sample.email.*" %><% String server = request.getParameter("server"); String toAddress = request.getParameter("to"); String subject = request.getParameter("subject"); String message = request.getParameter("message"); //Send the email message CustomEmailService mailService = new CustomEmailService(); mailService.send(server,toAddress,subject, message); %>
Modify the emailtemplate.jsp file to call the email2.json.jsp when the submit button is clicked. This code shows the JSON related code.
('#submit').click(function() { var failure = function(err) { $(".main").unmask(); alert("Unable to retrive data "+err); }; //Get the email message data var server = $('#host').val() ; var to = $('#toAddress').val() ; var subject = $('#subject').val() ; var message = $('#message').val() ; var url = location.pathname.replace(".html", "/_jcr_content.email2.json") + "?to="+ to +"&server="+server +"&subject="+subject +"&message="+message; $(".main").mask("Sending..."); $.ajax(url, { dataType: "text", success: function(rawData, status, xhr) { try { $(".main").unmask(); $('#toAddress').val(''); $('#subject').val(''); $('#message').val(''); $('#popup').show(); $('#popup').fadeOut(5000); } catch(err) { failure(err); } }, error: function(xhr, status, err) { failure(err); } });
<%@include file="/libs/foundation/global.jsp"%> <cq:includeClientLib categories="jquerysamples" /> <html> <head> <meta charset="UTF-8"> <title>CQ Email Form</title> <style> #signup .indent label.error { margin-left: 0; } #signup label.error { font-size: 0.8em; color: #F00; font-weight: bold; display: block; margin-left: 215px; } #signup input.error, #signup select.error { background: #FFA9B8; border: 1px solid red; } </style> <script> $(document).ready(function() { $('body').hide().fadeIn(5000); $('#submit').click(function() { var failure = function(err) { $(".main").unmask(); alert("Unable to retrive data "+err); // TODO - clear the form }; //Get the values to pass to the Mail OSGi bundle var server = $('#host').val() ; var to = $('#toAddress').val() ; var subject = $('#subject').val() ; var message = $('#message').val() ; var url = location.pathname.replace(".html", "/_jcr_content.email2.json") + "?to="+ to +"&server="+server +"&subject="+subject +"&message="+message; $(".main").mask("Sending..."); $.ajax(url, { dataType: "text", success: function(rawData, status, xhr) { try { $(".main").unmask(); $('#toAddress').val(''); $('#subject').val(''); $('#message').val(''); $('#popup').show(); $('#popup').fadeOut(5000); } catch(err) { failure(err); } }, error: function(xhr, status, err) { failure(err); } }); }); }); // end ready </script> </head> <body> <div class="wrapper"> <div class="header"> <p class="logo">Adobe CQ Email Client</p> </div> <div class="content"> <div class="main"> <h1>CQ Email Service Example</h1> <form name="signup" id="signup"> <table> <tr> <td> <label for="host" class="label">Email Server:</label> </td> <td> <input name="host" value="mymailServer.com"type="text" id="host" > </td> </tr> <tr> <td> <label for="toAddress" class="label">To:</label> </td> <td> <input name="toAddress" type="text" id="toAddress" > </td> </tr> <tr> <td> <label for=subject class="label">Subject:</label> </td> <td> <input name="subject" type="text" id="subject" > </td> </tr> <tr> <td> <label for="message" class="label">Message:</label> </td> <td> <textarea rows="3" cols="40" id="message"> </textarea> </td> </tr> <tr> <td> <input type="button" value="Click me!" name="submit" id="submit" value="Submit"> </td> <td> <div style="display:none" id="popup"> <h3 display=false backgroundcolor="#8B8989"> email was successfully sent</h3> </div> </td> </tr> </table> </form> </div> </div> </div> </body> </html>
Notice this line at the top of the JSP:
<cq:includeClientLib categories="jquerysamples" />
Notice the value of the categories attribute. This maps to the property that was added to the clientlibs node. This is how CQ locates the JQuery framework and the CSS files.
- To view the CQ welcome page, enter the URL: http://[host name]:[port] into a web browser. For example, http://localhost:4502.
- Select CRXDE Lite.
- Double-click apps/emailapp/components/page/emailtemplate/emailtemplate.jsp.
- Replace the JSP code with the new code shown in this section.
- Click Save All.
The final task is to create a site that contains a page that is based on the emailtemplate (the template created earlier in this development article).
- Go to the welcome page at http://[host name]:[port]; for example, http://localhost:4502.
- Select Websites.
- From the left hand pane, select Websites.
- Select New Page.
- Specify the title of the page in the Title field.
- Specify the name of the page in the Name field.
- Select emailtemplate from the template list that appears. This value represents the template that is created in this development article. If you do not see it, then repeat the steps in this development article. For example, if you made a typing mistake when entering in path information, the template will not show up in the New Page dialog box.
- Open the new page that you created by double-clicking it in the right pane. The new page opens in a web browser. You should see a page similar to the illustration located at the beginning of this article.