17 Replies Latest reply on May 10, 2013 9:33 AM by iyer.s

    Send Email Using CQ API and custom template

    ravindrareddydr Level 1

      Is is possible to send email using CQ API and custom template.

       

      If yes how can i pass template as Subject

       

      http://blogs.adobe.com/learningwem/2011/11/27/cq5-4-workflow-process-to-send-an-email-usin g-messagegateway/

       

      I was followed this and able send email to the recipients .

       

      But is it possible to send email CQ APi and custome email template ?

       

      I was tried this using workflow process

      ................................................................................

      public class SendEmailWorkflowProcess implements WorkflowProcess {

       

          @Reference

                 private MessageGatewayService messageGatewayService;

         

          public void execute(WorkItem item, WorkflowSession wfsession,MetaDataMap metaData) throws WorkflowException {

       

       

                    HtmlEmail email = new HtmlEmail();

       

               try{

                     .......................

                     ...................

                     email.setTo( emailRecipients );

                    email.setSubject( "This is subject");

                    email.setHtmlMsg( "Email testing is on");

       

                    String template = "/apps/cq/workflow/email/test/en.txt";

                    Session session = wfsession.getSession();

       

                    Resource templateRsrc = jcrResolverFactory.getResourceResolver(session).getResource(template);

       

                    if (templateRsrc.getChild("file") != null) {

                       templateRsrc = templateRsrc.getChild("file");

                    }

                    if (templateRsrc == null) {

                       throw new IllegalArgumentException("Missing template:---------- " + template);

                    }

                   

                    final MailTemplate mailTemplate = MailTemplate.create(templateRsrc.getPath(),

                            templateRsrc.getResourceResolver().adaptTo(Session.class));

                 

                              email = mailTemplate.getEmail(StrLookup.lookup(properties,HtmlEmail.class));

            

                    //Check the logs to see that messageGatewayService is not null

                    log.info("messageGatewayService : " + messageGatewayService);

       

       

                    messageGateway = messageGatewayService.getGateway(HtmlEmail.class);

       

       

                    //Check the logs to see that messageGateway is not null

                    log.info("messageGateway : " + messageGateway);

       

       

                    messageGateway.send( email );

                   }

                catch ( Exception e ) {

                    e.printStackTrace();

                    log.error( "Fatal error while sending email in workflow", e );

                }

       

       

           } 

       

       

          }

       

      ..............................................

       

      If this is correct procedure ,

       

      email = mailTemplate.getEmail(StrLookup.lookup(properties,HtmlEmail.class));

       

      what value required for " properties "(properties can't be resolved)

       

      All sugestions are accepted

        • 1. Re: Send Email Using CQ API and custom template
          rush_pawan Level 4

          Hi Ravinder,

           

          There are couple of things.

           

          1. The method call in your class is not correct. the call should be

          mailTemplate.getEmail(strLookup,email);

           

          email - is your templated object which you have created above

          strLookup - is object which lookups all variables which you have used in your template (/apps/cq/workflow/email/test/en.txt - a mail template txt file)

           

          so for example let say in en.txt you have used and varibale ${first} and ${second} then strLookup will be instantiated in such way so that these variables can be looked by the key name "first" or "second".

           

          2. to create StrLookup obejct use api http://commons.apache.org/lang/api-2.4/org/apache/commons/lang/text/StrLookup.html

           

          Example : you can use StrLookup.mapLookup(java.util.Map map) by creating a map object which will have all the variable you used in your templated (en.txt) - YOU ONLY NEED THIS OBJECT TO CREATE WITH KEY/VALUE IF YOU HAVE USED ANY VARIABLES IN TEMPLATE ELSE YOU CAN CREATE AN EMPTY LOOKUP OBJECT.

           

          i hope it clarifies your question and help you to proceed. Let me know for more information.


           

           

          Thanks,

          Pawan

          • 2. Re: Send Email Using CQ API and custom template
            ravindrareddydr Level 1

            Thanks for reply Pawan,

             

            I tried

             

            1)              String temp_path ="/apps/cq/workflow/email/test/en.txt";

                          final MailTemplate template = MailTemplate.create(temp_path, wfsession.getSession());

             

                          Map<String, Object> map;

                          map.put("payload.email", "test@gmail.com");

                          map.put("payload.fullname", "Tester");

                          map.put("payload.temppassword", "password");

                          map.put("properties", toString());

             

                         template.getEmail(StrLookup.mapLookup(map));

             

            I got below Complie error,

             

            DescriptionResourcePathLocation
            The method getEmail(StrLookup, Class<T>) in the type MailTemplate is not applicable for the arguments (StrLookup<Object>)SendEmailWorkflowProcess.java/localhost_4504_ac5d3318-9f30-49cb-a167-72a5ae819413/WebContent/apps/project/src/hrt/src/m ain/java/com/comline 97

            .......................................................................................... ...........

             

            2) Then i was also tried using

             

                            String temp_path ="/apps/cq/workflow/email/test/en.txt";

                          final MailTemplate template = MailTemplate.create(temp_path, wfsession.getSession());

                          log.info(email.getSmtpPort()+"----");

                          Map<String, Object> map;

             

                          map.put("payload.email", "test@gmail.com");

                          map.put("payload.fullname", "Tester");

                          map.put("payload.temppassword", "password");

                          map.put("properties", toString());

             

                          template.getEmail(StrLookup.mapLookup(map), HtmlEMail.class);

             

            Complie error

             

            DescriptionResourcePathLocation
            The method getEmail(StrLookup, Class<T>) in the type MailTemplate is not applicable for the arguments (StrLookup<Object>, Class<HtmlEmail>)SendEmailWorkflowProcess.java/localhost_4504_ac5d3318-9f30-49cb-a167-72a5ae819413/WebContent/apps/project1/src/hrt/src/ main/java/com/comline 97
            • 3. Re: Send Email Using CQ API and custom template
              Yogesh Upadhyay Level 4

              I see something like this working

               

              import org.apache.sling.api.resource.ValueMap;

              import org.apache.sling.api.wrappers.ValueMapDecorator;

               

               

              private static final StrLookup LOOKUP = new StrLookup() {

               

                      private final ValueMap PROPS = new ValueMapDecorator(new HashMap<String, Object>()) {{

                          put("email", SOMETHING);

                          put("fullname", SOMETHING);

                          put("temppassword", SOMETHING);

                          }};

               

                      public String lookup(final String key) {

                          return PROPS.get(key, String.class);

                      }

                  };

               

              final TestEmail email = template.getEmail(LOOKUP, TestEmail.class);

               

              Let me know if that works.

               

              Yogesh

              www.wemblog.com

              • 4. Re: Send Email Using CQ API and custom template
                rush_pawan Level 4

                Hello Ravindra,

                 

                I still see couple of problems in your code. Anyhow your error description is not sufficient to understand but based on code you sent providing comments

                 

                1. The first section will not work because there is no method with single argument template.getEmail(StrLookup.mapLookup(map));

                now about second method call  template.getEmail(StrLookup.mapLookup(map), HtmlEMail.class);  you should use "email" object type instead providing the typed class so use template.getEmail(StrLookup.mapLookup(map), email); as i saw you have already created an object "email" of type HtmlEmail.class above.

                 

                2. Not sure what you are trying to set here map.put("properties", toString()); and what "toString()" method is returning.  Please remember as per description of method "mapLookup(map)" the method will convert all the objects in "map" to string using toString(), so you have to make sure when you add data to map will be properly converted using "toString()" (this is implicit conversion by StrLookup class)

                 

                3. As it has already mentioned that "mapLookup(map)" method will automatically convert all the results object to string but i would still prefer if you are not adding any object to map (in case) to using map as <string, string>

                 

                so use Map <String, String> map=new HashMap<String,String>();

                 

                Please send any error with detail so that it will be easy visible also post your java class if required.

                 

                Thanks,

                Pawan

                • 6. Re: Send Email Using CQ API and custom template
                  ravindrareddydr Level 1

                  I am working with CQ 5.5

                   

                  public class SendEmailWorkflowProcess implements WorkflowProcess {

                        private static final Logger log = LoggerFactory.getLogger(SendEmailWorkflowProcess.class);

                        ArrayList<InternetAddress> emailRecipients = new ArrayList<InternetAddress>();

                   

                     @Reference

                             private MessageGateway<HtmlEmail> messageGateway;

                   

                     @Reference

                             private MessageGatewayService messageGatewayService;

                   

                  public void execute(WorkItem item, WorkflowSession wfsession,MetaDataMap metaData) throws WorkflowException {

                   

                                HtmlEmail email = new HtmlEmail();

                   

                           try{

                                    

                                    String instancePath = item.getWorkflow().getId();

                          Node instanceNode = JcrResourceUtil.createPath(instancePath+"/data/metaData", "nt:resource","nt:resource",            wfsession.getSession(), false);

                   

                        emailRecipients.add(new InternetAddress("Test@gmail.com") );

                   

                                email.setTo( emailRecipients );

                                email.setSubject( "Workflow notification : "+item.getWorkflow().getState());

                               

                                String temp_path ="/apps/cq/workflow/email/test/en.txt";

                                Map<String, String> map=new HashMap<String,String>();

                                final MailTemplate template = MailTemplate.create(temp_path, wfsession.getSession());

                                template.getEmail(StrLookup.mapLookup(map), email);

                               

                                messageGateway = messageGatewayService.getGateway(HtmlEmail.class);

                   

                                messageGateway.send( email );

                               }

                            catch ( Exception e ) {

                               log.error( "Exceptione block @@@ Send EMail workflow Process : ", e.getMessage());

                            }

                   

                   

                       }

                   

                      }

                   

                  ...................................

                   

                   

                  I am seeing still compilation issue

                   

                  COmpile Error

                  DescriptionResourcePathLocation
                  The method getEmail(StrLookup, Class<T>) in the type MailTemplate is not applicable for the arguments (StrLookup<String>, HtmlEmail)SendEmailWorkflowProcess.java/localhost_4504_ac5d3318-9f30-49cb-a167-72a5ae819413/WebContent/apps/hrt/src/hrt/src/main/ java/com/hrt/comline 92
                  • 7. Re: Send Email Using CQ API and custom template
                    rush_pawan Level 4

                    Hi Ravindra,

                     

                    I think you should be good with

                     

                    email = template.getEmail(StrLookup.mapLookup(map), HtmlEmail.class);

                     

                    messageGateway = messageGatewayService.getGateway(HtmlEmail.class);

                      messageGateway.send( email );

                     

                    as with above it looks good at my system. make sure you are using org.apache.commons.mail.HtmlEmail; as mentioned by yogesh too.

                     

                     

                    Thanks,

                    Pawan

                    • 8. Re: Send Email Using CQ API and custom template
                      djain5 Level 1

                      Try this.....

                       

                      import java.io.IOException;

                      import java.util.ArrayList;

                      import java.util.HashMap;

                      import java.util.Map;

                      import javax.jcr.Node;

                      import javax.jcr.PathNotFoundException;

                      import javax.jcr.RepositoryException;

                      import javax.jcr.Session;

                      import javax.mail.MessagingException;

                      import javax.mail.internet.AddressException;

                      import javax.mail.internet.InternetAddress;

                       

                      import com.day.cq.commons.mail.MailTemplate;

                      import com.day.cq.mailer.MessageGateway;

                      import com.day.cq.mailer.MessageGatewayService;

                       

                      import com.day.cq.workflow.WorkflowException;

                      import com.day.cq.workflow.WorkflowSession;

                      import com.day.cq.workflow.exec.WorkItem;

                      import com.day.cq.workflow.exec.WorkflowData;

                      import com.day.cq.workflow.exec.WorkflowProcess;

                      import com.day.cq.workflow.metadata.MetaDataMap;

                       

                      import org.apache.commons.lang.text.StrLookup;

                      import org.apache.commons.mail.EmailException;

                      import org.apache.commons.mail.HtmlEmail;

                      import org.apache.felix.scr.annotations.*;

                      import org.apache.sling.api.resource.LoginException;

                      import org.apache.sling.api.resource.Resource;

                      import org.apache.sling.api.resource.ResourceResolverFactory;

                      import org.osgi.framework.BundleContext;

                      import org.osgi.framework.Constants;

                      import org.osgi.framework.FrameworkUtil;

                      import org.osgi.framework.ServiceReference;

                      import org.slf4j.Logger;

                      import org.slf4j.LoggerFactory;

                       

                      @Component

                      @Service

                      @Properties({

                              @Property(name = Constants.SERVICE_DESCRIPTION, value = "Workflow process to Send Html Email to end User."),

                              @Property(name = Constants.SERVICE_VENDOR, value = "Adobe"),

                              @Property(name = "process.label", value = "Send HTML Email Process")})

                      public class SendHTMLEmailProcess implements WorkflowProcess{

                       

                           /**

                           * Workflow JCR_PATH.

                           */

                          private static final String TYPE_JCR_PATH = "JCR_PATH";

                          /**

                           * Logger.

                           */

                          private static final Logger LOG = LoggerFactory.getLogger(SendHTMLEmailProcess.class);

                       

                          ArrayList<InternetAddress> emailRecipients = new ArrayList<InternetAddress>();

                       

                          @Reference

                          private MessageGatewayService messageGatewayService;

                       

                          @Reference

                          private MessageGateway<HtmlEmail> messageGateway;

                       

                       

                             @Override

                          public void execute(WorkItem item, WorkflowSession session, MetaDataMap args)

                                  throws WorkflowException {

                              ResourceResolverFactory serviceRef;

                              BundleContext bundleContext = FrameworkUtil.getBundle(ResourceResolverFactory.class).getBundleContext();

                              ServiceReference osgiRef = bundleContext.getServiceReference(ResourceResolverFactory.class.getName());

                              serviceRef = (ResourceResolverFactory) bundleContext.getService(osgiRef);

                              Resource templateRsrc;

                              Map<String, String> mailTokens = new HashMap<String, String>();

                              mailTokens.put("Subject", "Welcome ");

                              HtmlEmail email = new HtmlEmail();

                               WorkflowData workflowData = item.getWorkflowData();

                               if (workflowData.getPayloadType().equals(TYPE_JCR_PATH)) {

                                      String path = workflowData.getPayload().toString().trim();

                       

                                      try {

                                          Session jcrSession = session.getSession();

                                          Node node = (Node) session.getSession().getItem(path);

                                          templateRsrc = serviceRef.getAdministrativeResourceResolver(null).getResource("/etc/workflow/email");

                                         LOG.info("templateRsrc ---------------- : " + templateRsrc );

                                        if(node.hasProperty("state")){

                                           templateRsrc = templateRsrc.getChild("approve.html");

                                        }

                       

                                             final MailTemplate mailTemplate = MailTemplate.create(templateRsrc.getPath(), templateRsrc.getResourceResolver().adaptTo(Session.class));

                       

                                     //Get data from payload Node

                                          String sendTo= node.getProperty("Email").getValue().getString();

                                          String recipientName= node.getProperty("Fname").getValue().getString();

                                          String comment = node.getProperty("comment").getValue().getString();

                                     //set data in map

                                          mailTokens.put("comment", comment);

                                          mailTokens.put("contactName", recipientName);

                       

                                          emailRecipients.add(new InternetAddress(sendTo) );

                                         email = mailTemplate.getEmail(StrLookup.mapLookup(mailTokens),HtmlEmail.class);

                                         email.setTo( emailRecipients );

                       

                       

                                         messageGateway = this.messageGatewayService.getGateway(HtmlEmail.class);

                       

                       

                                          messageGateway.send(email);

                                         jcrSession.save();

                                      }catch (AddressException e) {

                       

                                          e.printStackTrace();

                       

                                      }catch (MessagingException e) {

                                          // TODO Auto-generated catch block

                                          e.printStackTrace();

                                      } catch (EmailException e) {

                                          // TODO Auto-generated catch block

                                          e.printStackTrace();

                                      }

                               }

                       

                          } 

                       

                       

                          }

                       

                       

                       

                      In html email access them like 

                       

                      <td align="left" valign="top" style="font-family: arial, verdana; font-size: 12px; color: #ffffff;">

                                                  <span style="font-size: 15px; font-weight: bold;">Dear ${contactName} ,</span><br/><br/>

                      </td>

                      • 9. Re: Send Email Using CQ API and custom template
                        djain5 Level 1

                        Hi,

                         

                        I am also doing same work..

                        I am able to send html email using crxde deployment.

                        But when i am doingmaven build,

                        its giving null pointer exception at

                        messageGateway = messageGatewayService.getGateway(HtmlEmail.class);

                         

                        Any pointer ,what i am missing?

                        My Complete Code is on above post..

                         

                        Thanks

                        Deepika

                        • 10. Re: Send Email Using CQ API and custom template
                          rush_pawan Level 4

                          Hello,


                          If you are getting nullpointer at messageGateway = messageGatewayService.getGateway(HtmlEmail.class); then the reason is "messageGatewayService" is not referenced from sling service registry when you referenced above in your class

                           

                          @Reference

                              private MessageGatewayService messageGatewayService;

                           

                          To check whether messageGatewayService is available or not you can do it in two ways.

                           

                          1. try to access service in your scriptlet using below code

                               MessageGatewayService msgservice=sling.getService(MessageGatewayService.class);

                           

                          2. Or login to felix console http://<host>:<port>/system/console

                               i. go to "services" tab and search "MessageGatewayService" whether this service is deployed or not

                               ii. now go to "component" tab and search for "CqMailingService" to see whether the service registered and active or not.

                           

                           

                          Thanks,

                          Pawan

                          • 11. Re: Send Email Using CQ API and custom template
                            djain5 Level 1

                            Hi Pawan,

                             

                            In java process, how to get sling service?

                             

                            I checked felix settings...both services and component..Both are there in depolyed and active state.

                             

                            [com.day.cq.mailer.MailingService, com.day.cq.mailer.MessageGatewayService]

                            component.id287
                            component.namecom.day.cq.mailer.impl.CqMailingService
                            mailer.status.rootPath/var/mailer/status
                            Service DescriptionDay CQ Mailer Service
                            Service PIDcom.day.cq.mailer.impl.CqMailingService
                            Service VendorDay Management AG
                            Using Bundlesdummy (260)
                            com.sr.cq5.sr-services (277)
                            com.day.cq.mcm.cq-mcm-core (206)

                            and another serivce messagegateway is also deploy([com.day.cq.mailer.MailService, com.day.cq.mailer.MessageGateway]) and have all required properties.

                             

                             

                            com.day.cq.mailer.impl.CqMailingService

                            Bundlecom.day.cq.cq-mailer (171)
                            Implementation Classcom.day.cq.mailer.impl.CqMailingService
                            Default Stateenabled
                            Activationdelayed
                            Configuration Policyoptional
                            Service Typeservice
                            Servicescom.day.cq.mailer.MailingService
                            com.day.cq.mailer.MessageGatewayService
                            Reference mailingGateway["Satisfied","Service Name: com.day.cq.mailer.MessageGateway","Multiple: multiple","Optional: optional","Policy: dynamic","Bound Service ID 425 (com.day.cq.mailer.DefaultMailService)"]
                            Reference repository["Satisfied","Service Name: org.apache.sling.jcr.api.SlingRepository","Multiple: single","Optional: mandatory","Policy: static","Bound Service ID 77 (Adobe CRX Repository)"]
                            Propertiescomponent.id = 287
                            component.name = com.day.cq.mailer.impl.CqMailingService
                            mailer.status.rootPath = /var/mailer/status
                            service.description = Day CQ Mailer Service
                            service.pid = com.day.cq.mailer.impl.CqMailingService
                            service.vendor = Day Management AG
                            • 12. Re: Send Email Using CQ API and custom template
                              rush_pawan Level 4

                              Hello Deepika,

                               

                              Not sure why you are still getting nullpointer exception, it would be good if you share the logs (error.log). Now here are couple of things to consider.

                               

                              1. You mentioned the code works when you you deploy using crxde but it does not when you deploy using maven

                                    - Make sure when you deploy using maven the bundle deploy correctly because you have to add "cq-mailer-5.5.0.jar" dependency to you pom.xml as below

                              <dependency>

                                          <groupId>com.day.cq</groupId>

                                          <artifactId>cq-mailer</artifactId>

                                          <version>5.5.0</version>

                                          <scope>provided</scope>

                                      </dependency>

                               

                              2.I not sure why you are referencing "messageGateway" using below step (its service which will automatically take reference from service registry when you mentioned @Reference)

                              @Reference

                                  private MessageGateway<HtmlEmail> messageGateway;

                               

                              as you are again initializing it through step messageGateway = this.messageGatewayService.getGateway(HtmlEmail.class);

                               

                              I would suggest to try one way either through reference or through initializing through code.

                               

                              Please do above and if even it does not work then share error from error.log


                              Thanks,

                              Pawan

                              • 13. Re: Send Email Using CQ API and custom template
                                djain5 Level 1

                                Thanks pawan,

                                 

                                Cq-mailer dependendency is already added in same way that you suggested.

                                Also,I just tried referrencing messageGateway through "@Referrence" just to see if it can work.

                                I tried after removing that as well.But same error occured.

                                 

                                fooling are the error:

                                 

                                04.12.2012 09:01:01.972 *ERROR* [JobHandler: /etc/workflow/instances/2012-12-04/model_2156240184633857:/content/usergenerated/content/ sr/en/rugbyforce/clubregistration/cq-gen1350274637321/1354173393932_1] com.day.cq.workflow.impl.job.JobHandler Process execution resulted in an error: null java.lang.NullPointerException

                                    at com.sr.cq5.workflows.SendHTMLEmailProcess.execute(SendHTMLEmailProcess.java:123)

                                    at com.day.cq.workflow.impl.job.HandlerBase.executeProcess(HandlerBase.java:184)

                                    at com.day.cq.workflow.impl.job.JobHandler.process(JobHandler.java:112)

                                    at org.apache.sling.event.jobs.JobUtil$1.run(JobUtil.java:272)

                                    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)

                                    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

                                    at java.lang.Thread.run(Unknown Source)

                                04.12.2012 09:01:01.972 *ERROR* [JobHandler: /etc/workflow/instances/2012-12-04/model_2156240184633857:/content/usergenerated/content/ sr/en/rugbyforce/clubregistration/cq-gen1350274637321/1354173393932_1] com.day.cq.workflow.impl.job.JobHandler Process execution resulted in an error: null

                                 

                                 

                                where line number 123 is :   messageGateway.send(email);

                                 

                                also in LOGS :for this  : LOG.info("messageGateway---------------- : " + messageGateway);

                                2012-12-05 10:22:24.438 INFO [com.sr.cq5.workflows.SendHTMLEmailProcess] messageGateway---------------- : null

                                 

                                Regards

                                Deepika

                                • 14. Re: Send Email Using CQ API and custom template
                                  Yogesh Upadhyay Level 4

                                  Strage that it is not working with Maven but working with CRXDE. I would suggest to open a daycare ticket for this. Also can you try to add following dependency as well ?

                                   

                                  @Reference

                                  com.day.cq.mailer.impl.CqMailingService

                                  @Reference

                                  com.day.cq.mailer.DefaultMailService

                                   

                                  Yogesh


                                  • 15. Re: Send Email Using CQ API and custom template
                                    djain5 Level 1

                                    Hi yogesh,

                                     

                                    After adding these referrences,When i deploy the bundle.my component(com.sr.cq5.workflows.SendHTMLEmailProcess) get unsatisfied due to:

                                     

                                    Reference mailingService["Unsatisfied","Service Name: com.day.cq.mailer.impl.CqMailingService","Multiple: single","Optional: mandatory","Policy: static","No Services bound"]

                                     

                                     

                                    How to resolve this?

                                     

                                    Regards

                                    Deepika

                                    • 16. Re: Send Email Using CQ API and custom template
                                      iyer.s

                                      Greetings,

                                       

                                      Has anyone resolved this issue? I see the same issue where MessageGateway throws NPE.

                                      Any advice/suggestions much appreciated.

                                      Has anyone raised a daycare ticket for this, any resolution from support side?

                                       

                                      Best,

                                      Sivaram

                                      • 17. Re: Send Email Using CQ API and custom template
                                        iyer.s Level 1

                                        I setup an SMTP mail server within CQ and boom! it workeD!

                                         

                                        http://therealcq.blogspot.com/2013/01/setting-up-gmail-as-your-smtp-server-in.html

                                         

                                        go play!