mirror of
https://repository.entgra.net/community/device-mgt-core.git
synced 2025-10-06 02:01:45 +00:00
Merge branch 'corrective-policy' into 'corrective-policy'
Add mail sending feature as corrective action See merge request entgra/carbon-device-mgt!652
This commit is contained in:
commit
f41bf699ec
@ -57,8 +57,10 @@ import javax.validation.constraints.Size;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.HeaderParam;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
@ -359,4 +361,63 @@ public interface DeviceManagementAdminService {
|
||||
required = true)
|
||||
List<String> deviceIdentifiers);
|
||||
|
||||
@POST
|
||||
@Path("/{deviceId}/{featureCode}/")
|
||||
@ApiOperation(
|
||||
consumes = MediaType.APPLICATION_JSON,
|
||||
produces = MediaType.APPLICATION_JSON,
|
||||
httpMethod = "POST",
|
||||
value = "Removing Multiple Policies",
|
||||
notes = "Delete one or more than one policy using this API.",
|
||||
tags = "Device Policy Management",
|
||||
extensions = {
|
||||
@Extension(properties = {
|
||||
@ExtensionProperty(name = Constants.SCOPE, value = "perm:android:enroll")
|
||||
})
|
||||
}
|
||||
)
|
||||
@ApiResponses(
|
||||
value = {
|
||||
@ApiResponse(
|
||||
code = 200,
|
||||
message = "OK. \n Successfully removed the policy."),
|
||||
@ApiResponse(
|
||||
code = 400,
|
||||
message = "Bad Request. \n Invalid request or validation error.",
|
||||
response = ErrorResponse.class),
|
||||
@ApiResponse(
|
||||
code = 404,
|
||||
message = "Not Found. \n The specified resource does not exist.",
|
||||
response = ErrorResponse.class),
|
||||
@ApiResponse(
|
||||
code = 415,
|
||||
message = "Unsupported media type. \n The format of the requested entity was not " +
|
||||
"supported.\n "
|
||||
+ "supported format."),
|
||||
@ApiResponse(
|
||||
code = 500,
|
||||
message = "Internal Server Error. \n " +
|
||||
"Server error occurred whilst bulk removing policies.",
|
||||
response = ErrorResponse.class)
|
||||
})
|
||||
Response triggerCorrectiveActions(
|
||||
@ApiParam(
|
||||
name = "deviceId",
|
||||
value = "Device Identifier.",
|
||||
required = true)
|
||||
@PathParam("deviceId")
|
||||
String deviceId,
|
||||
@ApiParam(
|
||||
name = "featureCode",
|
||||
value = "Policy Feature Code.",
|
||||
required = true)
|
||||
@PathParam("featureCode")
|
||||
String featureCode,
|
||||
@ApiParam(
|
||||
name = "actions",
|
||||
value = "The list of actions to trigger when policy violated.",
|
||||
required = true)
|
||||
List<String> actions
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@ -41,8 +41,15 @@ import org.wso2.carbon.context.CarbonContext;
|
||||
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||
import org.wso2.carbon.device.mgt.common.Device;
|
||||
import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
|
||||
import org.wso2.carbon.device.mgt.common.MDMAppConstants;
|
||||
import org.wso2.carbon.device.mgt.common.PaginationRequest;
|
||||
import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry;
|
||||
import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManagementException;
|
||||
import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration;
|
||||
import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfigurationManagementService;
|
||||
import org.wso2.carbon.device.mgt.common.exceptions.BadRequestException;
|
||||
import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException;
|
||||
import org.wso2.carbon.device.mgt.common.exceptions.DeviceNotFoundException;
|
||||
import org.wso2.carbon.device.mgt.common.exceptions.InvalidDeviceException;
|
||||
import org.wso2.carbon.device.mgt.common.exceptions.UserNotFoundException;
|
||||
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
|
||||
@ -56,8 +63,10 @@ import javax.validation.constraints.Size;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.HeaderParam;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
@ -190,4 +199,38 @@ public class DeviceManagementAdminServiceImpl implements DeviceManagementAdminSe
|
||||
}
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/{deviceId}/{featureCode}")
|
||||
@Override
|
||||
public Response triggerCorrectiveActions(
|
||||
@PathParam("deviceId") String deviceIdentifier,
|
||||
@PathParam("featureCode") String featureCode,
|
||||
List<String> actions){
|
||||
DeviceManagementProviderService deviceManagementService = DeviceMgtAPIUtils.getDeviceManagementService();
|
||||
PlatformConfigurationManagementService platformConfigurationManagementService = DeviceMgtAPIUtils
|
||||
.getPlatformConfigurationManagementService();
|
||||
try {
|
||||
PlatformConfiguration config = platformConfigurationManagementService
|
||||
.getConfiguration(MDMAppConstants.RegistryConstants.GENERAL_CONFIG_RESOURCE_PATH);
|
||||
List<ConfigurationEntry> configList = config.getConfiguration();
|
||||
deviceManagementService.triggerCorrectiveActions(deviceIdentifier, featureCode, actions, configList);
|
||||
} catch (ConfigurationManagementException e) {
|
||||
String msg = "Error occurred while processing platform configuration.";
|
||||
log.error(msg);
|
||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
|
||||
} catch (BadRequestException e) {
|
||||
String msg = "Bad request, can't proceed. Hence verify the request and re-try";
|
||||
log.error(msg);
|
||||
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
|
||||
} catch (DeviceManagementException e) {
|
||||
String msg = "Error occurred while getting device data which has ID: " + deviceIdentifier;
|
||||
log.error(msg);
|
||||
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
|
||||
} catch (DeviceNotFoundException e) {
|
||||
String msg = "Couldn't find an device for device identifier: " + deviceIdentifier;
|
||||
log.error(msg);
|
||||
return Response.status(Response.Status.NOT_FOUND).entity(msg).build();
|
||||
}
|
||||
return Response.status(Response.Status.OK).entity("Triggered action successfully").build();
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
/* Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
|
||||
*
|
||||
* Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.wso2.carbon.device.mgt.common.configuration.mgt;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class CorrectiveActionConfig {
|
||||
|
||||
private List<String> mailReceivers;
|
||||
private String mailSubject;
|
||||
private String mailBody;
|
||||
private List<String> actionTypes;
|
||||
|
||||
public List<String> getMailReceivers() {
|
||||
return mailReceivers;
|
||||
}
|
||||
|
||||
public void setMailReceivers(List<String> mailReceivers) {
|
||||
this.mailReceivers = mailReceivers;
|
||||
}
|
||||
|
||||
public String getMailSubject() {
|
||||
return mailSubject;
|
||||
}
|
||||
|
||||
public void setMailSubject(String mailSubject) {
|
||||
this.mailSubject = mailSubject;
|
||||
}
|
||||
|
||||
public String getMailBody() {
|
||||
return mailBody;
|
||||
}
|
||||
|
||||
public void setMailBody(String mailBody) {
|
||||
this.mailBody = mailBody;
|
||||
}
|
||||
|
||||
public List<String> getActionTypes() {
|
||||
return actionTypes;
|
||||
}
|
||||
|
||||
public void setActionTypes(List<String> actionTypes) {
|
||||
this.actionTypes = actionTypes;
|
||||
}
|
||||
}
|
||||
@ -99,6 +99,12 @@ public final class DeviceManagementConstants {
|
||||
public static final String POLICY_REVOKE_OPERATION_CODE = OperationMgtConstants.OperationCodes.POLICY_REVOKE;
|
||||
}
|
||||
|
||||
public static final class CorrectiveActions {
|
||||
private CorrectiveActions() {throw new AssertionError();}
|
||||
|
||||
public static final String E_MAIL = "MAIL";
|
||||
}
|
||||
|
||||
public static final class EmailAttributes {
|
||||
private EmailAttributes() {
|
||||
throw new AssertionError();
|
||||
@ -117,6 +123,7 @@ public final class DeviceManagementConstants {
|
||||
public static final String USER_REGISTRATION_TEMPLATE = "user-registration";
|
||||
public static final String USER_ENROLLMENT_TEMPLATE = "user-enrollment";
|
||||
public static final String USER_VERIFY_TEMPLATE = "user-verify";
|
||||
public static final String POLICY_VIOLATE_TEMPLATE = "policy-violating-notifier";
|
||||
public static final String USER_WELCOME_TEMPLATE = "user-welcome";
|
||||
public static final String DEFAULT_ENROLLMENT_TEMPLATE = "default-enrollment-invitation";
|
||||
}
|
||||
|
||||
@ -1851,7 +1851,8 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO {
|
||||
+ "WHERE "
|
||||
+ "DEVICE_ID_NAME = ? AND "
|
||||
+ "DEVICE_TYPE_NAME = ? AND "
|
||||
+ "TIMESTAMP BETWEEN ? AND ?";
|
||||
+ "TIMESTAMP BETWEEN ? AND ? "
|
||||
+ "ORDER BY timestamp";
|
||||
try {
|
||||
Connection conn = this.getConnection();
|
||||
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||
|
||||
@ -30,8 +30,6 @@ import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException;
|
||||
import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory;
|
||||
import org.wso2.carbon.device.mgt.core.dao.impl.AbstractDeviceDAOImpl;
|
||||
import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil;
|
||||
import org.wso2.carbon.device.mgt.core.geo.GeoCluster;
|
||||
import org.wso2.carbon.device.mgt.core.geo.geoHash.GeoCoordinate;
|
||||
import org.wso2.carbon.device.mgt.core.report.mgt.Constants;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
@ -447,7 +447,7 @@ public class DeviceDetailsDAOImpl implements DeviceDetailsDAO {
|
||||
stmt.setDouble(6, location.getLongitude());
|
||||
stmt.setFloat(7, location.getSpeed());
|
||||
stmt.setFloat(8, location.getBearing());
|
||||
stmt.setLong(9, System.currentTimeMillis());
|
||||
stmt.setLong(9, location.getUpdatedTime().getTime());
|
||||
stmt.setString(10, GeoHashGenerator.encodeGeohash(location));
|
||||
stmt.setString(11, device.getEnrolmentInfo().getOwner());
|
||||
stmt.setDouble(12, location.getAltitude());
|
||||
|
||||
@ -47,6 +47,7 @@ import org.wso2.carbon.device.mgt.common.MonitoringOperation;
|
||||
import org.wso2.carbon.device.mgt.common.StartupOperationConfig;
|
||||
import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig;
|
||||
import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManagementException;
|
||||
import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry;
|
||||
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistorySnapshot;
|
||||
import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException;
|
||||
import org.wso2.carbon.device.mgt.common.exceptions.DeviceNotFoundException;
|
||||
@ -918,4 +919,17 @@ public interface DeviceManagementProviderService {
|
||||
* @return enrollment steps of each enrollment types which are provided in the device type xml file
|
||||
*/
|
||||
DeviceEnrollmentInvitationDetails getDeviceEnrollmentInvitationDetails(String deviceType);
|
||||
|
||||
/**
|
||||
* This method is called by device when triggered a corrective action
|
||||
*
|
||||
* @param deviceIdentifier Device Identifier
|
||||
* @param featureCode Feature Code
|
||||
* @param actions Actions
|
||||
* @param configList Configuration List
|
||||
* @throws DeviceManagementException if error occurred while triggering corrective action
|
||||
* @throws DeviceNotFoundException if server doesn't have a device for given device identifier
|
||||
*/
|
||||
void triggerCorrectiveActions(String deviceIdentifier, String featureCode, List<String> actions,
|
||||
List<ConfigurationEntry> configList) throws DeviceManagementException, DeviceNotFoundException;
|
||||
}
|
||||
|
||||
@ -59,6 +59,7 @@ import org.wso2.carbon.device.mgt.common.DeviceTransferRequest;
|
||||
import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
|
||||
import org.wso2.carbon.device.mgt.common.FeatureManager;
|
||||
import org.wso2.carbon.device.mgt.common.InitialOperationConfig;
|
||||
import org.wso2.carbon.device.mgt.common.MDMAppConstants;
|
||||
import org.wso2.carbon.device.mgt.common.MonitoringOperation;
|
||||
import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig;
|
||||
import org.wso2.carbon.device.mgt.common.PaginationRequest;
|
||||
@ -69,6 +70,7 @@ import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManagementException;
|
||||
import org.wso2.carbon.device.mgt.common.configuration.mgt.AmbiguousConfigurationException;
|
||||
import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry;
|
||||
import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManagementException;
|
||||
import org.wso2.carbon.device.mgt.common.configuration.mgt.CorrectiveActionConfig;
|
||||
import org.wso2.carbon.device.mgt.common.configuration.mgt.DeviceConfiguration;
|
||||
import org.wso2.carbon.device.mgt.common.configuration.mgt.DevicePropertyInfo;
|
||||
import org.wso2.carbon.device.mgt.common.configuration.mgt.EnrollmentConfiguration;
|
||||
@ -80,6 +82,7 @@ import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistorySna
|
||||
import org.wso2.carbon.device.mgt.common.enrollment.notification.EnrollmentNotificationConfiguration;
|
||||
import org.wso2.carbon.device.mgt.common.enrollment.notification.EnrollmentNotifier;
|
||||
import org.wso2.carbon.device.mgt.common.enrollment.notification.EnrollmentNotifierException;
|
||||
import org.wso2.carbon.device.mgt.common.exceptions.BadRequestException;
|
||||
import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException;
|
||||
import org.wso2.carbon.device.mgt.common.exceptions.DeviceNotFoundException;
|
||||
import org.wso2.carbon.device.mgt.common.exceptions.DeviceTypeNotFoundException;
|
||||
@ -129,6 +132,7 @@ import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder;
|
||||
import org.wso2.carbon.device.mgt.core.internal.DeviceManagementServiceComponent;
|
||||
import org.wso2.carbon.device.mgt.core.internal.PluginInitializationListener;
|
||||
import org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation;
|
||||
import org.wso2.carbon.device.mgt.core.report.mgt.Constants;
|
||||
import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil;
|
||||
import org.wso2.carbon.email.sender.core.ContentProviderInfo;
|
||||
import org.wso2.carbon.email.sender.core.EmailContext;
|
||||
@ -140,6 +144,7 @@ import org.wso2.carbon.stratos.common.beans.TenantInfoBean;
|
||||
import org.wso2.carbon.tenant.mgt.services.TenantMgtAdminService;
|
||||
import org.wso2.carbon.user.api.UserStoreException;
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Marshaller;
|
||||
@ -4207,4 +4212,60 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
|
||||
DeviceManagementService dms = pluginRepository.getDeviceManagementService(deviceType, tenantId);
|
||||
return dms.getDeviceEnrollmentInvitationDetails();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void triggerCorrectiveActions(String deviceIdentifier, String featureCode, List<String> actions,
|
||||
List<ConfigurationEntry> configList) throws DeviceManagementException, DeviceNotFoundException {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Triggering Corrective action. Device Identifier: " + deviceIdentifier);
|
||||
}
|
||||
|
||||
if (configList == null || configList.isEmpty()) {
|
||||
String msg = "Platform config is not configured";
|
||||
log.error(msg);
|
||||
throw new BadRequestException(msg);
|
||||
}
|
||||
|
||||
Device device = getDevice(deviceIdentifier, false);
|
||||
if (device == null) {
|
||||
String msg = "Couldn't find and device for device identifier " + deviceIdentifier;
|
||||
log.error(msg);
|
||||
throw new DeviceNotFoundException(msg);
|
||||
}
|
||||
EnrolmentInfo enrolmentInfo = device.getEnrolmentInfo();
|
||||
|
||||
for (String action : actions) {
|
||||
for (ConfigurationEntry config : configList) {
|
||||
if (config.getName().equals(featureCode)) {
|
||||
CorrectiveActionConfig correctiveActionConfig = (CorrectiveActionConfig) config.getValue();
|
||||
if (correctiveActionConfig.getActionTypes().contains(action)) {
|
||||
if (DeviceManagementConstants.CorrectiveActions.E_MAIL.equals(action)) {
|
||||
Properties props = new Properties();
|
||||
props.setProperty("mail-subject", correctiveActionConfig.getMailSubject());
|
||||
props.setProperty("feature-code", featureCode);
|
||||
props.setProperty("device-id", deviceIdentifier);
|
||||
props.setProperty("device-name", device.getName());
|
||||
props.setProperty("device-owner", enrolmentInfo.getOwner());
|
||||
props.setProperty("custom-mail-body", correctiveActionConfig.getMailBody());
|
||||
try {
|
||||
for (String mailAddress : correctiveActionConfig.getMailReceivers()) {
|
||||
EmailMetaInfo metaInfo = new EmailMetaInfo(mailAddress, props);
|
||||
sendEnrolmentInvitation(
|
||||
DeviceManagementConstants.EmailAttributes.POLICY_VIOLATE_TEMPLATE,
|
||||
metaInfo);
|
||||
}
|
||||
} catch (ConfigurationManagementException e) {
|
||||
String msg = "Error occurred while sending the mail.";
|
||||
log.error(msg);
|
||||
throw new DeviceManagementException(msg, e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.warn("Corrective action: " + action + " is not configured in the platform configuration "
|
||||
+ "for policy " + featureCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,12 +37,6 @@ import java.util.List;
|
||||
|
||||
public interface PolicyManagerService {
|
||||
|
||||
/*
|
||||
Feature addFeature(Feature feature) throws FeatureManagementException;
|
||||
|
||||
Feature updateFeature(Feature feature) throws FeatureManagementException;
|
||||
*/
|
||||
|
||||
Profile addProfile(Profile profile) throws PolicyManagementException;
|
||||
|
||||
Profile updateProfile(Profile profile) throws PolicyManagementException;
|
||||
@ -97,9 +91,8 @@ public interface PolicyManagerService {
|
||||
|
||||
boolean isCompliant(DeviceIdentifier deviceIdentifier) throws PolicyComplianceException;
|
||||
|
||||
PaginationResult getPolicyCompliance(
|
||||
PaginationRequest paginationRequest, String policyId, boolean complianceStatus, boolean isPending, String fromDate, String toDate)
|
||||
throws PolicyComplianceException;
|
||||
PaginationResult getPolicyCompliance(PaginationRequest paginationRequest, String policyId, boolean complianceStatus,
|
||||
boolean isPending, String fromDate, String toDate) throws PolicyComplianceException;
|
||||
|
||||
List<ComplianceFeature> getNoneComplianceFeatures(int complianceStatusId) throws PolicyComplianceException;
|
||||
}
|
||||
|
||||
@ -0,0 +1,69 @@
|
||||
#*
|
||||
Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
|
||||
|
||||
Entgra (Pvt) Ltd. licenses this file to you under the Apache License,
|
||||
Version 2.0 (the "License"); you may not use this file except
|
||||
in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
*#
|
||||
<EmailConfig>
|
||||
<Subject>$mail-subject</Subject>
|
||||
<Body>
|
||||
<![CDATA[
|
||||
<html>
|
||||
<head>
|
||||
<title>Entgra IoT Server</title>
|
||||
</head>
|
||||
<body style="color: #666666; background-color:#cdcdcd; padding: 0px; margin: 0px;">
|
||||
<div style="background-color:#cdcdcd; font-length: 1em; font-family: Arial, Helvetica; line-height: 170%; color: #666666; padding: 20px 0px; margin: 0px;">
|
||||
<div style="width: 86%; max-width: 650px; padding: 2%; background-color: #ffffff; margin: auto; border-radius: 14px;">
|
||||
<div style="background-color: #ffebcc; line-height: 0px; border-top-left-radius: 10px; border-top-right-radius: 10px; padding: 10px;">
|
||||
<div style="display: inline-block; line-height: 0px;">
|
||||
<img alt="entgra" src="https://storage.googleapis.com/cdn-entgra/logo.png" height="50px" width="143px" />
|
||||
</div>
|
||||
</div>
|
||||
<div style="background-color: #ffffff; line-height: 170%; color: #666666; padding: 20px 25px;">
|
||||
<p style="font-length: 1em; font-family: Arial, Helvetica; line-height: 170%; color: #666666; margin: 5px 0px 20px;">
|
||||
Hi,
|
||||
</p>
|
||||
<div>
|
||||
<p style="font-length: 1em; font-family: Arial, Helvetica; line-height: 170%; color: #666666; margin: 20px 0px 5px;">
|
||||
$feature-code policy is violated in the following device.
|
||||
</p>
|
||||
<p style="font-size: 1em; font-family: Arial, Helvetica; line-height: 170%; color: #666666; margin: 5px 0px;"><b>Device Id: </b> $device-id</p>
|
||||
<p style="font-size: 1em; font-family: Arial, Helvetica; line-height: 170%; color: #666666; margin: 5px 0px;"><b>Device Name: </b> $device-name</p>
|
||||
<p style="font-size: 1em; font-family: Arial, Helvetica; line-height: 170%; color: #666666; margin: 5px 0px;"><b>Device Owner: </b> $device-owner</p>
|
||||
</div>
|
||||
<div>
|
||||
<p style="font-size: 1em; font-family: Arial, Helvetica; line-height: 170%; color: #666666; margin: 5px 0px;">$custom-mail-body</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p style="font-length: 1em; font-family: Arial, Helvetica; line-height: 170%; color: #666666; margin: 20px 0px 5px;">
|
||||
If you have any further questions, please reach out to us using your registered mail to
|
||||
<a href="bizdev-group@entgra.io"> bizdev-group@entgra.io.</a> Looking forward to working with you.
|
||||
</p>
|
||||
<p style="font-length: 1em; font-family: Arial, Helvetica; line-height: 170%; color: #666666; margin: 20px 0px 5px;">
|
||||
Best Regards,
|
||||
</p>
|
||||
<p style="font-size: 1em; font-family: Arial, Helvetica; line-height: 170%; color: #666666; margin: 5px 0px;">
|
||||
Entgra Administrator
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
]]>
|
||||
</Body>
|
||||
</EmailConfig>
|
||||
Loading…
Reference in New Issue
Block a user