From 2887011933847ec726c8fccd48ca6437c480a644 Mon Sep 17 00:00:00 2001
From: AMIT KUMAR <amit.kumar@tarento.com>
Date: Wed, 11 Aug 2021 10:40:54 +0530
Subject: [PATCH] Issue #SC-2309 feat:Refactored notification service (#903)

* Issue #SC-2309 feat:Refactored notification service

* Issue #SC-2309 feat:fixed test cases

* Issue #SC-2309 feat:fixed test cases
---
 .../BackGroundNotificationActor.java          |   4 +-
 .../actor/notification/EmailServiceActor.java | 400 ++---------------
 .../notification/SendNotificationActor.java   | 126 +-----
 .../notification/NotificationService.java     | 269 ++++++++++++
 .../org/sunbird/service/otp/OTPService.java   |   4 -
 .../org/sunbird/service/user/UserService.java |  20 +-
 .../service/user/impl/UserServiceImpl.java    | 261 ++++++-----
 .../BackgroundNotificationActorTest.java      |  72 +++
 .../notification/EmailServiceActorTest.java   | 414 ++++--------------
 .../SendNotificationActorTest.java            | 181 +++++---
 .../org/sunbird/actor/otp/OTPActorTest.java   |  25 +-
 .../notification/NotificationServiceTest.java | 332 ++++++++++++++
 .../user/UserEmailsBySearchQueryTest.java     |  84 ++++
 13 files changed, 1201 insertions(+), 991 deletions(-)
 create mode 100644 service/src/main/java/org/sunbird/service/notification/NotificationService.java
 create mode 100644 service/src/test/java/org/sunbird/actor/notification/BackgroundNotificationActorTest.java
 create mode 100644 service/src/test/java/org/sunbird/service/notification/NotificationServiceTest.java
 create mode 100644 service/src/test/java/org/sunbird/service/user/UserEmailsBySearchQueryTest.java

diff --git a/service/src/main/java/org/sunbird/actor/notification/BackGroundNotificationActor.java b/service/src/main/java/org/sunbird/actor/notification/BackGroundNotificationActor.java
index ee47601d4..aae6e1971 100644
--- a/service/src/main/java/org/sunbird/actor/notification/BackGroundNotificationActor.java
+++ b/service/src/main/java/org/sunbird/actor/notification/BackGroundNotificationActor.java
@@ -23,14 +23,14 @@ public class BackGroundNotificationActor extends BaseActor {
 
   private void callNotificationService(Request reqObj) {
     Map<String, Object> request = reqObj.getRequest();
-    logger.info(
+    logger.debug(
         reqObj.getRequestContext(),
         "BackGroundNotificationActor:callNotificationService :: Method called.");
     try {
       ObjectMapper mapper = new ObjectMapper();
       String notification_service_base_url = System.getenv("notification_service_base_url");
       String NOTIFICATION_SERVICE_URL = notification_service_base_url + "/v1/notification/send";
-      logger.info(
+      logger.debug(
           reqObj.getRequestContext(),
           "BackGroundNotificationActor:callNotificationService :: calling notification service URL :"
               + NOTIFICATION_SERVICE_URL);
diff --git a/service/src/main/java/org/sunbird/actor/notification/EmailServiceActor.java b/service/src/main/java/org/sunbird/actor/notification/EmailServiceActor.java
index 127c3125e..dae695279 100644
--- a/service/src/main/java/org/sunbird/actor/notification/EmailServiceActor.java
+++ b/service/src/main/java/org/sunbird/actor/notification/EmailServiceActor.java
@@ -1,41 +1,25 @@
 package org.sunbird.actor.notification;
 
 import java.io.StringWriter;
-import java.text.MessageFormat;
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+
 import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.velocity.VelocityContext;
 import org.apache.velocity.app.Velocity;
 import org.sunbird.actor.BackgroundOperations;
 import org.sunbird.actor.core.BaseActor;
 import org.sunbird.actor.router.ActorConfig;
-import org.sunbird.cassandra.CassandraOperation;
-import org.sunbird.common.ElasticSearchHelper;
-import org.sunbird.common.factory.EsClientFactory;
-import org.sunbird.common.inf.ElasticSearchService;
-import org.sunbird.dao.notification.EmailTemplateDao;
-import org.sunbird.dao.notification.impl.EmailTemplateDaoImpl;
-import org.sunbird.datasecurity.DecryptionService;
-import org.sunbird.exception.ProjectCommonException;
-import org.sunbird.exception.ResponseCode;
-import org.sunbird.helper.ServiceFactory;
 import org.sunbird.keys.JsonKey;
 import org.sunbird.mail.SendEmail;
 import org.sunbird.mail.SendgridConnection;
-import org.sunbird.notification.sms.provider.ISmsProvider;
-import org.sunbird.notification.utils.SMSFactory;
 import org.sunbird.request.Request;
 import org.sunbird.request.RequestContext;
 import org.sunbird.response.Response;
+import org.sunbird.service.notification.NotificationService;
 import org.sunbird.util.ProjectUtil;
-import org.sunbird.util.Util;
-import scala.concurrent.Future;
 
 @ActorConfig(
   tasks = {"emailService"},
@@ -44,10 +28,7 @@ import scala.concurrent.Future;
 )
 public class EmailServiceActor extends BaseActor {
 
-  private CassandraOperation cassandraOperation = ServiceFactory.getInstance();
-  private DecryptionService decryptionService =
-      org.sunbird.datasecurity.impl.ServiceFactory.getDecryptionServiceInstance(null);
-  private ElasticSearchService esService = EsClientFactory.getInstance(JsonKey.REST);
+  private NotificationService notificationService = new NotificationService();
   private SendgridConnection connection = new SendgridConnection();
   private String resetInterval = ProjectUtil.getConfigValue("sendgrid_connection_reset_interval");
   private volatile long timer;
@@ -66,81 +47,38 @@ public class EmailServiceActor extends BaseActor {
     }
   }
 
-  @SuppressWarnings({"unchecked"})
   private void sendMail(Request actorMessage) {
+    RequestContext requestContext = actorMessage.getRequestContext();
     Map<String, Object> request =
-        (Map<String, Object>) actorMessage.getRequest().get(JsonKey.EMAIL_REQUEST);
-
-    List<String> userIds = (List<String>) request.get(JsonKey.RECIPIENT_USERIDS);
-    if (CollectionUtils.isEmpty(userIds)) {
-      userIds = new ArrayList<>();
-    }
-
+      (Map<String, Object>) actorMessage.getRequest().get(JsonKey.EMAIL_REQUEST);
+    List<String> userIds = (CollectionUtils.isEmpty((List<String>) request.get(JsonKey.RECIPIENT_USERIDS))) ? new ArrayList<>(): (List<String>) request.get(JsonKey.RECIPIENT_USERIDS);
+    List<String> phones = (CollectionUtils.isEmpty((List<String>) request.get(JsonKey.RECIPIENT_PHONES))) ? new ArrayList<>() : (List<String>) request.get(JsonKey.RECIPIENT_PHONES);
+    List<String> emails = (CollectionUtils.isEmpty((List<String>) request.get(JsonKey.RECIPIENT_EMAILS))) ? new ArrayList<>() : (List<String>) request.get(JsonKey.RECIPIENT_EMAILS);
+    String mode;
     if (request.get(JsonKey.MODE) != null
-        && "sms".equalsIgnoreCase((String) request.get(JsonKey.MODE))) {
-      // Sending sms
-      List<String> phones = (List<String>) request.get(JsonKey.RECIPIENT_PHONES);
-      if (CollectionUtils.isNotEmpty(phones)) {
-        Iterator<String> itr = phones.iterator();
-        while (itr.hasNext()) {
-          String phone = itr.next();
-          if (!ProjectUtil.validatePhone(phone, "")) {
-            logger.info(
-                actorMessage.getRequestContext(),
-                "EmailServiceActor:sendMail: Removing invalid phone number =" + phone);
-            itr.remove();
-          }
-        }
-      }
-      sendSMS(
-          phones, userIds, (String) request.get(JsonKey.BODY), actorMessage.getRequestContext());
+      && JsonKey.SMS.equalsIgnoreCase((String) request.get(JsonKey.MODE))) {
+      mode = JsonKey.SMS;
     } else {
-      // Sending email
-      List<String> emails = (List<String>) request.get(JsonKey.RECIPIENT_EMAILS);
-      if (CollectionUtils.isNotEmpty(emails)) {
-        checkEmailValidity(emails);
-      } else {
-        emails = new ArrayList<>();
-      }
-      // Fetch public user emails from Elastic Search based on recipient search query given in
-      // request.
-      getUserEmailsFromSearchQuery(request, emails, userIds, actorMessage.getRequestContext());
-      List<Map<String, Object>> userList = null;
-
-      if (CollectionUtils.isNotEmpty(userIds)) {
-        userList = getUsersFromDB(userIds, actorMessage.getRequestContext());
-        validateUserIds(userIds, userList, emails, actorMessage.getRequestContext());
-      }
+      mode = JsonKey.EMAIL;
+    }
+    if (JsonKey.SMS.equalsIgnoreCase(mode)) {
+      notificationService.processSMS(userIds, phones, (String) request.get(JsonKey.BODY), requestContext);
+    }
 
-      validateRecipientsLimit(emails);
+    if (JsonKey.EMAIL.equalsIgnoreCase(mode)) {
+      // Fetch user emails from Elastic Search based on recipient search query given in
+      // request.
+      Map<String, Object> recipientSearchQuery =
+        (Map<String, Object>) request.get(JsonKey.RECIPIENT_SEARCH_QUERY);
+      List<String> emailList = notificationService.validateAndGetEmailList(userIds, emails, recipientSearchQuery, requestContext);
+      notificationService.updateFirstNameAndOrgNameInEmailContext(userIds, emails, request, requestContext);
 
-      if ((userIds.size() == 1) && (emails.size() == 1) && (CollectionUtils.isNotEmpty(userList))) {
-        Map<String, Object> user = userList.get(0);
-        if (StringUtils.isNotBlank((String) request.get(JsonKey.FIRST_NAME))) {
-          request.put(
-              JsonKey.NAME, StringUtils.capitalize((String) request.get(JsonKey.FIRST_NAME)));
-        }
-        // fetch orgname inorder to set in the Template context
-        String orgName =
-            getOrgName(
-                request, (String) user.get(JsonKey.ROOT_ORG_ID), actorMessage.getRequestContext());
-        if (StringUtils.isNotBlank(orgName)) {
-          request.put(JsonKey.ORG_NAME, orgName);
-        }
-        logger.info(
-            actorMessage.getRequestContext(),
-            "EmailServiceActor:sendMail: Sending email to = " + emails + " emails");
-      } else {
-        logger.info(
-            actorMessage.getRequestContext(),
-            "EmailServiceActor:sendMail: Sending email to = " + emails.size() + " emails");
-      }
-      if (CollectionUtils.isNotEmpty(emails)) {
+      if (CollectionUtils.isNotEmpty(emailList)) {
         String template =
-            getEmailTemplateFile(
-                (String) request.get(JsonKey.EMAIL_TEMPLATE_TYPE),
-                actorMessage.getRequestContext());
-        sendMail(request, emails, template, actorMessage.getRequestContext());
+          notificationService.getEmailTemplateFile(
+            (String) request.get(JsonKey.EMAIL_TEMPLATE_TYPE),
+            requestContext);
+        sendMail(request, emailList, template, requestContext);
       }
     }
 
@@ -150,10 +88,10 @@ public class EmailServiceActor extends BaseActor {
   }
 
   private void sendMail(
-      Map<String, Object> request,
-      List<String> emails,
-      String template,
-      RequestContext requestContext) {
+    Map<String, Object> request,
+    List<String> emails,
+    String template,
+    RequestContext requestContext) {
     try {
       SendEmail sendEmail = new SendEmail();
       Velocity.init();
@@ -165,280 +103,30 @@ public class EmailServiceActor extends BaseActor {
         interval = Long.parseLong(resetInterval);
       }
       if (null == connection.getTransport()
-          || ((System.currentTimeMillis()) - timer >= interval)
-          || (!connection.getTransport().isConnected())) {
+        || ((System.currentTimeMillis()) - timer >= interval)
+        || (!connection.getTransport().isConnected())) {
         resetConnection();
       }
       sendEmail.send(
-          emails.toArray(new String[emails.size()]),
-          (String) request.get(JsonKey.SUBJECT),
-          context,
-          writer,
-          connection.getSession(),
-          connection.getTransport());
+        emails.toArray(new String[emails.size()]),
+        (String) request.get(JsonKey.SUBJECT),
+        context,
+        writer,
+        connection.getSession(),
+        connection.getTransport());
     } catch (Exception e) {
       logger.error(
-          requestContext,
-          "EmailServiceActor:sendMail: Exception occurred with message = " + e.getMessage(),
-          e);
+        requestContext,
+        "EmailServiceActor:sendMail: Exception occurred with message = " + e.getMessage(),
+        e);
     }
   }
 
   private void resetConnection() {
-    logger.info("SMTP Transport client connection is closed or timed out. Create new connection.");
+    logger.info("EmailServiceActor:resetConnection : SMTP Transport client connection is closed or timed out. Create new connection.");
     connection.createConnection();
     // set timer value
     timer = System.currentTimeMillis();
   }
 
-  /**
-   * This method will send sms to targeted user.
-   *
-   * @param phones list of phone numbers
-   * @param userIds list of userIds
-   * @param smsText message
-   */
-  private void sendSMS(
-      List<String> phones, List<String> userIds, String smsText, RequestContext context) {
-    logger.info(context, "EmailServiceActor:sendSMS: method started  = " + smsText);
-    if (CollectionUtils.isEmpty(phones)) {
-      phones = new ArrayList<String>();
-    }
-    if (CollectionUtils.isNotEmpty(userIds)) {
-      List<Map<String, Object>> userList = getUsersFromDB(userIds, context);
-      if (userIds.size() != userList.size()) {
-        findMissingUserIds(userIds, userList);
-      } else {
-        for (Map<String, Object> userMap : userList) {
-          String phone = (String) userMap.get(JsonKey.PHONE);
-          if (StringUtils.isNotBlank(phone)) {
-            String decryptedPhone = decryptionService.decryptData(phone, context);
-            if (!phones.contains(decryptedPhone)) {
-              phones.add(decryptedPhone);
-            }
-          }
-        }
-      }
-    }
-
-    validateRecipientsLimit(phones);
-
-    logger.info(
-        context, "EmailServiceActor:sendSMS: Sending sendSMS to = " + phones.size() + " phones");
-    try {
-      ISmsProvider smsProvider = SMSFactory.getInstance();
-      smsProvider.send(phones, smsText);
-    } catch (Exception e) {
-      logger.error(
-          context,
-          "EmailServiceActor:sendSMS: Exception occurred with message = " + e.getMessage(),
-          e);
-    }
-  }
-
-  private void validateRecipientsLimit(List<String> recipients) {
-    if (CollectionUtils.isEmpty(recipients)) {
-      ProjectCommonException.throwClientErrorException(
-          ResponseCode.emailNotSentRecipientsZero,
-          ResponseCode.emailNotSentRecipientsZero.getErrorMessage());
-    }
-    int maxLimit = 100;
-    try {
-      maxLimit =
-          Integer.parseInt(ProjectUtil.getConfigValue(JsonKey.SUNBIRD_EMAIL_MAX_RECEPIENT_LIMIT));
-    } catch (Exception exception) {
-      logger.error(
-          "EmailServiceActor:validateEmailRecipientsLimit: Exception occurred with error message = "
-              + exception.getMessage(),
-          exception);
-      maxLimit = 100;
-    }
-    if (recipients.size() > maxLimit) {
-      ProjectCommonException.throwClientErrorException(
-          ResponseCode.emailNotSentRecipientsExceededMaxLimit,
-          MessageFormat.format(
-              ResponseCode.emailNotSentRecipientsExceededMaxLimit.getErrorMessage(), maxLimit));
-    }
-  }
-
-  private void validateUserIds(
-      List<String> userIds,
-      List<Map<String, Object>> userList,
-      List<String> emails,
-      RequestContext context) {
-    // Fetch private (masked in Elastic Search) user emails from Cassandra DB
-    if (userIds.size() != userList.size()) {
-      findMissingUserIds(userIds, userList);
-    } else {
-      for (Map<String, Object> userMap : userList) {
-        String email = (String) userMap.get(JsonKey.EMAIL);
-        if (StringUtils.isNotBlank(email)) {
-          String decryptedEmail = decryptionService.decryptData(email, context);
-          emails.add(decryptedEmail);
-        }
-      }
-    }
-  }
-
-  private void findMissingUserIds(
-      List<String> requestedUserIds, List<Map<String, Object>> userListInDB) {
-    // if requested userId list and cassandra user list size not same , means
-    // requested userId
-    // list
-    // contains some invalid userId
-    List<String> userIdFromDBList = new ArrayList<>();
-    userListInDB.forEach(
-        user -> {
-          userIdFromDBList.add((String) user.get(JsonKey.ID));
-        });
-    requestedUserIds.forEach(
-        userId -> {
-          if (!userIdFromDBList.contains(userId)) {
-            ProjectCommonException.throwClientErrorException(
-                ResponseCode.invalidParameterValue,
-                MessageFormat.format(
-                    ResponseCode.invalidParameterValue.getErrorMessage(),
-                    userId,
-                    JsonKey.RECIPIENT_USERIDS));
-            return;
-          }
-        });
-  }
-
-  private String getEmailTemplateFile(String templateName, RequestContext context) {
-    EmailTemplateDao emailTemplateDao = EmailTemplateDaoImpl.getInstance();
-    String template = emailTemplateDao.getTemplate(templateName, context);
-    if (StringUtils.isBlank(template)) {
-      ProjectCommonException.throwClientErrorException(
-          ResponseCode.invalidParameterValue,
-          MessageFormat.format(
-              ResponseCode.invalidParameterValue.getErrorMessage(),
-              templateName,
-              JsonKey.EMAIL_TEMPLATE_TYPE));
-    }
-    return template;
-  }
-
-  private List<Map<String, Object>> getUsersFromDB(List<String> userIds, RequestContext context) {
-    Util.DbInfo usrDbInfo = Util.dbInfoMap.get(JsonKey.USER_DB);
-    List<String> userIdList = new ArrayList<>(userIds);
-    List<String> fields = new ArrayList<>();
-    fields.add(JsonKey.ID);
-    fields.add(JsonKey.FIRST_NAME);
-    fields.add(JsonKey.EMAIL);
-    fields.add(JsonKey.PHONE);
-    fields.add(JsonKey.ROOT_ORG_ID);
-    Response response =
-        cassandraOperation.getRecordsByIdsWithSpecifiedColumns(
-            usrDbInfo.getKeySpace(), usrDbInfo.getTableName(), fields, userIdList, context);
-    List<Map<String, Object>> userList = (List<Map<String, Object>>) response.get(JsonKey.RESPONSE);
-    return userList;
-  }
-
-  private void getUserEmailsFromSearchQuery(
-      Map<String, Object> request,
-      List<String> emails,
-      List<String> userIds,
-      RequestContext context) {
-    Map<String, Object> recipientSearchQuery =
-        (Map<String, Object>) request.get(JsonKey.RECIPIENT_SEARCH_QUERY);
-    if (MapUtils.isNotEmpty(recipientSearchQuery)) {
-
-      if (MapUtils.isEmpty((Map<String, Object>) recipientSearchQuery.get(JsonKey.FILTERS))) {
-        ProjectCommonException.throwClientErrorException(
-            ResponseCode.invalidParameterValue,
-            MessageFormat.format(
-                ResponseCode.invalidParameterValue.getErrorMessage(),
-                recipientSearchQuery,
-                JsonKey.RECIPIENT_SEARCH_QUERY));
-        return;
-      }
-
-      List<String> fields = new ArrayList<>();
-      fields.add(JsonKey.USER_ID);
-      fields.add(JsonKey.EMAIL);
-      recipientSearchQuery.put(JsonKey.FIELDS, fields);
-      Map<String, Object> esResult = Collections.emptyMap();
-      try {
-        Future<Map<String, Object>> esResultF =
-            esService.search(
-                ElasticSearchHelper.createSearchDTO(recipientSearchQuery),
-                ProjectUtil.EsType.user.getTypeName(),
-                context);
-        esResult = (Map<String, Object>) ElasticSearchHelper.getResponseFromFuture(esResultF);
-      } catch (Exception ex) {
-        logger.error(
-            "EmailServiceActor:getUserEmailsFromSearchQuery: Exception occurred with error message = "
-                + ex.getMessage(),
-            ex);
-        ProjectCommonException.throwClientErrorException(
-            ResponseCode.invalidParameterValue,
-            MessageFormat.format(
-                ResponseCode.invalidParameterValue.getErrorMessage(),
-                recipientSearchQuery,
-                JsonKey.RECIPIENT_SEARCH_QUERY));
-        return;
-      }
-      if (MapUtils.isNotEmpty(esResult)
-          && CollectionUtils.isNotEmpty((List) esResult.get(JsonKey.CONTENT))) {
-        List<Map<String, Object>> usersList =
-            (List<Map<String, Object>>) esResult.get(JsonKey.CONTENT);
-        usersList.forEach(
-            user -> {
-              if (StringUtils.isNotBlank((String) user.get(JsonKey.EMAIL))) {
-                String email =
-                    decryptionService.decryptData((String) user.get(JsonKey.EMAIL), context);
-                if (ProjectUtil.isEmailvalid(email)) {
-                  emails.add(email);
-                } else {
-                  logger.info(
-                      "EmailServiceActor:sendMail: Email decryption failed for userId = "
-                          + user.get(JsonKey.USER_ID));
-                }
-              } else {
-                // If email is blank (or private) then fetch email from cassandra
-                userIds.add((String) user.get(JsonKey.USER_ID));
-              }
-            });
-      }
-    }
-  }
-
-  private String getOrgName(Map<String, Object> request, String rootOrgId, RequestContext context) {
-    String orgName = (String) request.get(JsonKey.ORG_NAME);
-    if (StringUtils.isNotBlank(orgName)) {
-      return orgName;
-    }
-    if (StringUtils.isNotBlank(rootOrgId)) {
-      Util.DbInfo orgDbInfo = Util.dbInfoMap.get(JsonKey.ORG_DB);
-      Response response =
-          cassandraOperation.getRecordById(
-              orgDbInfo.getKeySpace(), orgDbInfo.getTableName(), rootOrgId, context);
-      List<Map<String, Object>> orgList =
-          (List<Map<String, Object>>) response.get(JsonKey.RESPONSE);
-      Map<String, Object> org = null;
-      if (CollectionUtils.isNotEmpty(orgList)) {
-        org = orgList.get(0);
-      }
-      if (MapUtils.isNotEmpty(org)) {
-        orgName =
-            (org.get(JsonKey.ORG_NAME) != null ? (String) org.get(JsonKey.ORGANISATION_NAME) : "");
-      }
-    }
-    return orgName;
-  }
-
-  private void checkEmailValidity(List<String> emails) {
-    for (String email : emails) {
-      if (!ProjectUtil.isEmailvalid(email)) {
-        ProjectCommonException.throwClientErrorException(
-            ResponseCode.invalidParameterValue,
-            MessageFormat.format(
-                ResponseCode.invalidParameterValue.getErrorMessage(),
-                email,
-                JsonKey.RECIPIENT_EMAILS));
-        return;
-      }
-    }
-  }
 }
diff --git a/service/src/main/java/org/sunbird/actor/notification/SendNotificationActor.java b/service/src/main/java/org/sunbird/actor/notification/SendNotificationActor.java
index dd60b9899..60ca0f811 100644
--- a/service/src/main/java/org/sunbird/actor/notification/SendNotificationActor.java
+++ b/service/src/main/java/org/sunbird/actor/notification/SendNotificationActor.java
@@ -1,25 +1,16 @@
 package org.sunbird.actor.notification;
 
-import java.text.MessageFormat;
 import java.util.*;
-import org.apache.commons.collections4.CollectionUtils;
+
 import org.apache.commons.lang.StringUtils;
-import org.apache.velocity.VelocityContext;
 import org.sunbird.actor.core.BaseActor;
 import org.sunbird.actor.router.ActorConfig;
-import org.sunbird.dao.notification.EmailTemplateDao;
-import org.sunbird.dao.notification.impl.EmailTemplateDaoImpl;
-import org.sunbird.datasecurity.DecryptionService;
-import org.sunbird.exception.ProjectCommonException;
-import org.sunbird.exception.ResponseCode;
-import org.sunbird.helper.ServiceFactory;
 import org.sunbird.keys.JsonKey;
 import org.sunbird.operations.ActorOperations;
 import org.sunbird.request.Request;
 import org.sunbird.request.RequestContext;
 import org.sunbird.response.Response;
-import org.sunbird.util.ProjectUtil;
-import org.sunbird.util.Util;
+import org.sunbird.service.notification.NotificationService;
 
 @ActorConfig(
   tasks = {"v2Notification"},
@@ -27,6 +18,9 @@ import org.sunbird.util.Util;
   dispatcher = "notification-dispatcher"
 )
 public class SendNotificationActor extends BaseActor {
+
+  NotificationService notificationService = new NotificationService();
+
   @Override
   public void onReceive(Request request) throws Throwable {
     if (request.getOperation().equalsIgnoreCase(ActorOperations.V2_NOTIFICATION.getValue())) {
@@ -40,24 +34,28 @@ public class SendNotificationActor extends BaseActor {
     Map<String, Object> requestMap =
         (Map<String, Object>) request.getRequest().get(JsonKey.EMAIL_REQUEST);
     List<String> userIds = (List<String>) requestMap.remove(JsonKey.RECIPIENT_USERIDS);
-    List<String> phoneOrEmailList;
-    Map<String, Object> notificationReq;
+    Set<String> phoneOrEmailList;
+    Map<String, Object> notificationReq = null;
     String mode = (String) requestMap.remove(JsonKey.MODE);
-    logger.info(
-        request.getRequestContext(),
-        "SendNotificationActor:sendNotification : called for mode =" + mode);
-    if (StringUtils.isNotBlank(mode) && JsonKey.SMS.equalsIgnoreCase(mode)) {
-      phoneOrEmailList = getUsersEmailOrPhone(userIds, JsonKey.PHONE, request.getRequestContext());
-      notificationReq = getNotificationRequest(phoneOrEmailList, requestMap, JsonKey.SMS, null);
+    if (StringUtils.isNotBlank(mode)
+      && JsonKey.SMS.equalsIgnoreCase(mode)) {
+      mode = JsonKey.SMS;
     } else {
-      phoneOrEmailList = getUsersEmailOrPhone(userIds, JsonKey.EMAIL, request.getRequestContext());
+      mode = JsonKey.EMAIL;
+    }
+    if (JsonKey.SMS.equalsIgnoreCase(mode)) {
+      phoneOrEmailList = notificationService.getEmailOrPhoneListByUserIds(userIds, JsonKey.PHONE, request.getRequestContext());
+      notificationReq = notificationService.getV2NotificationRequest(phoneOrEmailList, requestMap, JsonKey.SMS, null);
+    }
+    if (JsonKey.EMAIL.equalsIgnoreCase(mode)) {
+      phoneOrEmailList = notificationService.getEmailOrPhoneListByUserIds(userIds, JsonKey.EMAIL, request.getRequestContext());
       String template =
-          getEmailTemplateFile(
+        notificationService.getEmailTemplateFile(
               (String) requestMap.get(JsonKey.EMAIL_TEMPLATE_TYPE), request.getRequestContext());
       notificationReq =
-          getNotificationRequest(phoneOrEmailList, requestMap, JsonKey.EMAIL, template);
+        notificationService.getV2NotificationRequest(phoneOrEmailList, requestMap, JsonKey.EMAIL, template);
     }
-    logger.info(
+    logger.debug(
         request.getRequestContext(),
         "SendNotificationActor:sendNotification : called for userIds =" + userIds);
     process(notificationReq, request.getRequestId(), request.getRequestContext());
@@ -84,86 +82,4 @@ public class SendNotificationActor extends BaseActor {
     tellToAnother(bgRequest);
   }
 
-  private Map<String, Object> getNotificationRequest(
-      List<String> phoneOrEmailList, Map<String, Object> requestMap, String mode, String template) {
-    Map<String, Object> notiReq = new HashMap<>();
-    notiReq.put("deliveryType", "message");
-    Map<String, Object> config = new HashMap<>(2);
-    config.put("sender", System.getenv("sunbird_mail_server_from_email"));
-    config.put(JsonKey.SUBJECT, requestMap.remove(JsonKey.SUBJECT));
-    notiReq.put("config", config);
-    Map<String, Object> templateMap = new HashMap<>(2);
-    if (mode.equalsIgnoreCase(JsonKey.SMS)) {
-      templateMap.put(JsonKey.DATA, requestMap.remove(JsonKey.BODY));
-      templateMap.put(JsonKey.PARAMS, Collections.emptyMap());
-      notiReq.put("template", templateMap);
-      notiReq.put(JsonKey.MODE, JsonKey.PHONE);
-    } else {
-      templateMap.put(JsonKey.DATA, template);
-      VelocityContext context = ProjectUtil.getContext(requestMap);
-      Object[] keys = context.getKeys();
-      for (Object obj : keys) {
-        if (obj instanceof String) {
-          String key = (String) obj;
-          requestMap.put(key, context.get(key));
-        }
-      }
-      templateMap.put(JsonKey.PARAMS, requestMap);
-      notiReq.put("template", templateMap);
-      notiReq.put(JsonKey.MODE, JsonKey.EMAIL);
-    }
-    notiReq.put("ids", phoneOrEmailList);
-    return notiReq;
-  }
-
-  private String getEmailTemplateFile(String templateName, RequestContext context) {
-    EmailTemplateDao emailTemplateDao = EmailTemplateDaoImpl.getInstance();
-    String template = emailTemplateDao.getTemplate(templateName, context);
-    if (StringUtils.isBlank(template)) {
-      ProjectCommonException.throwClientErrorException(
-          ResponseCode.invalidParameterValue,
-          MessageFormat.format(
-              ResponseCode.invalidParameterValue.getErrorMessage(),
-              templateName,
-              JsonKey.EMAIL_TEMPLATE_TYPE));
-    }
-    return template;
-  }
-
-  private List<String> getUsersEmailOrPhone(
-      List<String> userIds, String key, RequestContext context) {
-    Util.DbInfo usrDbInfo = Util.dbInfoMap.get(JsonKey.USER_DB);
-    List<String> fields = new ArrayList<>();
-    fields.add(key);
-    Response response =
-        ServiceFactory.getInstance()
-            .getRecordsByIdsWithSpecifiedColumns(
-                usrDbInfo.getKeySpace(), usrDbInfo.getTableName(), fields, userIds, context);
-    List<Map<String, Object>> userList = (List<Map<String, Object>>) response.get(JsonKey.RESPONSE);
-    return getPhoneOrEmailList(userList, key, context);
-  }
-
-  private List<String> getPhoneOrEmailList(
-      List<Map<String, Object>> userList, String key, RequestContext context) {
-    if (CollectionUtils.isNotEmpty(userList)) {
-      DecryptionService decryptionService =
-          org.sunbird.datasecurity.impl.ServiceFactory.getDecryptionServiceInstance(null);
-      List<String> emailOrPhoneList = new ArrayList<>();
-      for (Map<String, Object> userMap : userList) {
-        String email = (String) userMap.get(key);
-        if (StringUtils.isNotBlank(email)) {
-          String decryptedEmail = decryptionService.decryptData(email, context);
-          emailOrPhoneList.add(decryptedEmail);
-        }
-      }
-      if (CollectionUtils.isNotEmpty(emailOrPhoneList)) {
-        return emailOrPhoneList;
-      } else {
-        ProjectCommonException.throwClientErrorException(
-            ResponseCode.notificationNotSent,
-            MessageFormat.format(ResponseCode.notificationNotSent.getErrorMessage(), key));
-      }
-    }
-    return Collections.emptyList();
-  }
 }
diff --git a/service/src/main/java/org/sunbird/service/notification/NotificationService.java b/service/src/main/java/org/sunbird/service/notification/NotificationService.java
new file mode 100644
index 000000000..36a2fd203
--- /dev/null
+++ b/service/src/main/java/org/sunbird/service/notification/NotificationService.java
@@ -0,0 +1,269 @@
+package org.sunbird.service.notification;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.velocity.VelocityContext;
+import org.sunbird.dao.notification.EmailTemplateDao;
+import org.sunbird.dao.notification.impl.EmailTemplateDaoImpl;
+import org.sunbird.exception.ProjectCommonException;
+import org.sunbird.exception.ResponseCode;
+import org.sunbird.keys.JsonKey;
+import org.sunbird.logging.LoggerUtil;
+import org.sunbird.model.user.User;
+import org.sunbird.notification.sms.provider.ISmsProvider;
+import org.sunbird.notification.utils.SMSFactory;
+import org.sunbird.request.RequestContext;
+import org.sunbird.service.organisation.OrgService;
+import org.sunbird.service.organisation.impl.OrgServiceImpl;
+import org.sunbird.service.user.UserService;
+import org.sunbird.service.user.impl.UserServiceImpl;
+import org.sunbird.util.ProjectUtil;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class NotificationService {
+
+  private static LoggerUtil logger = new LoggerUtil(NotificationService.class);
+  private UserService userService = UserServiceImpl.getInstance();
+  private OrgService orgService = OrgServiceImpl.getInstance();
+
+  public boolean processSMS(List<String> userIds, List<String> phones, String smsText, RequestContext requestContext) {
+    validatePhoneOrEmail(phones, JsonKey.PHONE);
+    Set<String> phoneList = getEmailOrPhoneListByUserIds(userIds, JsonKey.PHONE, requestContext);
+    //Merge All Phone
+    if (CollectionUtils.isNotEmpty(phones)) {
+      phoneList.addAll(phones);
+    }
+    validateRecipientsLimit(phoneList);
+
+    return sendSMS(new ArrayList<>(phoneList), smsText, requestContext);
+  }
+
+  private void findMissingUserIds(
+    List<String> requestedUserIds, List<Map<String, Object>> userListInDB) {
+    // if requested userId list and cassandra user list size not same , means
+    // requested userId
+    // list
+    // contains some invalid userId
+    List<String> userIdFromDBList = new ArrayList<>();
+    userListInDB.forEach(
+      user -> userIdFromDBList.add((String) user.get(JsonKey.ID)));
+    requestedUserIds.forEach(
+      userId -> {
+        if (!userIdFromDBList.contains(userId)) {
+          ProjectCommonException.throwClientErrorException(
+            ResponseCode.invalidParameterValue,
+            MessageFormat.format(
+              ResponseCode.invalidParameterValue.getErrorMessage(),
+              userId,
+              JsonKey.RECIPIENT_USERIDS));
+        }
+      });
+  }
+
+  private void validateRecipientsLimit(Set<String> recipients) {
+    int maxLimit;
+    try {
+      maxLimit =
+        Integer.parseInt(ProjectUtil.getConfigValue(JsonKey.SUNBIRD_EMAIL_MAX_RECEPIENT_LIMIT));
+    } catch (Exception exception) {
+      logger.error(
+        "EmailServiceActor:validateEmailRecipientsLimit: Exception occurred with error message = "
+          + exception.getMessage(),
+        exception);
+      maxLimit = 100;
+    }
+    if (recipients.size() > maxLimit) {
+      ProjectCommonException.throwClientErrorException(
+        ResponseCode.emailNotSentRecipientsExceededMaxLimit,
+        MessageFormat.format(
+          ResponseCode.emailNotSentRecipientsExceededMaxLimit.getErrorMessage(), maxLimit));
+    }
+  }
+
+  private boolean sendSMS(
+    List<String> phones, String smsText, RequestContext context) {
+    logger.info(
+      context, "NotificationService:sendSMS: Sending sendSMS to = " + phones.size() + " phones");
+    try {
+      ISmsProvider smsProvider = SMSFactory.getInstance();
+      return smsProvider.send(phones, smsText);
+    } catch (Exception e) {
+      logger.error(
+        context,
+        "NotificationService:sendSMS: Exception occurred with message = " + e.getMessage(),
+        e);
+      return false;
+    }
+  }
+
+  public List<String> validateAndGetEmailList(List<String> userIds, List<String> emails, Map<String, Object> recipientSearchQuery, RequestContext requestContext) {
+    validatePhoneOrEmail(emails, JsonKey.EMAIL);
+    List<Map<String, Object>> searchQueryResult = getUserEmailsFromSearchQuery(recipientSearchQuery, requestContext);
+    for (Map<String, Object> result : searchQueryResult) {
+      if (StringUtils.isNotBlank((String) result.get(JsonKey.EMAIL))) {
+        emails.add((String) result.get(JsonKey.EMAIL));
+      }
+    }
+    Set<String> emailList = getEmailOrPhoneListByUserIds(userIds, JsonKey.EMAIL, requestContext);
+    //Merge All Phone
+    if (CollectionUtils.isNotEmpty(emails)) {
+      emailList.addAll(emails);
+    }
+    validateRecipientsLimit(emailList);
+    return new ArrayList<>(emailList);
+  }
+
+  public void updateFirstNameAndOrgNameInEmailContext(List<String> userIds, List<String> emails, Map<String, Object> request, RequestContext requestContext) {
+    if ((userIds.size() == 1) && (emails.size() == 1)) {
+      User user = userService.getUserById(userIds.get(0), requestContext);
+      if (StringUtils.isNotBlank((String) request.get(JsonKey.FIRST_NAME))) {
+        request.put(
+          JsonKey.NAME, StringUtils.capitalize((String) request.get(JsonKey.FIRST_NAME)));
+      }
+      // fetch orgName inorder to set in the Template context
+      String orgName =
+        getOrgName(
+          request, user.getRootOrgId(), requestContext);
+      if (StringUtils.isNotBlank(orgName)) {
+        request.put(JsonKey.ORG_NAME, orgName);
+      }
+      logger.info(
+        requestContext,
+        "NotificationService:updateFirstNameAndOrgNameInEmailContext: Sending email to = " + emails + " emails");
+    } else {
+      logger.info(
+        requestContext,
+        "NotificationService:updateFirstNameAndOrgNameInEmailContext: Sending email to = " + emails.size() + " emails");
+    }
+  }
+
+  public String getEmailTemplateFile(String templateName, RequestContext context) {
+    EmailTemplateDao emailTemplateDao = EmailTemplateDaoImpl.getInstance();
+    String template = emailTemplateDao.getTemplate(templateName, context);
+    if (StringUtils.isBlank(template)) {
+      ProjectCommonException.throwClientErrorException(
+        ResponseCode.invalidParameterValue,
+        MessageFormat.format(
+          ResponseCode.invalidParameterValue.getErrorMessage(),
+          templateName,
+          JsonKey.EMAIL_TEMPLATE_TYPE));
+    }
+    return template;
+  }
+
+  private String getOrgName(Map<String, Object> request, String rootOrgId, RequestContext context) {
+    String orgName = (String) request.get(JsonKey.ORG_NAME);
+    if (StringUtils.isNotBlank(orgName)) {
+      return orgName;
+    }
+    if (StringUtils.isNotBlank(rootOrgId)) {
+      Map<String, Object> org = orgService.getOrgById(rootOrgId, context);
+      if (MapUtils.isNotEmpty(org)) {
+        orgName =
+          (org.get(JsonKey.ORG_NAME) != null ? (String) org.get(JsonKey.ORGANISATION_NAME) : "");
+      }
+    }
+    return orgName;
+  }
+
+  public Set<String> getEmailOrPhoneListByUserIds(List<String> userIds, String type, RequestContext requestContext) {
+    Set<String> emailOrPhoneList = new HashSet<>();
+    if (CollectionUtils.isNotEmpty(userIds)) {
+      List<Map<String, Object>> dbUserPhoneEmailList = userService.getDecryptedEmailPhoneByUserIds(userIds, type, requestContext);
+      if (userIds.size() != dbUserPhoneEmailList.size()) {
+        findMissingUserIds(userIds, dbUserPhoneEmailList);
+      }
+      for (Map<String, Object> userMap : dbUserPhoneEmailList) {
+        String emailOrPhone = (String) userMap.get(type);
+        if (StringUtils.isNotBlank(emailOrPhone)) {
+          emailOrPhoneList.add(emailOrPhone);
+        }
+      }
+    }
+    return emailOrPhoneList;
+  }
+
+  private List<Map<String, Object>> getUserEmailsFromSearchQuery(Map<String, Object> recipientSearchQuery, RequestContext context) {
+    if (MapUtils.isNotEmpty(recipientSearchQuery)) {
+      if (MapUtils.isEmpty((Map<String, Object>) recipientSearchQuery.get(JsonKey.FILTERS))) {
+        ProjectCommonException.throwClientErrorException(
+          ResponseCode.invalidParameterValue,
+          MessageFormat.format(
+            ResponseCode.invalidParameterValue.getErrorMessage(),
+            recipientSearchQuery,
+            JsonKey.RECIPIENT_SEARCH_QUERY));
+      }
+      List<String> fields = new ArrayList<>();
+      fields.add(JsonKey.USER_ID);
+      fields.add(JsonKey.EMAIL);
+      recipientSearchQuery.put(JsonKey.FIELDS, fields);
+      return userService.getUserEmailsBySearchQuery(recipientSearchQuery, context);
+    }
+    return Collections.emptyList();
+  }
+
+  private void validatePhoneOrEmail(List<String> emailOrPhones, String type) {
+    if (CollectionUtils.isNotEmpty(emailOrPhones)) {
+      for (String emailOrPhone : emailOrPhones) {
+        if (JsonKey.EMAIL.equalsIgnoreCase(type) && !ProjectUtil.isEmailvalid(emailOrPhone)) {
+          ProjectCommonException.throwClientErrorException(
+            ResponseCode.invalidParameterValue,
+            MessageFormat.format(
+              ResponseCode.invalidParameterValue.getErrorMessage(),
+              emailOrPhone,
+              JsonKey.RECIPIENT_EMAILS));
+        }
+
+        if (JsonKey.PHONE.equalsIgnoreCase(type) && !ProjectUtil.validatePhone(emailOrPhone, "")) {
+          ProjectCommonException.throwClientErrorException(
+            ResponseCode.invalidParameterValue,
+            MessageFormat.format(
+              ResponseCode.invalidParameterValue.getErrorMessage(),
+              emailOrPhone,
+              JsonKey.RECIPIENT_PHONES));
+        }
+      }
+    }
+  }
+
+  public Map<String, Object> getV2NotificationRequest(
+    Set<String> phoneOrEmailList, Map<String, Object> requestMap, String mode, String template) {
+    Map<String, Object> notiReq = new HashMap<>();
+    notiReq.put("deliveryType", "message");
+    Map<String, Object> config = new HashMap<>(2);
+    config.put("sender", System.getenv("sunbird_mail_server_from_email"));
+    config.put(JsonKey.SUBJECT, requestMap.remove(JsonKey.SUBJECT));
+    notiReq.put("config", config);
+    Map<String, Object> templateMap = new HashMap<>(2);
+    if (mode.equalsIgnoreCase(JsonKey.SMS)) {
+      templateMap.put(JsonKey.DATA, requestMap.remove(JsonKey.BODY));
+      templateMap.put(JsonKey.PARAMS, Collections.emptyMap());
+      notiReq.put("template", templateMap);
+      notiReq.put(JsonKey.MODE, JsonKey.PHONE);
+    } else {
+      templateMap.put(JsonKey.DATA, template);
+      VelocityContext context = ProjectUtil.getContext(requestMap);
+      Object[] keys = context.getKeys();
+      for (Object obj : keys) {
+        if (obj instanceof String) {
+          String key = (String) obj;
+          requestMap.put(key, context.get(key));
+        }
+      }
+      templateMap.put(JsonKey.PARAMS, requestMap);
+      notiReq.put("template", templateMap);
+      notiReq.put(JsonKey.MODE, JsonKey.EMAIL);
+    }
+    notiReq.put("ids", new ArrayList<>(phoneOrEmailList));
+    return notiReq;
+  }
+}
diff --git a/service/src/main/java/org/sunbird/service/otp/OTPService.java b/service/src/main/java/org/sunbird/service/otp/OTPService.java
index ea0a68aaa..a5673421a 100644
--- a/service/src/main/java/org/sunbird/service/otp/OTPService.java
+++ b/service/src/main/java/org/sunbird/service/otp/OTPService.java
@@ -3,7 +3,6 @@ package org.sunbird.service.otp;
 import java.io.StringWriter;
 import java.util.Map;
 
-import org.apache.commons.lang3.StringUtils;
 import org.apache.velocity.Template;
 import org.apache.velocity.VelocityContext;
 import org.apache.velocity.runtime.RuntimeServices;
@@ -13,9 +12,6 @@ import org.sunbird.dao.notification.EmailTemplateDao;
 import org.sunbird.dao.notification.impl.EmailTemplateDaoImpl;
 import org.sunbird.dao.otp.OTPDao;
 import org.sunbird.dao.otp.impl.OTPDaoImpl;
-import org.sunbird.datasecurity.DecryptionService;
-import org.sunbird.exception.ProjectCommonException;
-import org.sunbird.exception.ResponseCode;
 import org.sunbird.keys.JsonKey;
 import org.sunbird.logging.LoggerUtil;
 import org.sunbird.request.RequestContext;
diff --git a/service/src/main/java/org/sunbird/service/user/UserService.java b/service/src/main/java/org/sunbird/service/user/UserService.java
index c3574c0d2..0a1a96e6a 100644
--- a/service/src/main/java/org/sunbird/service/user/UserService.java
+++ b/service/src/main/java/org/sunbird/service/user/UserService.java
@@ -23,30 +23,34 @@ public interface UserService {
   String getRootOrgIdFromChannel(String channel, RequestContext context);
 
   String getCustodianChannel(
-      Map<String, Object> userMap, ActorRef actorRef, RequestContext context);
+    Map<String, Object> userMap, ActorRef actorRef, RequestContext context);
 
   List<String> generateUsernames(
-      String name, List<String> excludedUsernames, RequestContext context);
+    String name, List<String> excludedUsernames, RequestContext context);
 
   List<String> getEncryptedList(List<String> dataList, RequestContext context);
 
   String getCustodianOrgId(ActorRef actorRef, RequestContext context);
 
   Map<String, Object> fetchEncryptedToken(
-      String parentId, List<Map<String, Object>> respList, RequestContext context);
+    String parentId, List<Map<String, Object>> respList, RequestContext context);
 
   void appendEncryptedToken(
-      Map<String, Object> encryptedTokenList,
-      List<Map<String, Object>> respList,
-      RequestContext context);
+    Map<String, Object> encryptedTokenList,
+    List<Map<String, Object>> respList,
+    RequestContext context);
 
   List<Map<String, Object>> searchUserNameInUserLookup(
-      List<String> encUserNameList, RequestContext context);
+    List<String> encUserNameList, RequestContext context);
 
   Response userLookUpByKey(String key, String value, List<String> fields, RequestContext context);
 
   Response saveUserAttributes(
-      Map<String, Object> userMap, ActorRef actorRef, RequestContext context);
+    Map<String, Object> userMap, ActorRef actorRef, RequestContext context);
 
   String getDecryptedEmailPhoneByUserId(String userId, String type, RequestContext context);
+
+  List<Map<String, Object>> getDecryptedEmailPhoneByUserIds(List<String> userIds, String type, RequestContext context);
+
+  List<Map<String, Object>> getUserEmailsBySearchQuery(Map<String, Object> searchQuery, RequestContext context);
 }
diff --git a/service/src/main/java/org/sunbird/service/user/impl/UserServiceImpl.java b/service/src/main/java/org/sunbird/service/user/impl/UserServiceImpl.java
index 358fcb3f1..f6a4c8b84 100644
--- a/service/src/main/java/org/sunbird/service/user/impl/UserServiceImpl.java
+++ b/service/src/main/java/org/sunbird/service/user/impl/UserServiceImpl.java
@@ -3,6 +3,7 @@ package org.sunbird.service.user.impl;
 import akka.actor.ActorRef;
 import akka.pattern.Patterns;
 import akka.util.Timeout;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -53,7 +54,7 @@ public class UserServiceImpl implements UserService {
 
   private LoggerUtil logger = new LoggerUtil(UserServiceImpl.class);
   private EncryptionService encryptionService =
-      org.sunbird.datasecurity.impl.ServiceFactory.getEncryptionServiceInstance(null);
+    org.sunbird.datasecurity.impl.ServiceFactory.getEncryptionServiceInstance(null);
   private static UserDao userDao = UserDaoImpl.getInstance();
   private static UserService userService = null;
   private static UserLookupDao userLookupDao = UserLookupDaoImpl.getInstance();
@@ -78,9 +79,9 @@ public class UserServiceImpl implements UserService {
     User user = userDao.getUserById(userId, context);
     if (null == user) {
       throw new ProjectCommonException(
-          ResponseCode.userNotFound.getErrorCode(),
-          ResponseCode.userNotFound.getErrorMessage(),
-          ResponseCode.RESOURCE_NOT_FOUND.getResponseCode());
+        ResponseCode.userNotFound.getErrorCode(),
+        ResponseCode.userNotFound.getErrorMessage(),
+        ResponseCode.RESOURCE_NOT_FOUND.getResponseCode());
     }
     return user;
   }
@@ -99,38 +100,38 @@ public class UserServiceImpl implements UserService {
       userId = UserUtil.getUserId(request.getRequest(), context);
     }
     logger.info(
-        "validateUserId :: ctxtUserId : "
-            + ctxtUserId
-            + " userId: "
-            + userId
-            + " managedById: "
-            + managedById
-            + " managedForId: "
-            + managedForId);
+      "validateUserId :: ctxtUserId : "
+        + ctxtUserId
+        + " userId: "
+        + userId
+        + " managedById: "
+        + managedById
+        + " managedForId: "
+        + managedForId);
     // LIUA token is validated when LIUA is updating own account details or LIUA token is validated
     // when updating MUA details
     if ((StringUtils.isNotEmpty(managedForId) && !managedForId.equals(userId))
-        || (StringUtils.isEmpty(managedById)
-            && (!StringUtils.isBlank(userId) && !userId.equals(ctxtUserId))) // UPDATE
-        || (StringUtils.isNotEmpty(managedById)
-            && !(ctxtUserId.equals(managedById)))) // CREATE NEW USER/ UPDATE MUA {
-    throw new ProjectCommonException(
-          ResponseCode.unAuthorized.getErrorCode(),
-          ResponseCode.unAuthorized.getErrorMessage(),
-          ResponseCode.UNAUTHORIZED.getResponseCode());
+      || (StringUtils.isEmpty(managedById)
+      && (!StringUtils.isBlank(userId) && !userId.equals(ctxtUserId))) // UPDATE
+      || (StringUtils.isNotEmpty(managedById)
+      && !(ctxtUserId.equals(managedById)))) // CREATE NEW USER/ UPDATE MUA {
+      throw new ProjectCommonException(
+        ResponseCode.unAuthorized.getErrorCode(),
+        ResponseCode.unAuthorized.getErrorMessage(),
+        ResponseCode.UNAUTHORIZED.getResponseCode());
   }
 
   @Override
   public Map<String, Object> esGetPublicUserProfileById(String userId, RequestContext context) {
     Future<Map<String, Object>> esResultF =
-        esUtil.getDataByIdentifier(ProjectUtil.EsType.user.getTypeName(), userId, context);
+      esUtil.getDataByIdentifier(ProjectUtil.EsType.user.getTypeName(), userId, context);
     Map<String, Object> esResult =
-        (Map<String, Object>) ElasticSearchHelper.getResponseFromFuture(esResultF);
+      (Map<String, Object>) ElasticSearchHelper.getResponseFromFuture(esResultF);
     if (esResult == null || esResult.size() == 0) {
       throw new ProjectCommonException(
-          ResponseCode.userNotFound.getErrorCode(),
-          ResponseCode.userNotFound.getErrorMessage(),
-          ResponseCode.RESOURCE_NOT_FOUND.getResponseCode());
+        ResponseCode.userNotFound.getErrorCode(),
+        ResponseCode.userNotFound.getErrorMessage(),
+        ResponseCode.RESOURCE_NOT_FOUND.getResponseCode());
     }
     return esResult;
   }
@@ -145,48 +146,48 @@ public class UserServiceImpl implements UserService {
     SearchDTO searchDTO = new SearchDTO();
     searchDTO.getAdditionalProperties().put(JsonKey.FILTERS, filters);
     Future<Map<String, Object>> esResultF =
-        esUtil.search(searchDTO, ProjectUtil.EsType.organisation.getTypeName(), context);
+      esUtil.search(searchDTO, ProjectUtil.EsType.organisation.getTypeName(), context);
     Map<String, Object> esResult =
-        (Map<String, Object>) ElasticSearchHelper.getResponseFromFuture(esResultF);
+      (Map<String, Object>) ElasticSearchHelper.getResponseFromFuture(esResultF);
     if (MapUtils.isNotEmpty(esResult)
-        && CollectionUtils.isNotEmpty((List) esResult.get(JsonKey.CONTENT))) {
+      && CollectionUtils.isNotEmpty((List) esResult.get(JsonKey.CONTENT))) {
       Map<String, Object> esContent =
-          ((List<Map<String, Object>>) esResult.get(JsonKey.CONTENT)).get(0);
+        ((List<Map<String, Object>>) esResult.get(JsonKey.CONTENT)).get(0);
       if (null != esContent.get(JsonKey.STATUS)) {
         int status = (int) esContent.get(JsonKey.STATUS);
         if (1 != status) {
           ProjectCommonException.throwClientErrorException(
-              ResponseCode.errorInactiveOrg,
-              ProjectUtil.formatMessage(
-                  ResponseCode.errorInactiveOrg.getErrorMessage(), JsonKey.CHANNEL, channel));
+            ResponseCode.errorInactiveOrg,
+            ProjectUtil.formatMessage(
+              ResponseCode.errorInactiveOrg.getErrorMessage(), JsonKey.CHANNEL, channel));
         }
       } else {
         ProjectCommonException.throwClientErrorException(
-            ResponseCode.errorInactiveOrg,
-            ProjectUtil.formatMessage(
-                ResponseCode.errorInactiveOrg.getErrorMessage(), JsonKey.CHANNEL, channel));
+          ResponseCode.errorInactiveOrg,
+          ProjectUtil.formatMessage(
+            ResponseCode.errorInactiveOrg.getErrorMessage(), JsonKey.CHANNEL, channel));
       }
       return (String) esContent.get(JsonKey.ID);
     } else {
       if (StringUtils.isNotBlank(channel)) {
         throw new ProjectCommonException(
-            ResponseCode.invalidParameterValue.getErrorCode(),
-            ProjectUtil.formatMessage(
-                ResponseCode.invalidParameterValue.getErrorMessage(), channel, JsonKey.CHANNEL),
-            ResponseCode.CLIENT_ERROR.getResponseCode());
+          ResponseCode.invalidParameterValue.getErrorCode(),
+          ProjectUtil.formatMessage(
+            ResponseCode.invalidParameterValue.getErrorMessage(), channel, JsonKey.CHANNEL),
+          ResponseCode.CLIENT_ERROR.getResponseCode());
       } else {
         throw new ProjectCommonException(
-            ResponseCode.mandatoryParamsMissing.getErrorCode(),
-            ProjectUtil.formatMessage(
-                ResponseCode.mandatoryParamsMissing.getErrorMessage(), JsonKey.CHANNEL),
-            ResponseCode.CLIENT_ERROR.getResponseCode());
+          ResponseCode.mandatoryParamsMissing.getErrorCode(),
+          ProjectUtil.formatMessage(
+            ResponseCode.mandatoryParamsMissing.getErrorMessage(), JsonKey.CHANNEL),
+          ResponseCode.CLIENT_ERROR.getResponseCode());
       }
     }
   }
 
   @Override
   public String getCustodianChannel(
-      Map<String, Object> userMap, ActorRef actorRef, RequestContext context) {
+    Map<String, Object> userMap, ActorRef actorRef, RequestContext context) {
     String channel = (String) userMap.get(JsonKey.CHANNEL);
     if (StringUtils.isBlank(channel)) {
       try {
@@ -195,19 +196,19 @@ public class UserServiceImpl implements UserService {
         if (StringUtils.isBlank(channel)) {
           SystemSettingClient client = SystemSettingClientImpl.getInstance();
           SystemSetting custodianOrgChannelSetting =
-              client.getSystemSettingByField(actorRef, JsonKey.CUSTODIAN_ORG_CHANNEL, context);
+            client.getSystemSettingByField(actorRef, JsonKey.CUSTODIAN_ORG_CHANNEL, context);
           if (custodianOrgChannelSetting != null
-              && StringUtils.isNotBlank(custodianOrgChannelSetting.getValue())) {
+            && StringUtils.isNotBlank(custodianOrgChannelSetting.getValue())) {
             configSettingMap.put(
-                custodianOrgChannelSetting.getId(), custodianOrgChannelSetting.getValue());
+              custodianOrgChannelSetting.getId(), custodianOrgChannelSetting.getValue());
             channel = custodianOrgChannelSetting.getValue();
           }
         }
       } catch (Exception ex) {
         logger.error(
-            context,
-            "getCustodianChannel: Exception occurred while fetching custodian channel from system setting.",
-            ex);
+          context,
+          "getCustodianChannel: Exception occurred while fetching custodian channel from system setting.",
+          ex);
       }
     }
     if (StringUtils.isBlank(channel)) {
@@ -216,10 +217,10 @@ public class UserServiceImpl implements UserService {
     }
     if (StringUtils.isBlank(channel)) {
       throw new ProjectCommonException(
-          ResponseCode.mandatoryParamsMissing.getErrorCode(),
-          ProjectUtil.formatMessage(
-              ResponseCode.mandatoryParamsMissing.getErrorMessage(), JsonKey.CHANNEL),
-          ResponseCode.CLIENT_ERROR.getResponseCode());
+        ResponseCode.mandatoryParamsMissing.getErrorCode(),
+        ProjectUtil.formatMessage(
+          ResponseCode.mandatoryParamsMissing.getErrorMessage(), JsonKey.CHANNEL),
+        ResponseCode.CLIENT_ERROR.getResponseCode());
     }
     return channel;
   }
@@ -247,9 +248,9 @@ public class UserServiceImpl implements UserService {
         encData = encryptionService.encryptData(data, context);
       } catch (Exception e) {
         logger.error(
-            context,
-            "UserServiceImpl:getEncryptedDataList: Exception occurred with error message ",
-            e);
+          context,
+          "UserServiceImpl:getEncryptedDataList: Exception occurred with error message ",
+          e);
       }
       if (StringUtils.isNotBlank(encData)) {
         encryptedDataList.add(encData);
@@ -260,24 +261,24 @@ public class UserServiceImpl implements UserService {
 
   @Override
   public List<String> generateUsernames(
-      String name, List<String> excludedUsernames, RequestContext context) {
+    String name, List<String> excludedUsernames, RequestContext context) {
     if (name == null || name.isEmpty()) return null;
     name = Slug.makeSlug(name, true);
     int numOfCharsToAppend =
-        Integer.valueOf(ProjectUtil.getConfigValue(JsonKey.SUNBIRD_USERNAME_NUM_DIGITS).trim());
+      Integer.valueOf(ProjectUtil.getConfigValue(JsonKey.SUNBIRD_USERNAME_NUM_DIGITS).trim());
     HashSet<String> userNameSet = new HashSet<>();
     int totalUserNameGenerated = 0;
     String nameLowercase = name.toLowerCase().replaceAll("\\-+", "");
     while (totalUserNameGenerated < GENERATE_USERNAME_COUNT) {
       String userNameSuffix =
-          RandomStringUtils.randomAlphanumeric(numOfCharsToAppend).toLowerCase();
+        RandomStringUtils.randomAlphanumeric(numOfCharsToAppend).toLowerCase();
 
       StringBuilder userNameSB = new StringBuilder();
       userNameSB.append(nameLowercase).append("_").append(userNameSuffix);
       String generatedUsername = userNameSB.toString();
 
       if (!userNameSet.contains(generatedUsername)
-          && !excludedUsernames.contains(generatedUsername)) {
+        && !excludedUsernames.contains(generatedUsername)) {
         userNameSet.add(generatedUsername);
         totalUserNameGenerated += 1;
       }
@@ -287,7 +288,7 @@ public class UserServiceImpl implements UserService {
 
   @Override
   public List<Map<String, Object>> searchUserNameInUserLookup(
-      List<String> encUserNameList, RequestContext context) {
+    List<String> encUserNameList, RequestContext context) {
 
     Map<String, Object> reqMap = new LinkedHashMap<>();
     reqMap.put(JsonKey.TYPE, JsonKey.USER_LOOKUP_FILED_USER_NAME);
@@ -298,7 +299,7 @@ public class UserServiceImpl implements UserService {
 
   @Override
   public Response userLookUpByKey(
-      String key, String value, List<String> fields, RequestContext context) {
+    String key, String value, List<String> fields, RequestContext context) {
     Response response;
     if (JsonKey.ID.equalsIgnoreCase(key)) {
       List<String> ids = new ArrayList<>(2);
@@ -306,18 +307,18 @@ public class UserServiceImpl implements UserService {
       response = userDao.getUserPropertiesById(ids, fields, context);
     } else {
       List<Map<String, Object>> records =
-          userLookupDao.getRecordByType(key.toLowerCase(), value.toLowerCase(), true, context);
+        userLookupDao.getRecordByType(key.toLowerCase(), value.toLowerCase(), true, context);
       List<String> ids = new ArrayList<>();
       records
-          .stream()
-          .forEach(
-              record -> {
-                ids.add((String) record.get(JsonKey.USER_ID));
-              });
+        .stream()
+        .forEach(
+          record -> {
+            ids.add((String) record.get(JsonKey.USER_ID));
+          });
       response = userDao.getUserPropertiesById(ids, fields, context);
     }
     for (Map<String, Object> userMap :
-        (List<Map<String, Object>>) response.getResult().get(JsonKey.RESPONSE)) {
+      (List<Map<String, Object>>) response.getResult().get(JsonKey.RESPONSE)) {
       UserUtility.decryptUserDataFrmES(userMap);
     }
     return response;
@@ -329,19 +330,19 @@ public class UserServiceImpl implements UserService {
     try {
       SystemSettingClient client = SystemSettingClientImpl.getInstance();
       SystemSetting systemSetting =
-          client.getSystemSettingByField(actorRef, JsonKey.CUSTODIAN_ORG_ID, context);
+        client.getSystemSettingByField(actorRef, JsonKey.CUSTODIAN_ORG_ID, context);
       if (null != systemSetting && StringUtils.isNotBlank(systemSetting.getValue())) {
         custodianOrgId = systemSetting.getValue();
       }
     } catch (Exception ex) {
       logger.error(
-          context,
-          "getCustodianOrgId: Exception occurred with error message = " + ex.getMessage(),
-          ex);
+        context,
+        "getCustodianOrgId: Exception occurred with error message = " + ex.getMessage(),
+        ex);
       ProjectCommonException.throwServerErrorException(
-          ResponseCode.errorSystemSettingNotFound,
-          ProjectUtil.formatMessage(
-              ResponseCode.errorSystemSettingNotFound.getErrorMessage(), JsonKey.CUSTODIAN_ORG_ID));
+        ResponseCode.errorSystemSettingNotFound,
+        ProjectUtil.formatMessage(
+          ResponseCode.errorSystemSettingNotFound.getErrorMessage(), JsonKey.CUSTODIAN_ORG_ID));
     }
     return custodianOrgId;
   }
@@ -355,22 +356,22 @@ public class UserServiceImpl implements UserService {
    * @return encryptedTokenList
    */
   public Map<String, Object> fetchEncryptedToken(
-      String parentId, List<Map<String, Object>> respList, RequestContext context) {
+    String parentId, List<Map<String, Object>> respList, RequestContext context) {
     Map<String, Object> encryptedTokenList = null;
     try {
       // create AdminUtilRequestData list of managedUserId and parentId
       List<AdminUtilRequestData> managedUsers = createManagedUserList(parentId, respList);
       // Fetch encrypted token list from admin utils
       encryptedTokenList =
-          AdminUtilHandler.fetchEncryptedToken(
-              AdminUtilHandler.prepareAdminUtilPayload(managedUsers), context);
+        AdminUtilHandler.fetchEncryptedToken(
+          AdminUtilHandler.prepareAdminUtilPayload(managedUsers), context);
     } catch (ProjectCommonException pe) {
       throw pe;
     } catch (Exception e) {
       throw new ProjectCommonException(
-          ResponseCode.unableToParseData.getErrorCode(),
-          ResponseCode.unableToParseData.getErrorMessage(),
-          ResponseCode.SERVER_ERROR.getResponseCode());
+        ResponseCode.unableToParseData.getErrorCode(),
+        ResponseCode.unableToParseData.getErrorMessage(),
+        ResponseCode.SERVER_ERROR.getResponseCode());
     }
     return encryptedTokenList;
   }
@@ -383,20 +384,20 @@ public class UserServiceImpl implements UserService {
    * @param context
    */
   public void appendEncryptedToken(
-      Map<String, Object> encryptedTokenList,
-      List<Map<String, Object>> respList,
-      RequestContext context) {
+    Map<String, Object> encryptedTokenList,
+    List<Map<String, Object>> respList,
+    RequestContext context) {
     ArrayList<Map<String, Object>> data =
-        (ArrayList<Map<String, Object>>) encryptedTokenList.get(JsonKey.DATA);
+      (ArrayList<Map<String, Object>>) encryptedTokenList.get(JsonKey.DATA);
     for (Object object : data) {
       Map<String, Object> tempMap = (Map<String, Object>) object;
       respList
-          .stream()
-          .filter(o -> o.get(JsonKey.ID).equals(tempMap.get(JsonKey.SUB)))
-          .forEach(
-              o -> {
-                o.put(JsonKey.MANAGED_TOKEN, tempMap.get(JsonKey.TOKEN));
-              });
+        .stream()
+        .filter(o -> o.get(JsonKey.ID).equals(tempMap.get(JsonKey.SUB)))
+        .forEach(
+          o -> {
+            o.put(JsonKey.MANAGED_TOKEN, tempMap.get(JsonKey.TOKEN));
+          });
     }
   }
 
@@ -409,15 +410,15 @@ public class UserServiceImpl implements UserService {
    * @return reqData List<AdminUtilRequestData>
    */
   private List<AdminUtilRequestData> createManagedUserList(
-      String parentId, List<Map<String, Object>> respList) {
+    String parentId, List<Map<String, Object>> respList) {
     return respList
-        .stream()
-        .map(p -> new AdminUtilRequestData(parentId, (String) p.get(JsonKey.ID)))
-        .collect(Collectors.toList());
+      .stream()
+      .map(p -> new AdminUtilRequestData(parentId, (String) p.get(JsonKey.ID)))
+      .collect(Collectors.toList());
   }
 
   public Response saveUserAttributes(
-      Map<String, Object> userMap, ActorRef actorRef, RequestContext context) {
+    Map<String, Object> userMap, ActorRef actorRef, RequestContext context) {
     Request request = new Request();
     request.setRequestContext(context);
     request.setOperation(UserActorOperations.SAVE_USER_ATTRIBUTES.getValue());
@@ -448,12 +449,70 @@ public class UserServiceImpl implements UserService {
         ResponseCode.userNotFound.getErrorMessage(),
         ResponseCode.RESOURCE_NOT_FOUND.getResponseCode());
     }
-    DecryptionService decService =
-      org.sunbird.datasecurity.impl.ServiceFactory.getDecryptionServiceInstance(null);
-    String emailPhone = decService.decryptData((String) user.get(type), context);
+    String emailPhone = getDecryptedValue((String) user.get(type), context);
     if (StringUtils.isBlank(emailPhone)) {
       ProjectCommonException.throwClientErrorException(ResponseCode.invalidRequestData);
     }
     return emailPhone;
   }
+
+  private String getDecryptedValue(String key, RequestContext context) {
+    if (StringUtils.isNotBlank(key)) {
+      DecryptionService decService =
+        org.sunbird.datasecurity.impl.ServiceFactory.getDecryptionServiceInstance(null);
+      return decService.decryptData(key, context);
+    }
+    return "";
+  }
+
+  /**
+   * This method will return either email or phone value of user based on the asked type in request
+   *
+   * @param userIds
+   * @param type value can be email, phone
+   * @return List<Map<String, Object>> i.e List of Map of userId, email/phone
+   */
+  @Override
+  public List<Map<String, Object>> getDecryptedEmailPhoneByUserIds(List<String> userIds, String type, RequestContext context) {
+    List<String> properties = new ArrayList<>();
+    properties.add(type);
+    properties.add(JsonKey.ID);
+    properties.add(JsonKey.FIRST_NAME);
+    properties.add(JsonKey.ROOT_ORG_ID);
+    Response  response = userDao.getUserPropertiesById(userIds, properties, context);
+    List<Map<String, Object>> responseList = (List<Map<String, Object>>)response.get(JsonKey.RESPONSE);
+    responseList.stream().forEach(resMap -> resMap.put(type, getDecryptedValue((String)resMap.get(type), context)));
+    return responseList;
+  }
+
+  @Override
+  public List<Map<String, Object>> getUserEmailsBySearchQuery(Map<String, Object> searchQuery, RequestContext context) {
+    Future<Map<String, Object>> esResultF =
+        esUtil.search(
+          ElasticSearchHelper.createSearchDTO(searchQuery),
+          ProjectUtil.EsType.user.getTypeName(),
+          context);
+    List<Map<String, Object>> usersList = new ArrayList<>();
+    Map<String, Object> esResult = (Map<String, Object>) ElasticSearchHelper.getResponseFromFuture(esResultF);
+    if (MapUtils.isNotEmpty(esResult)
+      && CollectionUtils.isNotEmpty((List) esResult.get(JsonKey.CONTENT))) {
+      usersList =
+        (List<Map<String, Object>>) esResult.get(JsonKey.CONTENT);
+      usersList.forEach(
+        user -> {
+          if (org.apache.commons.lang.StringUtils.isNotBlank((String) user.get(JsonKey.EMAIL))) {
+            String email = getDecryptedValue((String) user.get(JsonKey.EMAIL), context);
+            if (ProjectUtil.isEmailvalid(email)) {
+              user.put(JsonKey.EMAIL,email);
+            } else {
+              logger.info(
+                "UserServiceImpl:getUserEmailsBySearchQuery: Invalid Email or its decryption failed for userId = "
+                  + user.get(JsonKey.USER_ID));
+              user.put(JsonKey.EMAIL,null);
+            }
+          }
+        });
+    }
+    return usersList;
+  }
 }
diff --git a/service/src/test/java/org/sunbird/actor/notification/BackgroundNotificationActorTest.java b/service/src/test/java/org/sunbird/actor/notification/BackgroundNotificationActorTest.java
new file mode 100644
index 000000000..bbe77f458
--- /dev/null
+++ b/service/src/test/java/org/sunbird/actor/notification/BackgroundNotificationActorTest.java
@@ -0,0 +1,72 @@
+package org.sunbird.actor.notification;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.actor.Props;
+import akka.testkit.javadsl.TestKit;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.sunbird.actor.service.BaseMWService;
+import org.sunbird.actor.service.SunbirdMWService;
+import org.sunbird.cassandraimpl.CassandraOperationImpl;
+import org.sunbird.helper.ServiceFactory;
+import org.sunbird.http.HttpClientUtil;
+import org.sunbird.operations.ActorOperations;
+import org.sunbird.request.Request;
+import org.sunbird.response.Response;
+import org.sunbird.util.DataCacheHandler;
+import org.sunbird.util.ProjectUtil;
+import org.sunbird.util.Util;
+
+import static akka.testkit.JavaTestKit.duration;
+import static org.junit.Assert.assertTrue;
+import static org.powermock.api.mockito.PowerMockito.mock;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({
+  HttpClientUtil.class,
+  ProjectUtil.class,
+  BaseMWService.class
+})
+@PowerMockIgnore({
+  "javax.management.*",
+  "javax.net.ssl.*",
+  "javax.security.*",
+  "jdk.internal.reflect.*",
+  "javax.crypto.*"
+})
+public class BackgroundNotificationActorTest {
+
+  private static final Props props = Props.create(BackGroundNotificationActor.class);
+  private ActorSystem system = ActorSystem.create("system");
+
+  @BeforeClass
+  public static void setUp() {
+    PowerMockito.mockStatic(ProjectUtil.class);
+  }
+
+  @Before
+  public void beforeTest() {
+    PowerMockito.mockStatic(ProjectUtil.class);
+    PowerMockito.mockStatic(HttpClientUtil.class);
+  }
+
+  @Test
+  public void callNotificationServiceTest() {
+    TestKit probe = new TestKit(system);
+    ActorRef subject = system.actorOf(props);
+    Request reqObj = new Request();
+    reqObj.setOperation("processNotification");
+
+    subject.tell(reqObj, probe.getRef());
+    probe.expectNoMessage();
+  }
+
+}
diff --git a/service/src/test/java/org/sunbird/actor/notification/EmailServiceActorTest.java b/service/src/test/java/org/sunbird/actor/notification/EmailServiceActorTest.java
index 479fce6db..1a8017da2 100644
--- a/service/src/test/java/org/sunbird/actor/notification/EmailServiceActorTest.java
+++ b/service/src/test/java/org/sunbird/actor/notification/EmailServiceActorTest.java
@@ -1,19 +1,10 @@
 package org.sunbird.actor.notification;
 
-import static akka.testkit.JavaTestKit.duration;
-import static org.junit.Assert.assertTrue;
-import static org.powermock.api.mockito.PowerMockito.mock;
-import static org.powermock.api.mockito.PowerMockito.when;
-
 import akka.actor.ActorRef;
 import akka.actor.ActorSystem;
 import akka.actor.Props;
-import akka.dispatch.Futures;
 import akka.testkit.javadsl.TestKit;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -24,16 +15,10 @@ import org.powermock.core.classloader.annotations.PowerMockIgnore;
 import org.powermock.core.classloader.annotations.PrepareForTest;
 import org.powermock.modules.junit4.PowerMockRunner;
 import org.sunbird.actor.BackgroundOperations;
+import org.sunbird.actor.service.BaseMWService;
+import org.sunbird.actor.service.SunbirdMWService;
 import org.sunbird.cassandraimpl.CassandraOperationImpl;
-import org.sunbird.common.ElasticSearchHelper;
-import org.sunbird.common.ElasticSearchRestHighImpl;
-import org.sunbird.common.factory.EsClientFactory;
-import org.sunbird.common.inf.ElasticSearchService;
-import org.sunbird.dao.notification.impl.EmailTemplateDaoImpl;
-import org.sunbird.datasecurity.impl.DefaultDecryptionServiceImpl;
-import org.sunbird.datasecurity.impl.DefaultEncryptionServivceImpl;
 import org.sunbird.exception.ProjectCommonException;
-import org.sunbird.exception.ResponseCode;
 import org.sunbird.helper.ServiceFactory;
 import org.sunbird.keys.JsonKey;
 import org.sunbird.request.Request;
@@ -41,18 +26,25 @@ import org.sunbird.response.Response;
 import org.sunbird.util.DataCacheHandler;
 import org.sunbird.util.ProjectUtil;
 import org.sunbird.util.Util;
-import scala.concurrent.Promise;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static akka.testkit.JavaTestKit.duration;
+import static org.junit.Assert.assertTrue;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.when;
 
 @RunWith(PowerMockRunner.class)
 @PrepareForTest({
+  SunbirdMWService.class,
   ServiceFactory.class,
   Util.class,
   DataCacheHandler.class,
-  org.sunbird.datasecurity.impl.ServiceFactory.class,
-  ElasticSearchRestHighImpl.class,
-  EmailTemplateDaoImpl.class,
-  EsClientFactory.class,
-  ElasticSearchHelper.class
+  ProjectUtil.class,
+  BaseMWService.class
 })
 @PowerMockIgnore({
   "javax.management.*",
@@ -71,81 +63,30 @@ public class EmailServiceActorTest {
   private static final Props props = Props.create(EmailServiceActor.class);
   private ActorSystem system = ActorSystem.create("system");
   private static CassandraOperationImpl cassandraOperation;
-  private static DefaultDecryptionServiceImpl defaultDecryptionService;
-  private static DefaultEncryptionServivceImpl defaultEncryptionServivce;
-  private static EmailTemplateDaoImpl emailTemplateDao;
-  private ElasticSearchService esService;
 
   @BeforeClass
   public static void setUp() {
-
+    PowerMockito.mockStatic(SunbirdMWService.class);
+    SunbirdMWService.tellToBGRouter(Mockito.any(), Mockito.any());
+    PowerMockito.mockStatic(ProjectUtil.class);
     PowerMockito.mockStatic(ServiceFactory.class);
-    PowerMockito.mockStatic(EmailTemplateDaoImpl.class);
-    PowerMockito.mockStatic(org.sunbird.datasecurity.impl.ServiceFactory.class);
     cassandraOperation = mock(CassandraOperationImpl.class);
-    defaultDecryptionService = mock(DefaultDecryptionServiceImpl.class);
-    defaultEncryptionServivce = mock(DefaultEncryptionServivceImpl.class);
-    emailTemplateDao = mock(EmailTemplateDaoImpl.class);
   }
 
   @Before
   public void beforeTest() {
-
+    PowerMockito.mockStatic(SunbirdMWService.class);
+    SunbirdMWService.tellToBGRouter(Mockito.any(), Mockito.any());
+    PowerMockito.mockStatic(ProjectUtil.class);
     PowerMockito.mockStatic(ServiceFactory.class);
-    PowerMockito.mockStatic(ElasticSearchHelper.class);
-    esService = mock(ElasticSearchRestHighImpl.class);
-    PowerMockito.mockStatic(EsClientFactory.class);
-    when(EsClientFactory.getInstance(Mockito.anyString())).thenReturn(esService);
-    PowerMockito.mockStatic(org.sunbird.datasecurity.impl.ServiceFactory.class);
-    PowerMockito.mockStatic(EmailTemplateDaoImpl.class);
     when(ServiceFactory.getInstance()).thenReturn(cassandraOperation);
-    when(org.sunbird.datasecurity.impl.ServiceFactory.getDecryptionServiceInstance(null))
-        .thenReturn(defaultDecryptionService);
-    when(org.sunbird.datasecurity.impl.ServiceFactory.getEncryptionServiceInstance(null))
-        .thenReturn(defaultEncryptionServivce);
     when(cassandraOperation.getRecordsByIdsWithSpecifiedColumns(
-            Mockito.anyString(),
-            Mockito.anyString(),
-            Mockito.anyList(),
-            Mockito.anyList(),
-            Mockito.any()))
-        .thenReturn(cassandraGetRecordById());
-
-    when(cassandraOperation.getRecordById(
-            Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.any()))
-        .thenReturn(cassandraGetRecordById());
-
-    emailTemplateDao = mock(EmailTemplateDaoImpl.class);
-    when(EmailTemplateDaoImpl.getInstance()).thenReturn(emailTemplateDao);
-    when(emailTemplateDao.getTemplate(Mockito.anyString(), Mockito.any()))
-        .thenReturn("templateName");
-
-    Map<String, Object> recipientSearchQuery = new HashMap<>();
-    recipientSearchQuery.put(JsonKey.FILTERS, "anyName");
-    recipientSearchQuery.put(JsonKey.ROOT_ORG_ID, "anyRootId");
-    Map<String, Object> esOrgResult = new HashMap<>();
-    esOrgResult.put(JsonKey.ORGANISATION_NAME, "anyOrgName");
-    Promise<Map<String, Object>> promise = Futures.promise();
-    promise.success(createGetSkillResponse());
-    when(esService.search(
-            Mockito.eq(ElasticSearchHelper.createSearchDTO(recipientSearchQuery)),
-            Mockito.eq(ProjectUtil.EsType.user.getTypeName()),
-            Mockito.any()))
-        .thenReturn(promise.future());
-    Promise<Map<String, Object>> promise_recipientSearchQuery = Futures.promise();
-
-    promise_recipientSearchQuery.trySuccess(recipientSearchQuery);
-    when(esService.getDataByIdentifier(
-            Mockito.eq(ProjectUtil.EsType.user.getTypeName()), Mockito.eq("001"), Mockito.any()))
-        .thenReturn(promise_recipientSearchQuery.future());
-
-    Promise<Map<String, Object>> promise_esOrgResult = Futures.promise();
-    promise_esOrgResult.trySuccess(esOrgResult);
-    when(esService.getDataByIdentifier(
-            Mockito.eq(ProjectUtil.EsType.organisation.getTypeName()),
-            Mockito.eq("anyRootId"),
-            Mockito.any()))
-        .thenReturn(promise_esOrgResult.future());
+      Mockito.anyString(),
+      Mockito.anyString(),
+      Mockito.anyList(),
+      Mockito.anyList(),
+      Mockito.any()))
+      .thenReturn(cassandraGetRecordById());
   }
 
   private static Response cassandraGetRecordById() {
@@ -153,280 +94,105 @@ public class EmailServiceActorTest {
     List<Map<String, Object>> list = new ArrayList();
     Map<String, Object> map = new HashMap<>();
     map.put(JsonKey.ID, "anyId");
-    map.put(JsonKey.EMAIL, "anyEmailId");
-    map.put(JsonKey.ROOT_ORG_ID, "1234567890");
-    map.put(JsonKey.FIRST_NAME, "firstName");
-    map.put(JsonKey.ORG_NAME, "orgName");
+    map.put(JsonKey.EMAIL, "xyz@xyz.com");
+    map.put(JsonKey.PHONE, "9999999999");
+    map.put("template", "some template Id");
     list.add(map);
     response.put(JsonKey.RESPONSE, list);
     return response;
   }
 
-  private static Map<String, Object> createGetSkillResponse() {
-    HashMap<String, Object> response = new HashMap<>();
-    List<Map<String, Object>> content = new ArrayList<>();
-    HashMap<String, Object> innerMap = new HashMap<>();
-    innerMap.put(JsonKey.EMAIL, "anyEmailId");
-    content.add(innerMap);
-    response.put(JsonKey.CONTENT, content);
-    return response;
-  }
 
   @Test
-  public void testSendEmailSuccess() {
-
+  public void testSendSMSSuccess() {
+    when(cassandraOperation.getPropertiesValueById(
+      Mockito.anyString(),
+      Mockito.anyString(),
+      Mockito.anyList(),
+      Mockito.anyList(),
+      Mockito.any()))
+      .thenReturn(cassandraGetRecordById());
+    when(cassandraOperation.getRecordsByPrimaryKeys(
+      Mockito.anyString(),
+      Mockito.anyString(),
+      Mockito.anyList(),
+      Mockito.anyString(),
+      Mockito.any()))
+      .thenReturn(cassandraGetRecordById());
+    PowerMockito.mockStatic(SunbirdMWService.class);
+    SunbirdMWService.tellToBGRouter(Mockito.any(), Mockito.any());
+    PowerMockito.mockStatic(BaseMWService.class);
+    BaseMWService.getRemoteRouter(Mockito.anyString());
     TestKit probe = new TestKit(system);
     ActorRef subject = system.actorOf(props);
     Request reqObj = new Request();
     reqObj.setOperation(BackgroundOperations.emailService.name());
 
     HashMap<String, Object> innerMap = new HashMap<>();
-    Map<String, Object> pageMap = new HashMap<String, Object>();
-    List<String> emailIdList = new ArrayList<>();
-    emailIdList.add("aaa@gmail.com");
+    Map<String, Object> reqMap = new HashMap<>();
     List<String> userIdList = new ArrayList<>();
     userIdList.add("001");
-    Map<String, Object> queryMap = new HashMap<>();
-    Map<String, Object> filterMap = new HashMap<>();
-    filterMap.put(JsonKey.NAME, "anyName");
-    queryMap.put(JsonKey.FILTERS, filterMap);
-    pageMap.put(JsonKey.RECIPIENT_EMAILS, emailIdList);
-    pageMap.put(JsonKey.RECIPIENT_SEARCH_QUERY, queryMap);
-    pageMap.put(JsonKey.EMAIL_TEMPLATE_TYPE, "default");
-    innerMap.put(JsonKey.EMAIL_REQUEST, pageMap);
-    innerMap.put(JsonKey.RECIPIENT_USERIDS, userIdList);
-    innerMap.put(JsonKey.RECIPIENT_SEARCH_QUERY, queryMap);
-    reqObj.setRequest(innerMap);
-    subject.tell(reqObj, probe.getRef());
-    Response response = probe.expectMsgClass(duration("10 second"), Response.class);
-    assertTrue(response != null);
-  }
-
-  @Test
-  public void testEmailSuccess() {
+    reqMap.put(JsonKey.EMAIL_TEMPLATE_TYPE, "default");
+    reqMap.put(JsonKey.RECIPIENT_USERIDS, userIdList);
+    List<String> phoneList = new ArrayList<>();
+    reqMap.put(JsonKey.RECIPIENT_PHONES, phoneList);
+    reqMap.put(JsonKey.MODE,"sms");
+    innerMap.put(JsonKey.EMAIL_REQUEST, reqMap);
 
-    TestKit probe = new TestKit(system);
-    ActorRef subject = system.actorOf(props);
-    Request reqObj = new Request();
-    reqObj.setOperation(BackgroundOperations.emailService.name());
-
-    Map<String, Object> innerMap = new HashMap<>();
-    Map<String, Object> pageMap = new HashMap<String, Object>();
-    List<String> userIdList = new ArrayList<>();
-    userIdList.add("001");
-    innerMap.put(JsonKey.EMAIL_REQUEST, pageMap);
-    pageMap.put(JsonKey.RECIPIENT_USERIDS, userIdList);
-    pageMap.put(JsonKey.FIRST_NAME, "Name");
-    pageMap.put(JsonKey.EMAIL_TEMPLATE_TYPE, "default");
     reqObj.setRequest(innerMap);
     subject.tell(reqObj, probe.getRef());
-    Response response = probe.expectMsgClass(duration("10 second"), Response.class);
+    Response response = probe.expectMsgClass(duration("10000 second"), Response.class);
     assertTrue(response != null);
   }
 
   @Test
-  public void testSendEmailFailureWithInvalidParameterValue() {
-
-    TestKit probe = new TestKit(system);
-    ActorRef subject = system.actorOf(props);
-    Request reqObj = new Request();
-    reqObj.setOperation(BackgroundOperations.emailService.name());
-
-    HashMap<String, Object> innerMap = new HashMap<>();
-    Map<String, Object> pageMap = new HashMap<String, Object>();
-    List<String> emailIdList = new ArrayList<>();
-    emailIdList.add("aaa");
-    List<String> userIdList = new ArrayList<>();
-    userIdList.add("001");
-    Map<String, Object> queryMap = new HashMap<>();
-    Map<String, Object> filterMap = new HashMap<>();
-    queryMap.put(JsonKey.FILTERS, filterMap);
-    pageMap.put(JsonKey.RECIPIENT_EMAILS, emailIdList);
-    pageMap.put(JsonKey.RECIPIENT_SEARCH_QUERY, queryMap);
-    innerMap.put(JsonKey.EMAIL_REQUEST, pageMap);
-    innerMap.put(JsonKey.RECIPIENT_USERIDS, userIdList);
-    innerMap.put(JsonKey.RECIPIENT_SEARCH_QUERY, queryMap);
-    reqObj.setRequest(innerMap);
-    subject.tell(reqObj, probe.getRef());
-    ProjectCommonException exc =
-        probe.expectMsgClass(duration("10 second"), ProjectCommonException.class);
-    assertTrue(exc.getCode().equals(ResponseCode.invalidParameterValue.getErrorCode()));
-  }
-
-  @Test
-  public void testSendEmailFailureWithEmptyFilters() {
-
-    TestKit probe = new TestKit(system);
-    ActorRef subject = system.actorOf(props);
-    Request reqObj = new Request();
-    reqObj.setOperation(BackgroundOperations.emailService.name());
-
-    HashMap<String, Object> innerMap = new HashMap<>();
-    Map<String, Object> pageMap = new HashMap<String, Object>();
-    List<String> emailIdList = new ArrayList<>();
-    emailIdList.add("aaa@gmail.com");
-    List<String> userIdList = new ArrayList<>();
-    userIdList.add("001");
-    Map<String, Object> queryMap = new HashMap<>();
-    Map<String, Object> filterMap = new HashMap<>();
-    queryMap.put(JsonKey.FILTERS, filterMap);
-    pageMap.put(JsonKey.RECIPIENT_EMAILS, emailIdList);
-    pageMap.put(JsonKey.RECIPIENT_SEARCH_QUERY, queryMap);
-    innerMap.put(JsonKey.EMAIL_REQUEST, pageMap);
-    innerMap.put(JsonKey.RECIPIENT_USERIDS, userIdList);
-    innerMap.put(JsonKey.RECIPIENT_SEARCH_QUERY, queryMap);
-    reqObj.setRequest(innerMap);
-    subject.tell(reqObj, probe.getRef());
-    ProjectCommonException exc =
-        probe.expectMsgClass(duration("10 second"), ProjectCommonException.class);
-    assertTrue(exc.getCode().equals(ResponseCode.invalidParameterValue.getErrorCode()));
-  }
-
-  @Test
-  public void testSendEmailFailureWithEmailSizeExceeding() {
-
-    TestKit probe = new TestKit(system);
-    ActorRef subject = system.actorOf(props);
-    Request reqObj = new Request();
-    reqObj.setOperation(BackgroundOperations.emailService.name());
-
-    HashMap<String, Object> innerMap = new HashMap<>();
-    Map<String, Object> pageMap = new HashMap<String, Object>();
-    List<String> emailIdList = new ArrayList<>();
-
-    for (int i = 0; i < 40; i++) {
-      emailIdList.add("aaa" + i + "@gmail.com");
-      emailIdList.add("bbb" + i + "@gmail.com");
-      emailIdList.add("ccc" + i + "@gmail.com");
-    }
-    List<String> userIdList = new ArrayList<>();
-    userIdList.add("001");
-    Map<String, Object> queryMap = new HashMap<>();
-    Map<String, Object> filterMap = new HashMap<>();
-    filterMap.put(JsonKey.NAME, "anyName");
-    queryMap.put(JsonKey.FILTERS, filterMap);
-    pageMap.put(JsonKey.RECIPIENT_EMAILS, emailIdList);
-    pageMap.put(JsonKey.RECIPIENT_SEARCH_QUERY, queryMap);
-    innerMap.put(JsonKey.EMAIL_REQUEST, pageMap);
-    innerMap.put(JsonKey.RECIPIENT_USERIDS, userIdList);
-    innerMap.put(JsonKey.RECIPIENT_SEARCH_QUERY, queryMap);
-    reqObj.setRequest(innerMap);
-    Promise<Map<String, Object>> promise = Futures.promise();
-    promise.success(createGetSkillResponse());
-
-    when(esService.search(
-            Mockito.eq(ElasticSearchHelper.createSearchDTO(new HashMap<>())),
-            Mockito.eq(ProjectUtil.EsType.user.getTypeName()),
-            Mockito.any()))
-        .thenReturn(promise.future());
-
-    subject.tell(reqObj, probe.getRef());
-    ProjectCommonException exc =
-        probe.expectMsgClass(duration("10 second"), ProjectCommonException.class);
-    assertTrue(
-        exc.getCode().equals(ResponseCode.emailNotSentRecipientsExceededMaxLimit.getErrorCode()));
-  }
-
-  @Test
-  public void testSendEmailFailureWithBlankTemplateName() {
-
-    TestKit probe = new TestKit(system);
-    ActorRef subject = system.actorOf(props);
-    Request reqObj = new Request();
-    reqObj.setOperation(BackgroundOperations.emailService.name());
-
-    HashMap<String, Object> innerMap = new HashMap<>();
-    Map<String, Object> pageMap = new HashMap<String, Object>();
-    List<String> emailIdList = new ArrayList<>();
-    emailIdList.add("aaa@gmail.com");
-    List<String> userIdList = new ArrayList<>();
-    userIdList.add("001");
-    Map<String, Object> queryMap = new HashMap<>();
-    Map<String, Object> filterMap = new HashMap<>();
-    filterMap.put(JsonKey.NAME, "anyName");
-    queryMap.put(JsonKey.FILTERS, filterMap);
-    pageMap.put(JsonKey.RECIPIENT_EMAILS, emailIdList);
-    pageMap.put(JsonKey.RECIPIENT_SEARCH_QUERY, queryMap);
-    innerMap.put(JsonKey.EMAIL_REQUEST, pageMap);
-    innerMap.put(JsonKey.RECIPIENT_USERIDS, userIdList);
-    innerMap.put(JsonKey.RECIPIENT_SEARCH_QUERY, queryMap);
-    reqObj.setRequest(innerMap);
-    when(emailTemplateDao.getTemplate(Mockito.anyString(), Mockito.any())).thenReturn("");
-    subject.tell(reqObj, probe.getRef());
-    ProjectCommonException exc =
-        probe.expectMsgClass(duration("10 second"), ProjectCommonException.class);
-    assertTrue(exc.getCode().equals(ResponseCode.invalidParameterValue.getErrorCode()));
-  }
-
-  @Test
-  public void testSendEmailFailureWithInvalidUserIdInList() {
-
+  public void testSendEmailSuccess() {
+    when(cassandraOperation.getPropertiesValueById(
+      Mockito.anyString(),
+      Mockito.anyString(),
+      Mockito.anyList(),
+      Mockito.anyList(),
+      Mockito.any()))
+      .thenReturn(cassandraGetRecordById());
+    when(cassandraOperation.getRecordsByPrimaryKeys(
+      Mockito.anyString(),
+      Mockito.anyString(),
+      Mockito.anyList(),
+      Mockito.anyString(),
+      Mockito.any()))
+      .thenReturn(cassandraGetRecordById());
+    PowerMockito.mockStatic(SunbirdMWService.class);
+    SunbirdMWService.tellToBGRouter(Mockito.any(), Mockito.any());
+    PowerMockito.mockStatic(BaseMWService.class);
+    BaseMWService.getRemoteRouter(Mockito.anyString());
     TestKit probe = new TestKit(system);
     ActorRef subject = system.actorOf(props);
     Request reqObj = new Request();
     reqObj.setOperation(BackgroundOperations.emailService.name());
 
     HashMap<String, Object> innerMap = new HashMap<>();
-    Map<String, Object> pageMap = new HashMap<String, Object>();
-    List<String> emailIdList = new ArrayList<>();
-    emailIdList.add("aaa@gmail.com");
+    Map<String, Object> reqMap = new HashMap<>();
     List<String> userIdList = new ArrayList<>();
     userIdList.add("001");
-    userIdList.add("002");
-    Map<String, Object> queryMap = new HashMap<>();
-    Map<String, Object> filterMap = new HashMap<>();
-    queryMap.put(JsonKey.FILTERS, filterMap);
-    pageMap.put(JsonKey.RECIPIENT_EMAILS, emailIdList);
+    reqMap.put(JsonKey.EMAIL_TEMPLATE_TYPE, "default");
+    reqMap.put(JsonKey.RECIPIENT_USERIDS, userIdList);
+    reqMap.put(JsonKey.MODE,"email");
+    innerMap.put(JsonKey.EMAIL_REQUEST, reqMap);
 
-    Map<String, Object> searchQueryMap = new HashMap<>();
-    Map<String, Object> userIdMap = new HashMap<>();
-    userIdMap.put(JsonKey.RECIPIENT_USERIDS, userIdList);
-    userIdMap.put(JsonKey.RECIPIENT_SEARCH_QUERY, searchQueryMap);
-    innerMap.put(JsonKey.EMAIL_REQUEST, userIdMap);
-
-    innerMap.put(JsonKey.RECIPIENT_SEARCH_QUERY, queryMap);
     reqObj.setRequest(innerMap);
     subject.tell(reqObj, probe.getRef());
-    ProjectCommonException exc =
-        probe.expectMsgClass(duration("10 second"), ProjectCommonException.class);
-    assertTrue(exc.getCode().equals(ResponseCode.invalidParameterValue.getErrorCode()));
+    Response response = probe.expectMsgClass(duration("10000 second"), Response.class);
+    assertTrue(response != null);
   }
 
   @Test
-  public void testSendEmailFailureWithElasticSearchException() {
-
+  public void testWithInvalidRequest() {
+    Request request = new Request();
     TestKit probe = new TestKit(system);
     ActorRef subject = system.actorOf(props);
-    Request reqObj = new Request();
-    reqObj.setOperation(BackgroundOperations.emailService.name());
-
-    HashMap<String, Object> innerMap = new HashMap<>();
-    Map<String, Object> pageMap = new HashMap<String, Object>();
-    List<String> emailIdList = new ArrayList<>();
-    emailIdList.add("aaa@gmail.com");
-    List<String> userIdList = new ArrayList<>();
-    userIdList.add("001");
-    Map<String, Object> queryMap = new HashMap<>();
-    Map<String, Object> filterMap = new HashMap<>();
-    filterMap.put(JsonKey.NAME, "anyName");
-    queryMap.put(JsonKey.FILTERS, filterMap);
-    pageMap.put(JsonKey.RECIPIENT_EMAILS, emailIdList);
-    pageMap.put(JsonKey.RECIPIENT_SEARCH_QUERY, queryMap);
-    innerMap.put(JsonKey.EMAIL_REQUEST, pageMap);
-    innerMap.put(JsonKey.RECIPIENT_USERIDS, userIdList);
-    innerMap.put(JsonKey.RECIPIENT_SEARCH_QUERY, queryMap);
-    reqObj.setRequest(innerMap);
-    when(esService.search(
-            Mockito.eq(ElasticSearchHelper.createSearchDTO(new HashMap<>())),
-            Mockito.eq(ProjectUtil.EsType.user.getTypeName()),
-            Mockito.any()))
-        .thenThrow(new ProjectCommonException("", "", 0));
-    when(ElasticSearchHelper.getResponseFromFuture(Mockito.any()))
-        .thenThrow(new ProjectCommonException("", "", 0));
-
-    subject.tell(reqObj, probe.getRef());
-    ProjectCommonException exc =
-        probe.expectMsgClass(duration("10 second"), ProjectCommonException.class);
-    assertTrue(exc.getCode().equals(ResponseCode.invalidParameterValue.getErrorCode()));
+    request.setOperation("invalidOperation");
+    subject.tell(request, probe.getRef());
+    ProjectCommonException exception = probe.expectMsgClass(duration("10 second"), ProjectCommonException.class);
+    Assert.assertNotNull(exception);
   }
 }
diff --git a/service/src/test/java/org/sunbird/actor/notification/SendNotificationActorTest.java b/service/src/test/java/org/sunbird/actor/notification/SendNotificationActorTest.java
index 279a9615d..ee3b8577b 100644
--- a/service/src/test/java/org/sunbird/actor/notification/SendNotificationActorTest.java
+++ b/service/src/test/java/org/sunbird/actor/notification/SendNotificationActorTest.java
@@ -1,19 +1,11 @@
 package org.sunbird.actor.notification;
 
-import static akka.testkit.JavaTestKit.duration;
-import static org.junit.Assert.assertTrue;
-import static org.powermock.api.mockito.PowerMockito.mock;
-import static org.powermock.api.mockito.PowerMockito.when;
-
 import akka.actor.ActorRef;
 import akka.actor.ActorSystem;
 import akka.actor.Props;
 import akka.testkit.javadsl.TestKit;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
 import org.apache.velocity.VelocityContext;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -26,9 +18,6 @@ import org.powermock.modules.junit4.PowerMockRunner;
 import org.sunbird.actor.service.BaseMWService;
 import org.sunbird.actor.service.SunbirdMWService;
 import org.sunbird.cassandraimpl.CassandraOperationImpl;
-import org.sunbird.common.inf.ElasticSearchService;
-import org.sunbird.dao.notification.impl.EmailTemplateDaoImpl;
-import org.sunbird.datasecurity.impl.DefaultDecryptionServiceImpl;
 import org.sunbird.exception.ProjectCommonException;
 import org.sunbird.exception.ResponseCode;
 import org.sunbird.helper.ServiceFactory;
@@ -41,13 +30,23 @@ import org.sunbird.util.DataCacheHandler;
 import org.sunbird.util.ProjectUtil;
 import org.sunbird.util.Util;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static akka.testkit.JavaTestKit.duration;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.when;
+
 @RunWith(PowerMockRunner.class)
 @PrepareForTest({
   ServiceFactory.class,
   Util.class,
   DataCacheHandler.class,
-  org.sunbird.datasecurity.impl.ServiceFactory.class,
-  EmailTemplateDaoImpl.class,
   SunbirdMWService.class,
   HttpClientUtil.class,
   ProjectUtil.class,
@@ -65,9 +64,6 @@ public class SendNotificationActorTest {
   private static final Props props = Props.create(SendNotificationActor.class);
   private ActorSystem system = ActorSystem.create("system");
   private static CassandraOperationImpl cassandraOperation;
-  private static DefaultDecryptionServiceImpl defaultDecryptionService;
-  private static EmailTemplateDaoImpl emailTemplateDao;
-  private ElasticSearchService esService;
 
   @BeforeClass
   public static void setUp() {
@@ -75,11 +71,7 @@ public class SendNotificationActorTest {
     SunbirdMWService.tellToBGRouter(Mockito.any(), Mockito.any());
     PowerMockito.mockStatic(ProjectUtil.class);
     PowerMockito.mockStatic(ServiceFactory.class);
-    PowerMockito.mockStatic(EmailTemplateDaoImpl.class);
-    PowerMockito.mockStatic(org.sunbird.datasecurity.impl.ServiceFactory.class);
     cassandraOperation = mock(CassandraOperationImpl.class);
-    defaultDecryptionService = mock(DefaultDecryptionServiceImpl.class);
-    emailTemplateDao = mock(EmailTemplateDaoImpl.class);
   }
 
   @Before
@@ -89,11 +81,7 @@ public class SendNotificationActorTest {
     PowerMockito.mockStatic(ProjectUtil.class);
     PowerMockito.mockStatic(ServiceFactory.class);
     PowerMockito.mockStatic(HttpClientUtil.class);
-    PowerMockito.mockStatic(org.sunbird.datasecurity.impl.ServiceFactory.class);
-    PowerMockito.mockStatic(EmailTemplateDaoImpl.class);
     when(ServiceFactory.getInstance()).thenReturn(cassandraOperation);
-    when(org.sunbird.datasecurity.impl.ServiceFactory.getDecryptionServiceInstance(null))
-        .thenReturn(defaultDecryptionService);
     when(cassandraOperation.getRecordsByIdsWithSpecifiedColumns(
             Mockito.anyString(),
             Mockito.anyString(),
@@ -101,11 +89,6 @@ public class SendNotificationActorTest {
             Mockito.anyList(),
             Mockito.any()))
         .thenReturn(cassandraGetRecordById());
-
-    emailTemplateDao = mock(EmailTemplateDaoImpl.class);
-    when(EmailTemplateDaoImpl.getInstance()).thenReturn(emailTemplateDao);
-    when(emailTemplateDao.getTemplate(Mockito.anyString(), Mockito.any()))
-        .thenReturn("templateName");
   }
 
   private static Response cassandraGetRecordById() {
@@ -113,7 +96,9 @@ public class SendNotificationActorTest {
     List<Map<String, Object>> list = new ArrayList();
     Map<String, Object> map = new HashMap<>();
     map.put(JsonKey.ID, "anyId");
-    map.put(JsonKey.EMAIL, "anyEmailId");
+    map.put(JsonKey.EMAIL, "xyz@xyz.com");
+    map.put(JsonKey.PHONE, "9999999999");
+    map.put("template","some template Id");
     list.add(map);
     response.put(JsonKey.RESPONSE, list);
     return response;
@@ -132,6 +117,21 @@ public class SendNotificationActorTest {
 
   @Test
   public void testSendEmailSuccess() {
+    when(cassandraOperation.getPropertiesValueById(
+      Mockito.anyString(),
+      Mockito.anyString(),
+      Mockito.anyList(),
+      Mockito.anyList(),
+      Mockito.any()))
+      .thenReturn(cassandraGetRecordById());
+    when(cassandraOperation.getRecordsByPrimaryKeys(
+      Mockito.anyString(),
+      Mockito.anyString(),
+      Mockito.anyList(),
+      Mockito.anyString(),
+      Mockito.any()))
+      .thenReturn(cassandraGetRecordById());
+
     PowerMockito.mockStatic(SunbirdMWService.class);
     SunbirdMWService.tellToBGRouter(Mockito.any(), Mockito.any());
     PowerMockito.mockStatic(BaseMWService.class);
@@ -163,18 +163,29 @@ public class SendNotificationActorTest {
     PowerMockito.mockStatic(SunbirdMWService.class);
     SunbirdMWService.tellToBGRouter(Mockito.any(), Mockito.any());
     PowerMockito.mockStatic(BaseMWService.class);
-    when(cassandraOperation.getRecordsByIdsWithSpecifiedColumns(
-            Mockito.anyString(),
-            Mockito.anyString(),
-            Mockito.anyList(),
-            Mockito.anyList(),
-            Mockito.any()))
-        .thenReturn(cassandraGetEmptyRecordById());
+    when(cassandraOperation.getPropertiesValueById(
+      Mockito.anyString(),
+      Mockito.anyString(),
+      Mockito.anyList(),
+      Mockito.anyList(),
+      Mockito.any()))
+      .thenReturn(cassandraGetRecordById());
+    when(cassandraOperation.getRecordsByPrimaryKeys(
+      Mockito.anyString(),
+      Mockito.anyString(),
+      Mockito.anyList(),
+      Mockito.anyString(),
+      Mockito.any()))
+      .thenReturn(cassandraGetEmptyRecordById());
     TestKit probe = new TestKit(system);
     ActorRef subject = system.actorOf(props);
     Request reqObj = new Request();
     reqObj.setOperation(ActorOperations.V2_NOTIFICATION.getValue());
-
+    VelocityContext context = PowerMockito.mock(VelocityContext.class);
+    when(ProjectUtil.getContext(Mockito.anyMap())).thenReturn(context);
+    Object[] arr = new Object[1];
+    arr[0] = "name";
+    when(context.getKeys()).thenReturn(arr);
     HashMap<String, Object> innerMap = new HashMap<>();
     Map<String, Object> reqMap = new HashMap<String, Object>();
     List<String> userIdList = new ArrayList<>();
@@ -186,63 +197,93 @@ public class SendNotificationActorTest {
     subject.tell(reqObj, probe.getRef());
     ProjectCommonException exc =
         probe.expectMsgClass(duration("10 second"), ProjectCommonException.class);
-    assertTrue(exc.getCode().equals(ResponseCode.notificationNotSent.getErrorCode()));
+    assertTrue(exc.getCode().equals(ResponseCode.invalidParameterValue.getErrorCode()));
   }
 
   @Test
-  public void testSendEmailFailureWithBlankTemplateName() {
-
+  public void testSendEmailFailureWithInvalidUserIdInList() {
+    PowerMockito.mockStatic(SunbirdMWService.class);
+    SunbirdMWService.tellToBGRouter(Mockito.any(), Mockito.any());
+    when(cassandraOperation.getPropertiesValueById(
+      Mockito.anyString(),
+      Mockito.anyString(),
+      Mockito.anyList(),
+      Mockito.anyList(),
+      Mockito.any()))
+      .thenReturn(cassandraGetEmptyRecordById());
+    when(cassandraOperation.getRecordsByPrimaryKeys(
+      Mockito.anyString(),
+      Mockito.anyString(),
+      Mockito.anyList(),
+      Mockito.anyString(),
+      Mockito.any()))
+      .thenReturn(cassandraGetRecordById());
     TestKit probe = new TestKit(system);
     ActorRef subject = system.actorOf(props);
     Request reqObj = new Request();
     reqObj.setOperation(ActorOperations.V2_NOTIFICATION.getValue());
-
+    VelocityContext context = PowerMockito.mock(VelocityContext.class);
+    when(ProjectUtil.getContext(Mockito.anyMap())).thenReturn(context);
+    Object[] arr = new Object[1];
+    arr[0] = "name";
+    when(context.getKeys()).thenReturn(arr);
     HashMap<String, Object> innerMap = new HashMap<>();
-    Map<String, Object> reqMap = new HashMap<String, Object>();
+    List<String> emailIdList = new ArrayList<>();
+    emailIdList.add("aaa@gmail.com");
     List<String> userIdList = new ArrayList<>();
     userIdList.add("001");
-    reqMap.put(JsonKey.RECIPIENT_USERIDS, userIdList);
-    innerMap.put(JsonKey.EMAIL_REQUEST, reqMap);
-    reqObj.setRequest(innerMap);
+    userIdList.add("002");
+    Map<String, Object> userIdMap = new HashMap<>();
+    userIdMap.put(JsonKey.RECIPIENT_USERIDS, userIdList);
+    innerMap.put(JsonKey.EMAIL_REQUEST, userIdMap);
 
-    when(emailTemplateDao.getTemplate(Mockito.anyString(), Mockito.any())).thenReturn("");
+    reqObj.setRequest(innerMap);
     subject.tell(reqObj, probe.getRef());
     ProjectCommonException exc =
         probe.expectMsgClass(duration("10 second"), ProjectCommonException.class);
-    assertTrue(exc.getCode().equals(ResponseCode.invalidParameterValue.getErrorCode()));
+    assertEquals(ResponseCode.invalidParameterValue.getErrorCode(),exc.getCode());
   }
 
   @Test
-  public void testSendEmailFailureWithInvalidUserIdInList() {
+  public void testSendSMSSuccess() {
+    when(cassandraOperation.getPropertiesValueById(
+      Mockito.anyString(),
+      Mockito.anyString(),
+      Mockito.anyList(),
+      Mockito.anyList(),
+      Mockito.any()))
+      .thenReturn(cassandraGetRecordById());
+
     PowerMockito.mockStatic(SunbirdMWService.class);
     SunbirdMWService.tellToBGRouter(Mockito.any(), Mockito.any());
-    when(cassandraOperation.getRecordsByIdsWithSpecifiedColumns(
-            Mockito.anyString(),
-            Mockito.anyString(),
-            Mockito.anyList(),
-            Mockito.anyList(),
-            Mockito.any()))
-        .thenReturn(cassandraGetEmptyRecordById());
+    PowerMockito.mockStatic(BaseMWService.class);
+    BaseMWService.getRemoteRouter(Mockito.anyString());
     TestKit probe = new TestKit(system);
     ActorRef subject = system.actorOf(props);
     Request reqObj = new Request();
     reqObj.setOperation(ActorOperations.V2_NOTIFICATION.getValue());
-
     HashMap<String, Object> innerMap = new HashMap<>();
-    Map<String, Object> pageMap = new HashMap<String, Object>();
-    List<String> emailIdList = new ArrayList<>();
-    emailIdList.add("aaa@gmail.com");
+    Map<String, Object> reqMap = new HashMap<String, Object>();
     List<String> userIdList = new ArrayList<>();
     userIdList.add("001");
-    userIdList.add("002");
-    Map<String, Object> userIdMap = new HashMap<>();
-    userIdMap.put(JsonKey.RECIPIENT_USERIDS, userIdList);
-    innerMap.put(JsonKey.EMAIL_REQUEST, userIdMap);
-
-    reqObj.setRequest(innerMap);
+    reqMap.put(JsonKey.RECIPIENT_USERIDS, userIdList);
+    reqMap.put(JsonKey.MODE,JsonKey.SMS);
+    innerMap.put(JsonKey.EMAIL_REQUEST, reqMap);
+    reqMap.put(JsonKey.EMAIL_TEMPLATE_TYPE, "default");
+    reqObj.getRequest().put(JsonKey.EMAIL_REQUEST, reqMap);
     subject.tell(reqObj, probe.getRef());
-    ProjectCommonException exc =
-        probe.expectMsgClass(duration("10 second"), ProjectCommonException.class);
-    assertTrue(exc.getCode().equals(ResponseCode.notificationNotSent.getErrorCode()));
+    Response response = probe.expectMsgClass(duration("1000 second"), Response.class);
+    assertNotNull(response);
+  }
+
+  @Test
+  public void testWithInvalidRequest() {
+    Request request = new Request();
+    TestKit probe = new TestKit(system);
+    ActorRef subject = system.actorOf(props);
+    request.setOperation("invalidOperation");
+    subject.tell(request, probe.getRef());
+    ProjectCommonException exception = probe.expectMsgClass(duration("10 second"), ProjectCommonException.class);
+    Assert.assertNotNull(exception);
   }
 }
diff --git a/service/src/test/java/org/sunbird/actor/otp/OTPActorTest.java b/service/src/test/java/org/sunbird/actor/otp/OTPActorTest.java
index d413ad64e..d40eb29f4 100644
--- a/service/src/test/java/org/sunbird/actor/otp/OTPActorTest.java
+++ b/service/src/test/java/org/sunbird/actor/otp/OTPActorTest.java
@@ -32,28 +32,17 @@ import org.sunbird.helper.ServiceFactory;
 import org.sunbird.keys.JsonKey;
 import org.sunbird.operations.ActorOperations;
 import org.sunbird.request.Request;
-import org.sunbird.request.RequestContext;
 import org.sunbird.response.ClientErrorResponse;
 import org.sunbird.response.Response;
-import org.sunbird.service.otp.OTPService;
-import org.sunbird.service.ratelimit.RateLimitService;
-import org.sunbird.service.ratelimit.RateLimitServiceImpl;
-import org.sunbird.service.user.UserService;
-import org.sunbird.service.user.impl.UserServiceImpl;
 import org.sunbird.util.ratelimit.OtpRateLimiter;
 
 @RunWith(PowerMockRunner.class)
 @PrepareForTest({
   ServiceFactory.class,
-  OTPService.class,
   CassandraOperationImpl.class,
-  RateLimitService.class,
   RateLimitDaoImpl.class,
   RateLimitDao.class,
-  RateLimitServiceImpl.class,
-  SunbirdMWService.class,
-  UserService.class,
-  UserServiceImpl.class
+  SunbirdMWService.class
 })
 @PowerMockIgnore({
   "javax.management.*",
@@ -130,7 +119,7 @@ public class OTPActorTest {
   }
 
   @Test
-  public void testVerifyOtpSuccessWithEmailOtp2() throws Exception {
+  public void testVerifyOtpSuccessWithEmailOtp2() {
     Response mockedCassandraResponse =
       getMockCassandraRecordByIdSuccessResponse(EMAIL_KEY, EMAIL_TYPE, REQUEST_OTP);
     List<Map<String, Object>> responseList =
@@ -144,9 +133,6 @@ public class OTPActorTest {
       Mockito.anyString(),
       Mockito.any()))
       .thenReturn(mockedCassandraResponse);
-    OTPService otpService = PowerMockito.mock(OTPService.class);
-    PowerMockito.whenNew(OTPService.class).withNoArguments().thenReturn(otpService);
-    PowerMockito.when(otpService.getEmailPhoneByUserId(Mockito.anyString(),Mockito.anyString(),Mockito.any(RequestContext.class))).thenReturn("xyz@xyz.com");
     when(mockCassandraOperation.getRecordWithTTLById(
       Mockito.anyString(),
               Mockito.anyString(),
@@ -161,7 +147,7 @@ public class OTPActorTest {
   }
 
   @Test
-  public void testVerifyOtpFailureWithEmailOtp3() throws Exception {
+  public void testVerifyOtpFailureWithEmailOtp3() {
     Response mockedCassandraResponse =
       getMockCassandraRecordByIdSuccessResponse(EMAIL_KEY, EMAIL_TYPE, REQUEST_OTP);
     List<Map<String, Object>> responseList =
@@ -176,10 +162,7 @@ public class OTPActorTest {
       Mockito.anyString(),
       Mockito.any()))
       .thenReturn(mockedCassandraResponse);
-    OTPService otpService = PowerMockito.mock(OTPService.class);
-    PowerMockito.whenNew(OTPService.class).withNoArguments().thenReturn(otpService);
-    PowerMockito.when(otpService.getEmailPhoneByUserId(Mockito.anyString(),Mockito.anyString(),Mockito.any(RequestContext.class))).thenReturn("xyz@xyz.com");
-    when(mockCassandraOperation.getRecordWithTTLById(
+   when(mockCassandraOperation.getRecordWithTTLById(
       Mockito.anyString(),
       Mockito.anyString(),
       Mockito.anyMap(),
diff --git a/service/src/test/java/org/sunbird/service/notification/NotificationServiceTest.java b/service/src/test/java/org/sunbird/service/notification/NotificationServiceTest.java
new file mode 100644
index 000000000..683ca7bc5
--- /dev/null
+++ b/service/src/test/java/org/sunbird/service/notification/NotificationServiceTest.java
@@ -0,0 +1,332 @@
+package org.sunbird.service.notification;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.sunbird.cassandraimpl.CassandraOperationImpl;
+import org.sunbird.dao.notification.EmailTemplateDao;
+import org.sunbird.dao.notification.impl.EmailTemplateDaoImpl;
+import org.sunbird.dao.user.UserDao;
+import org.sunbird.dao.user.impl.UserDaoImpl;
+import org.sunbird.exception.ProjectCommonException;
+import org.sunbird.helper.ServiceFactory;
+import org.sunbird.keys.JsonKey;
+import org.sunbird.model.user.User;
+import org.sunbird.notification.sms.provider.ISmsProvider;
+import org.sunbird.notification.utils.SMSFactory;
+import org.sunbird.request.RequestContext;
+import org.sunbird.service.organisation.OrgService;
+import org.sunbird.service.organisation.impl.OrgServiceImpl;
+import org.sunbird.service.user.UserService;
+import org.sunbird.service.user.impl.UserServiceImpl;
+import org.sunbird.util.ProjectUtil;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({
+  UserService.class,
+  UserServiceImpl.class,
+  EmailTemplateDao.class,
+  EmailTemplateDaoImpl.class,
+  OrgService.class,
+  OrgServiceImpl.class,
+  EmailTemplateDao.class,
+  EmailTemplateDaoImpl.class,
+  ISmsProvider.class,
+  SMSFactory.class,
+  ProjectUtil.class
+})
+@PowerMockIgnore({
+  "javax.management.*",
+  "javax.net.ssl.*",
+  "javax.security.*",
+  "jdk.internal.reflect.*",
+  "javax.crypto.*"
+})
+public class NotificationServiceTest {
+
+  @Test(expected = ProjectCommonException.class)
+  public void processSMSWithInvalidPhoneNumber() {
+    UserService userService = PowerMockito.mock(UserService.class);
+    PowerMockito.mockStatic(UserServiceImpl.class);
+    PowerMockito.when(UserServiceImpl.getInstance()).thenReturn(userService);
+    List<Map<String, Object>> users = new ArrayList<>();
+    Map<String, Object> user = new HashMap<>();
+    user.put(JsonKey.PHONE,"9999999999");
+    user.put(JsonKey.FIRST_NAME,"FirstName");
+    user.put(JsonKey.ID,"21315-456-7894");
+    users.add(user);
+    PowerMockito.when(userService.getDecryptedEmailPhoneByUserIds(Mockito.anyList(), Mockito.anyString(), Mockito.any(RequestContext.class))).thenReturn(users);
+
+    List<String> userIds = new ArrayList<>();
+    userIds.add("21315-456-7894");
+    List<String> phones = new ArrayList<>();
+    phones.add("1111111111");
+    String smsText = "SMS Text";
+
+    NotificationService service = new NotificationService();
+    service.processSMS(userIds, phones, smsText, new RequestContext());
+  }
+
+  @Test(expected = ProjectCommonException.class)
+  public void processSMSWithInvalidUserId() {
+    UserService userService = PowerMockito.mock(UserService.class);
+    PowerMockito.mockStatic(UserServiceImpl.class);
+    PowerMockito.when(UserServiceImpl.getInstance()).thenReturn(userService);
+    List<Map<String, Object>> users = new ArrayList<>();
+    Map<String, Object> user = new HashMap<>();
+    user.put(JsonKey.PHONE,"9999999999");
+    user.put(JsonKey.FIRST_NAME,"FirstName");
+    user.put(JsonKey.ID,"21315-456-7894");
+    users.add(user);
+    PowerMockito.when(userService.getDecryptedEmailPhoneByUserIds(Mockito.anyList(), Mockito.anyString(), Mockito.any(RequestContext.class))).thenReturn(users);
+
+    List<String> userIds = new ArrayList<>();
+    userIds.add("21315-456-7894");
+    userIds.add("invalidUserIds");
+    List<String> phones = new ArrayList<>();
+    phones.add("9999999999");
+    String smsText = "SMS Text";
+
+    NotificationService service = new NotificationService();
+    service.processSMS(userIds, phones, smsText, new RequestContext());
+  }
+
+  @Test
+  public void processSMS() {
+    UserService userService = PowerMockito.mock(UserService.class);
+    PowerMockito.mockStatic(UserServiceImpl.class);
+    PowerMockito.when(UserServiceImpl.getInstance()).thenReturn(userService);
+    List<Map<String, Object>> users = new ArrayList<>();
+    Map<String, Object> user = new HashMap<>();
+    user.put(JsonKey.PHONE,"9999999999");
+    user.put(JsonKey.FIRST_NAME,"FirstName");
+    user.put(JsonKey.ID,"21315-456-7894");
+    users.add(user);
+    PowerMockito.when(userService.getDecryptedEmailPhoneByUserIds(Mockito.anyList(), Mockito.anyString(), Mockito.any(RequestContext.class))).thenReturn(users);
+
+    List<String> userIds = new ArrayList<>();
+    userIds.add("21315-456-7894");
+    List<String> phones = new ArrayList<>();
+    phones.add("9999999999");
+    String smsText = "SMS Text";
+
+    NotificationService service = new NotificationService();
+    boolean bool = service.processSMS(userIds, phones, smsText, new RequestContext());
+    Assert.assertFalse(bool);
+  }
+
+  @Test(expected = ProjectCommonException.class)
+  public void validateAndGetEmailListWithInvalidEmailFormat() {
+    List<String> userIds = new ArrayList<>();
+    userIds.add("21315-456-7894");
+    List<String> emails = new ArrayList<>();
+    emails.add("xyzxyz@com");
+    Map<String,Object> recipientSearchQuery = new HashMap<>();
+    Map<String,Object> filters =  new HashMap<>();
+    filters.put(JsonKey.FIRST_NAME,"FirstName");
+    recipientSearchQuery.put(JsonKey.FILTERS,filters);
+
+
+    NotificationService service = new NotificationService();
+    service.validateAndGetEmailList(userIds, emails, recipientSearchQuery, new RequestContext());
+  }
+
+  @Test(expected = ProjectCommonException.class)
+  public void validateAndGetEmailListWithEmptyFilters() {
+    List<String> userIds = new ArrayList<>();
+    userIds.add("21315-456-7894");
+    List<String> emails = new ArrayList<>();
+    emails.add("xyz@xyz.com");
+    Map<String,Object> recipientSearchQuery = new HashMap<>();
+    Map<String,Object> filters =  new HashMap<>();
+    recipientSearchQuery.put(JsonKey.FILTERS,filters);
+
+    NotificationService service = new NotificationService();
+    service.validateAndGetEmailList(userIds, emails, recipientSearchQuery, new RequestContext());
+  }
+
+  @Test(expected = ProjectCommonException.class)
+  public void validateAndGetEmailListWithInvalidUserIds() {
+    UserService userService = PowerMockito.mock(UserService.class);
+    PowerMockito.mockStatic(UserServiceImpl.class);
+    PowerMockito.when(UserServiceImpl.getInstance()).thenReturn(userService);
+    List<Map<String, Object>> users = new ArrayList<>();
+    PowerMockito.when(userService.getDecryptedEmailPhoneByUserIds(Mockito.anyList(), Mockito.anyString(), Mockito.any(RequestContext.class))).thenReturn(users);
+    PowerMockito.when(userService.getUserEmailsBySearchQuery(Mockito.anyMap(), Mockito.any(RequestContext.class))).thenReturn(users);
+    List<String> userIds = new ArrayList<>();
+    userIds.add("21315-456-7894");
+    List<String> emails = new ArrayList<>();
+    emails.add("xyz@xyz.com");
+    Map<String,Object> recipientSearchQuery = new HashMap<>();
+    Map<String,Object> filters =  new HashMap<>();
+    filters.put(JsonKey.FIRST_NAME,"FirstName");
+    recipientSearchQuery.put(JsonKey.FILTERS,filters);
+
+
+    NotificationService service = new NotificationService();
+    service.validateAndGetEmailList(userIds, emails, recipientSearchQuery, new RequestContext());
+  }
+
+  @Test
+  public void validateAndGetEmailList() {
+    UserService userService = PowerMockito.mock(UserService.class);
+    PowerMockito.mockStatic(UserServiceImpl.class);
+    PowerMockito.when(UserServiceImpl.getInstance()).thenReturn(userService);
+    List<Map<String, Object>> users = new ArrayList<>();
+    Map<String, Object> user = new HashMap<>();
+    user.put(JsonKey.EMAIL,"xyz@xyz.com");
+    user.put(JsonKey.FIRST_NAME,"FirstName");
+    user.put(JsonKey.ID,"21315-456-7894");
+    users.add(user);
+    PowerMockito.when(userService.getDecryptedEmailPhoneByUserIds(Mockito.anyList(), Mockito.anyString(), Mockito.any(RequestContext.class))).thenReturn(users);
+    PowerMockito.when(userService.getUserEmailsBySearchQuery(Mockito.anyMap(), Mockito.any(RequestContext.class))).thenReturn(users);
+    List<String> userIds = new ArrayList<>();
+    userIds.add("21315-456-7894");
+    List<String> emails = new ArrayList<>();
+    emails.add("xyz@xyz.com");
+    String smsText = "SMS Text";
+    Map<String,Object> recipientSearchQuery = new HashMap<>();
+    Map<String,Object> filters =  new HashMap<>();
+    filters.put(JsonKey.FIRST_NAME,"FirstName");
+    recipientSearchQuery.put(JsonKey.FILTERS,filters);
+
+
+    NotificationService service = new NotificationService();
+    List<String> emailList = service.validateAndGetEmailList(userIds, emails, recipientSearchQuery, new RequestContext());
+    Assert.assertEquals(1,emailList.size());
+  }
+
+  @Test
+  public void updateFirstNameAndOrgNameInEmailContext() {
+    UserService userService = PowerMockito.mock(UserService.class);
+    PowerMockito.mockStatic(UserServiceImpl.class);
+    PowerMockito.when(UserServiceImpl.getInstance()).thenReturn(userService);
+    OrgService orgService = PowerMockito.mock(OrgService.class);
+    PowerMockito.mockStatic(OrgServiceImpl.class);
+    PowerMockito.when(OrgServiceImpl.getInstance()).thenReturn(orgService);
+    Map<String, Object> org = new HashMap<>();
+    org.put(JsonKey.ID,"45642118798");
+    org.put(JsonKey.ORG_NAME,"orgName");
+    PowerMockito.when(orgService.getOrgById(Mockito.anyString(), Mockito.any(RequestContext.class))).thenReturn(org);
+    User user = new User();
+    user.setId("1315-45-4546");
+    user.setRootOrgId("45642118798");
+    PowerMockito.when(userService.getUserById(Mockito.anyString(), Mockito.any(RequestContext.class))).thenReturn(user);
+    List<String> userIds = new ArrayList<>();
+    userIds.add("21315-456-7894");
+    List<String> emails = new ArrayList<>();
+    emails.add("xyz@xyz.com");
+    String smsText = "SMS Text";
+    Map<String,Object> recipientSearchQuery = new HashMap<>();
+    Map<String,Object> filters =  new HashMap<>();
+    filters.put(JsonKey.FIRST_NAME,"FirstName");
+    recipientSearchQuery.put(JsonKey.FILTERS,filters);
+    Map<String, Object> request = new HashMap<>();
+    request.put(JsonKey.FIRST_NAME,"firstName");
+    request.put(JsonKey.ORG_NAME,"orgName");
+
+    NotificationService service = new NotificationService();
+    service.updateFirstNameAndOrgNameInEmailContext(userIds, emails, request, new RequestContext());
+    Assert.assertNotNull(request);
+  }
+
+  @Test
+  public void updateFirstNameAndOrgNameInEmailContext2() {
+    UserService userService = PowerMockito.mock(UserService.class);
+    PowerMockito.mockStatic(UserServiceImpl.class);
+    PowerMockito.when(UserServiceImpl.getInstance()).thenReturn(userService);
+    OrgService orgService = PowerMockito.mock(OrgService.class);
+    PowerMockito.mockStatic(OrgServiceImpl.class);
+    PowerMockito.when(OrgServiceImpl.getInstance()).thenReturn(orgService);
+    Map<String, Object> org = new HashMap<>();
+    org.put(JsonKey.ID,"45642118798");
+    org.put(JsonKey.ORG_NAME,"orgName");
+    PowerMockito.when(orgService.getOrgById(Mockito.anyString(), Mockito.any(RequestContext.class))).thenReturn(org);
+    User user = new User();
+    user.setId("1315-45-4546");
+    user.setRootOrgId("45642118798");
+    PowerMockito.when(userService.getUserById(Mockito.anyString(), Mockito.any(RequestContext.class))).thenReturn(user);
+    List<String> userIds = new ArrayList<>();
+    userIds.add("21315-456-7894");
+    List<String> emails = new ArrayList<>();
+    emails.add("xyz@xyz.com");
+    Map<String, Object> request = new HashMap<>();
+    request.put(JsonKey.FIRST_NAME,"firstName");
+
+    NotificationService service = new NotificationService();
+    service.updateFirstNameAndOrgNameInEmailContext(userIds, emails, request, new RequestContext());
+    Assert.assertNotNull(request);
+  }
+
+  @Test
+  public void updateFirstNameAndOrgNameInEmailContext3() {
+    List<String> userIds = new ArrayList<>();
+    List<String> emails = new ArrayList<>();
+    emails.add("xyz@xyz.com");
+    Map<String, Object> request = new HashMap<>();
+    request.put(JsonKey.FIRST_NAME,"firstName");
+
+    NotificationService service = new NotificationService();
+    service.updateFirstNameAndOrgNameInEmailContext(userIds, emails, request, new RequestContext());
+    Assert.assertNotNull(request);
+  }
+
+  @Test
+  public void getEmailTemplateFile() {
+    EmailTemplateDao templateDao = PowerMockito.mock(EmailTemplateDaoImpl.class);
+    PowerMockito.mockStatic(EmailTemplateDaoImpl.class);
+    PowerMockito.when(EmailTemplateDaoImpl.getInstance()).thenReturn(templateDao);
+    PowerMockito.when(templateDao.getTemplate(Mockito.anyString(),Mockito.any(RequestContext.class))).thenReturn("template");
+    NotificationService service = new NotificationService();
+    String template = service.getEmailTemplateFile("templateName", new RequestContext());
+    Assert.assertNotNull(template);
+  }
+
+  @Test(expected = ProjectCommonException.class)
+  public void getEmailTemplateFileWithInvalidTemplateId() {
+    EmailTemplateDao templateDao = PowerMockito.mock(EmailTemplateDaoImpl.class);
+    PowerMockito.mockStatic(EmailTemplateDaoImpl.class);
+    PowerMockito.when(EmailTemplateDaoImpl.getInstance()).thenReturn(templateDao);
+    PowerMockito.when(templateDao.getTemplate(Mockito.anyString(),Mockito.any(RequestContext.class))).thenReturn("");
+    NotificationService service = new NotificationService();
+    service.getEmailTemplateFile("templateName", new RequestContext());
+  }
+
+  @Test
+  public void getV2NotificationRequest() {
+    Set<String> phoneList = new HashSet<>();
+    phoneList.add("9999999999");
+    Map<String,Object> reqMap = new HashMap<>();
+    reqMap.put(JsonKey.SUBJECT,"subject");
+    reqMap.put(JsonKey.BODY,"body");
+    NotificationService service = new NotificationService();
+    Map<String, Object> notiReq = service.getV2NotificationRequest(phoneList,reqMap,JsonKey.SMS,"");
+    Assert.assertNotNull(notiReq);
+  }
+
+  @Test
+  public void getV2NotificationRequest2() {
+    Set<String> emailList = new HashSet<>();
+    emailList.add("xyz@xyz.com");
+    Map<String,Object> reqMap = new HashMap<>();
+    reqMap.put(JsonKey.SUBJECT,"subject");
+    reqMap.put(JsonKey.BODY,"body");
+    String template = "Welcome to $instanceName. Your user account has now been created. Click on the link below to #if ($setPasswordLink) set a password #else verify your email ID #end and start using your account:$newline$link";
+    NotificationService service = new NotificationService();
+    Map<String, Object> notiReq = service.getV2NotificationRequest(emailList,reqMap,JsonKey.EMAIL,template);
+    Assert.assertNotNull(notiReq);
+  }
+
+}
diff --git a/service/src/test/java/org/sunbird/service/user/UserEmailsBySearchQueryTest.java b/service/src/test/java/org/sunbird/service/user/UserEmailsBySearchQueryTest.java
new file mode 100644
index 000000000..d277a2b91
--- /dev/null
+++ b/service/src/test/java/org/sunbird/service/user/UserEmailsBySearchQueryTest.java
@@ -0,0 +1,84 @@
+package org.sunbird.service.user;
+
+import akka.dispatch.Futures;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.sunbird.common.ElasticSearchHelper;
+import org.sunbird.common.ElasticSearchRestHighImpl;
+import org.sunbird.common.factory.EsClientFactory;
+import org.sunbird.dao.user.UserDao;
+import org.sunbird.dao.user.impl.UserDaoImpl;
+import org.sunbird.dto.SearchDTO;
+import org.sunbird.keys.JsonKey;
+import org.sunbird.request.RequestContext;
+import org.sunbird.service.user.impl.UserServiceImpl;
+import scala.concurrent.Promise;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({
+  UserDao.class,
+  UserDaoImpl.class,
+  ElasticSearchRestHighImpl.class,
+  EsClientFactory.class,
+  ElasticSearchHelper.class
+})
+@PowerMockIgnore({
+  "javax.management.*",
+  "javax.net.ssl.*",
+  "javax.security.*",
+  "jdk.internal.reflect.*",
+  "javax.crypto.*"
+})
+public class UserEmailsBySearchQueryTest {
+
+  private ElasticSearchRestHighImpl esSearch;
+
+  @Before
+  public void beforeTest(){
+    PowerMockito.mockStatic(EsClientFactory.class);
+    esSearch = mock(ElasticSearchRestHighImpl.class);
+    when(EsClientFactory.getInstance(Mockito.anyString())).thenReturn(esSearch);
+  }
+
+  @Test
+  public void getUserEmailsBySearchQuery() {
+    Map<String, Object> esResponse = new HashMap<>();
+    List<Map<String,Object>> contents = new ArrayList<>();
+    Map<String , Object> content1 = new HashMap<>();
+    content1.put(JsonKey.USER_ID, "1231-45654-5135");
+    content1.put(JsonKey.EMAIL, "xyz@xyz.com");
+    contents.add(content1);
+    Map<String , Object> content2 = new HashMap<>();
+    content2.put(JsonKey.USER_ID, "1232-45654-5135");
+    content2.put(JsonKey.EMAIL, "xyz.com");
+    contents.add(content2);
+    esResponse.put(JsonKey.CONTENT, contents);
+    Promise<Map<String, Object>> promise = Futures.promise();
+    promise.success(esResponse);
+
+    when(esSearch.search(Mockito.any(SearchDTO.class), Mockito.anyString(), Mockito.any()))
+      .thenReturn(promise.future());
+    UserService userService = UserServiceImpl.getInstance();
+    Map<String, Object> searchQuery = new HashMap<>();
+    Map<String, Object> filters = new HashMap<>();
+    filters.put(JsonKey.FIRST_NAME, "firstName");
+    searchQuery.put(JsonKey.FILTERS, filters);
+    List<Map<String, Object>> res = userService.getUserEmailsBySearchQuery(searchQuery, new RequestContext());
+    Assert.assertNotNull(res);
+  }
+}
-- 
GitLab