From 73307b0ada907f8ac857b3dfc4e7d50e3b7b92e9 Mon Sep 17 00:00:00 2001 From: Tomas <tomasysh@gmail.com> Date: 星期一, 24 一月 2022 16:24:52 +0800 Subject: [PATCH] Merge branch 'Phase3' of https://dev.pollex.com.tw:8443/r/pcalife/PAM into Phase3 --- pamapi/src/main/resources/config/application-dev.yml | 18 ++- PAMapp/components/Ui/UiTimePicker.vue | 33 +++++- PAMapp/pages/questionnaire/_agentNo.vue | 11 ++ pamapi/src/main/java/com/pollex/pam/config/Constants.java | 2 PAMapp/components/Ui/UiDatePicker.vue | 20 +++ pamapi/src/doc/sql/淨空整個系統資料(除顧問).sql | 12 ++ pamapi/src/main/java/com/pollex/pam/enums/SendEmailMsgMethod.java | 6 + PAMapp/components/DateTimePicker.vue | 5 + PAMapp/pages/appointment/_appointmentId/close/index.vue | 1 pamapi/src/main/resources/config/application-pollex.yml | 18 ++- pamapi/src/main/resources/config/application-sit.yml | 4 pamapi/src/main/java/com/pollex/pam/service/AppointmentService.java | 3 pamapi/src/main/java/com/pollex/pam/service/SendMsgService.java | 63 +++++++++-- pamapi/src/main/resources/config/application-uat.yml | 4 pamapi/src/main/java/com/pollex/pam/config/ApplicationProperties.java | 37 +++++- PAMapp/assets/scss/vendors/elementUI/_rate.scss | 1 pamapi/src/main/resources/config/application-prod.yml | 4 17 files changed, 194 insertions(+), 48 deletions(-) diff --git a/PAMapp/assets/scss/vendors/elementUI/_rate.scss b/PAMapp/assets/scss/vendors/elementUI/_rate.scss index 48909a5..571b574 100644 --- a/PAMapp/assets/scss/vendors/elementUI/_rate.scss +++ b/PAMapp/assets/scss/vendors/elementUI/_rate.scss @@ -45,6 +45,7 @@ display: flex; justify-content: center; margin-top: 10px; + @extend .fix-chrome-click--issue; .el-rate__item { .el-rate__icon { font-size: 30px; diff --git a/PAMapp/components/DateTimePicker.vue b/PAMapp/components/DateTimePicker.vue index f2a8763..584df86 100644 --- a/PAMapp/components/DateTimePicker.vue +++ b/PAMapp/components/DateTimePicker.vue @@ -5,12 +5,14 @@ <UiDatePicker @changeDate="changeDateTime($event, 'date')" :isPastDateDisabled="isPastDateDisabled" + :isFutureDateDisabled="isFutureDateDisabled" :defaultValue="defaultValue" ></UiDatePicker> <UiTimePicker @changeTime="changeDateTime($event, 'time')" :defaultValue="defaultValue" :isPastDateDisabled="isPastDateDisabled" + :isFutureDateDisabled="isFutureDateDisabled" :changeDate="changeDate" ></UiTimePicker> </div> @@ -30,6 +32,9 @@ @Prop() isPastDateDisabled!: boolean; + @Prop() + isFutureDateDisabled!: boolean; + @Emit('changeDateTime') changeDateTime(event, type) { if (type === 'date') { diff --git a/PAMapp/components/Ui/UiDatePicker.vue b/PAMapp/components/Ui/UiDatePicker.vue index 20132bc..025594a 100644 --- a/PAMapp/components/Ui/UiDatePicker.vue +++ b/PAMapp/components/Ui/UiDatePicker.vue @@ -5,6 +5,7 @@ v-model="dateValue" :clearable="false" type="date" + :editable="false" format="yyyy/MM/dd" placeholder="������" prefix-icon="icon-down down-icon" @@ -27,6 +28,9 @@ @Prop({default: false}) isPastDateDisabled!: boolean; + @Prop({default: false}) + isFutureDateDisabled!: boolean; + @Emit('changeDate') changeDate() { return this.dateValue; @@ -41,16 +45,26 @@ } get pickerOptions() { + const date = new Date(); + const currentDate = `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`; + if (this.isPastDateDisabled) { return { disabledDate(time: Date) { - const date = new Date(); - const currentDate = `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`; - const pickedDate = `${time.getFullYear()}/${time.getMonth() + 1}/${time.getDate()}` + const pickedDate = `${time.getFullYear()}/${time.getMonth() + 1}/${time.getDate()}`; return new Date(pickedDate).getTime() < new Date(currentDate).getTime(); } } } + + if (this.isFutureDateDisabled) { + return { + disabledDate(time: Date) { + const pickedDate = `${time.getFullYear()}/${time.getMonth() + 1}/${time.getDate()}`; + return new Date(pickedDate).getTime() > new Date(currentDate).getTime(); + } + } + } } } diff --git a/PAMapp/components/Ui/UiTimePicker.vue b/PAMapp/components/Ui/UiTimePicker.vue index b661e00..291fbcd 100644 --- a/PAMapp/components/Ui/UiTimePicker.vue +++ b/PAMapp/components/Ui/UiTimePicker.vue @@ -4,6 +4,7 @@ popper-class="pam-time-popper" v-model="timeValue" :clearable="false" + :editable="false" :picker-options="pickerOptions" placeholder="������" prefix-icon="icon-down down-icon" @@ -29,6 +30,9 @@ @Prop() isPastDateDisabled!: boolean; + @Prop() + isFutureDateDisabled!: boolean; + /////////////////////////////////////////////////////////////////////// @Emit('changeTime') @@ -49,25 +53,40 @@ get pickerOptions() { let minTime = ''; + let maxTime = ''; const currentDate = new Date(); - if (this.isPastDateDisabled && this.changeDate && this.isPickedToday(currentDate)) { - minTime = this.formatTimeString(currentDate); - this.isPickedDisableTime(currentDate, minTime); + if (this.changeDate && this.isPickedToday(currentDate)) { + + if (this.isPastDateDisabled) { + minTime = this.formatTimeString(currentDate); + this.isPickedDisableTime(currentDate, minTime); + } + + if (this.isFutureDateDisabled) { + maxTime = this.formatTimeString(currentDate); + this.isPickedDisableTime(currentDate, maxTime); + } + } return { start: '09:00', step: '00:15', end: '21:00', - minTime: minTime + minTime: minTime, + maxTime: maxTime } } - private isPickedDisableTime(currentDate: Date, minTime: string) { - const currentTime = this.getTimeValue(currentDate, minTime); + private isPickedDisableTime(currentDate: Date, minMaxTime: string) { + const currentTime = this.getTimeValue(currentDate, minMaxTime); const pickedTime = this.getTimeValue(currentDate, this.timeValue); - if (pickedTime < currentTime) { + if (this.isPastDateDisabled && pickedTime < currentTime) { + this.timeValue = ''; + this.changeTime(); + } + if (this.isFutureDateDisabled && currentTime < pickedTime) { this.timeValue = ''; this.changeTime(); } diff --git a/PAMapp/pages/appointment/_appointmentId/close/index.vue b/PAMapp/pages/appointment/_appointmentId/close/index.vue index d10476c..a267a72 100644 --- a/PAMapp/pages/appointment/_appointmentId/close/index.vue +++ b/PAMapp/pages/appointment/_appointmentId/close/index.vue @@ -46,6 +46,7 @@ <UiField label="�脖辣����" :labelSize="20" class="required"> <DateTimePicker :defaultValue="appointmentCloseInfo.policyEntryDate" + :isFutureDateDisabled="true" @changeDateTime="appointmentCloseDate = $event"></DateTimePicker> </UiField> </el-row> diff --git a/PAMapp/pages/questionnaire/_agentNo.vue b/PAMapp/pages/questionnaire/_agentNo.vue index cc1ccc5..cb8c164 100644 --- a/PAMapp/pages/questionnaire/_agentNo.vue +++ b/PAMapp/pages/questionnaire/_agentNo.vue @@ -24,8 +24,12 @@ <div class="ques-header__input-block"> <span>Email嚗�</span> <input class="ques-header__input" + :class="{ 'is-invalid': !emailValid}" placeholder="隢撓�" v-model="myRequest.email"> + </div> + <div class="error mt-5 mb-5" style="margin-left:65px"> + <span v-show="!emailValid">Email�撘�炊</span> </div> </div> </div> @@ -466,6 +470,11 @@ : true; } + get emailValid() { + const rule = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/; + return this.myRequest.email ? rule.test(this.myRequest.email) : true; + } + get userInfo(): RegisterInfo { const initUserInfo = JSON.parse(localStorage.getItem('userInfo')!); return initUserInfo; @@ -473,7 +482,7 @@ get isDisabledSubmitBtn(): boolean { return _.includes(this.myRequest.contactType,ContactType.PHONE) - ? !this.isHopeContactTimeDone() + ? !this.isHopeContactTimeDone() || !this.emailValid : !this.phoneValid; } diff --git "a/pamapi/src/doc/sql/\346\267\250\347\251\272\346\225\264\345\200\213\347\263\273\347\265\261\350\263\207\346\226\231\050\351\231\244\351\241\247\345\225\217\051.sql" "b/pamapi/src/doc/sql/\346\267\250\347\251\272\346\225\264\345\200\213\347\263\273\347\265\261\350\263\207\346\226\231\050\351\231\244\351\241\247\345\225\217\051.sql" new file mode 100644 index 0000000..963ed9f --- /dev/null +++ "b/pamapi/src/doc/sql/\346\267\250\347\251\272\346\225\264\345\200\213\347\263\273\347\265\261\350\263\207\346\226\231\050\351\231\244\351\241\247\345\225\217\051.sql" @@ -0,0 +1,12 @@ +truncate public.appointment; +truncate public.appointment_closed_info; +truncate public.appointment_expiring_notify_record; +truncate public.appointment_memo; +truncate public.appointment_notice_log; +truncate public.customer; +truncate public.interview_record; +truncate public.login_record; +truncate public.otp_tmp; +truncate public.personal_notification; +truncate public.satisfaction; +truncate public.customer_favorite_consultant; diff --git a/pamapi/src/main/java/com/pollex/pam/config/ApplicationProperties.java b/pamapi/src/main/java/com/pollex/pam/config/ApplicationProperties.java index d4b2b36..60b33ca 100644 --- a/pamapi/src/main/java/com/pollex/pam/config/ApplicationProperties.java +++ b/pamapi/src/main/java/com/pollex/pam/config/ApplicationProperties.java @@ -1,5 +1,6 @@ package com.pollex.pam.config; +import com.pollex.pam.enums.SendEmailMsgMethod; import org.springframework.boot.context.properties.ConfigurationProperties; /** @@ -19,7 +20,6 @@ private String eServiceLoginFunc; private String eServiceLoginSys; private String frontEndDomain; - private boolean sendNotifyMsg; private SMS sms; private Email email; private String fileFolderPath; @@ -88,14 +88,6 @@ this.frontEndDomain = frontEndDomain; } - public boolean isSendNotifyMsg() { - return sendNotifyMsg; - } - - public void setSendNotifyMsg(boolean sendNotifyMsg) { - this.sendNotifyMsg = sendNotifyMsg; - } - public SMS getSms() { return sms; } @@ -118,6 +110,7 @@ private String sender; private String smsType; private String subject; + private boolean sendNotifyMsg; public String getUrl() { return url; @@ -158,12 +151,22 @@ public void setSubject(String subject) { this.subject = subject; } + + public boolean isSendNotifyMsg() { + return sendNotifyMsg; + } + + public void setSendNotifyMsg(boolean sendNotifyMsg) { + this.sendNotifyMsg = sendNotifyMsg; + } } public static class Email { private String url; private String functionId; private String senderEmail; + private boolean sendNotifyMsg; + private SendEmailMsgMethod method; public String getUrl() { return url; @@ -188,6 +191,22 @@ public void setSenderEmail(String senderEmail) { this.senderEmail = senderEmail; } + + public boolean isSendNotifyMsg() { + return sendNotifyMsg; + } + + public void setSendNotifyMsg(boolean sendNotifyMsg) { + this.sendNotifyMsg = sendNotifyMsg; + } + + public SendEmailMsgMethod getMethod() { + return method; + } + + public void setMethod(SendEmailMsgMethod method) { + this.method = method; + } } public String getFileFolderPath() { return fileFolderPath; diff --git a/pamapi/src/main/java/com/pollex/pam/config/Constants.java b/pamapi/src/main/java/com/pollex/pam/config/Constants.java index aae9b67..87dd25b 100644 --- a/pamapi/src/main/java/com/pollex/pam/config/Constants.java +++ b/pamapi/src/main/java/com/pollex/pam/config/Constants.java @@ -30,5 +30,7 @@ */ public static final int SEND_EXPIRING_NOTIFY_LIMIT = 1; + public static final String SPRING_PROFILE_POLLEX_DEVELOPMENT = "pollex"; + private Constants() {} } diff --git a/pamapi/src/main/java/com/pollex/pam/enums/SendEmailMsgMethod.java b/pamapi/src/main/java/com/pollex/pam/enums/SendEmailMsgMethod.java new file mode 100644 index 0000000..42a10ce --- /dev/null +++ b/pamapi/src/main/java/com/pollex/pam/enums/SendEmailMsgMethod.java @@ -0,0 +1,6 @@ +package com.pollex.pam.enums; + +public enum SendEmailMsgMethod { + PAM_EMAIL_SERVICE, + POLLEX_GMAIL +} diff --git a/pamapi/src/main/java/com/pollex/pam/service/AppointmentService.java b/pamapi/src/main/java/com/pollex/pam/service/AppointmentService.java index 6d5ded6..3ae99c4 100644 --- a/pamapi/src/main/java/com/pollex/pam/service/AppointmentService.java +++ b/pamapi/src/main/java/com/pollex/pam/service/AppointmentService.java @@ -200,7 +200,8 @@ public void sendAppointmentNotify(Appointment appointment) { Assert.notNull(appointment, "appointment entity cannot be null"); - log.debug("is need send appointment notify msg? = {}", applicationProperties.isSendNotifyMsg()); + log.debug("is need send appointment notify msg? sms = {}, email = {}", + applicationProperties.getSms().isSendNotifyMsg(), applicationProperties.getEmail().isSendNotifyMsg()); log.debug("sending appointment notify, appointmentId = {}", appointment.getId()); sendAppointmentNotifyBySMS(appointment); diff --git a/pamapi/src/main/java/com/pollex/pam/service/SendMsgService.java b/pamapi/src/main/java/com/pollex/pam/service/SendMsgService.java index 05d8d73..a5be71e 100644 --- a/pamapi/src/main/java/com/pollex/pam/service/SendMsgService.java +++ b/pamapi/src/main/java/com/pollex/pam/service/SendMsgService.java @@ -2,7 +2,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.pollex.pam.config.ApplicationProperties; +import com.pollex.pam.config.ApplicationProperties.Email; import com.pollex.pam.config.ApplicationProperties.SMS; +import com.pollex.pam.config.Constants; +import com.pollex.pam.enums.SendEmailMsgMethod; import com.pollex.pam.repository.ConsultantRepository; import com.pollex.pam.service.dto.*; import com.pollex.pam.service.util.HttpRequestUtil; @@ -11,9 +14,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.core.env.Profiles; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.thymeleaf.spring5.SpringTemplateEngine; +import tech.jhipster.config.JHipsterConstants; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; @@ -38,13 +44,19 @@ @Autowired SpringTemplateEngine springTemplateEngine; + @Autowired + Environment environment; + + @Autowired + MailService mailService; + public SendSMSResponse sendMsgBySMS(String toMobile, String content) throws SendSMSFailException { - if(!applicationProperties.isSendNotifyMsg()) { + + SMS smsProperties = applicationProperties.getSms(); + if(!smsProperties.isSendNotifyMsg()) { // return getMockSMSResponse(); - return null; - } - - SMS smsProperties = applicationProperties.getSms(); + return null; + } SendSMSRequest sendSMSRequest = new SendSMSRequest(); sendSMSRequest.setpKey(UUID.randomUUID().toString()); @@ -94,7 +106,7 @@ public String sendMsgByEmail(String toAddress, String subject, String content, boolean htmlFormat, List<String> toCCAddress, List<String> attachments) throws SendEmailFailException { String fromAddress = applicationProperties.getEmail().getSenderEmail(); - + SendMailRequest sendMailRequest = new SendMailRequest(); sendMailRequest.setSendMailAddresses(Collections.singletonList(toAddress)); sendMailRequest.setFrom(fromAddress); @@ -109,25 +121,48 @@ } public String sendMsgByEmail(SendMailRequest sendMailRequest) throws SendEmailFailException{ - if(!applicationProperties.isSendNotifyMsg()) { - return null; - } - try { + final Email emailProperties = applicationProperties.getEmail(); + + if(!emailProperties.isSendNotifyMsg()) { + return null; + } + + if(emailProperties.getMethod() == SendEmailMsgMethod.POLLEX_GMAIL) { + return sendMsgByPollexGmail(sendMailRequest); + } + else if(emailProperties.getMethod() == SendEmailMsgMethod.PAM_EMAIL_SERVICE) { + return sendMsgByPamEmailService(sendMailRequest); + } + + return null; + } + + private String sendMsgByPollexGmail(SendMailRequest sendMailRequest) { + String subject = sendMailRequest.getSubject(); + String content = sendMailRequest.getContent(); + boolean isHtml = sendMailRequest.isHtmlFormat(); + sendMailRequest.getSendMailAddresses().forEach(receiver -> mailService.sendEmail(receiver, subject, content, false, isHtml)); + + return null; + } + + private String sendMsgByPamEmailService(SendMailRequest sendMailRequest) { + final Email emailProperties = applicationProperties.getEmail(); + try { ResponseEntity<String> responseEntity = - HttpRequestUtil.postWithJson( applicationProperties.getEmail().getUrl(), sendMailRequest, String.class); + HttpRequestUtil.postWithJson(emailProperties.getUrl(), sendMailRequest, String.class); log.debug("responseEntity = {}", responseEntity); String rawResponseString = responseEntity.getBody(); SendMailResponse sendMailResponse = new ObjectMapper().readValue(rawResponseString, SendMailResponse.class); log.debug("sendMailResponse = {}", sendMailResponse); - if(sendMailResponse == null || sendMailResponse.getData() == null || !"ADDED".equalsIgnoreCase(sendMailResponse.getData().getMessageStatus())) { + if (sendMailResponse == null || sendMailResponse.getData() == null || !"ADDED".equalsIgnoreCase(sendMailResponse.getData().getMessageStatus())) { throw new SendEmailFailException("send email service return error msg! raw response string= " + rawResponseString); } return responseEntity.getBody(); - } - catch (SendEmailFailException e) { + } catch (SendEmailFailException e) { throw e; } catch (Exception e) { log.warn("send email fail by other reason", e); diff --git a/pamapi/src/main/resources/config/application-dev.yml b/pamapi/src/main/resources/config/application-dev.yml index ced80df..e612913 100644 --- a/pamapi/src/main/resources/config/application-dev.yml +++ b/pamapi/src/main/resources/config/application-dev.yml @@ -45,10 +45,16 @@ # Remove 'faker' if you do not want the sample data to be loaded automatically contexts: dev, faker mail: - host: localhost - port: 25 - username: - password: + host: smtp.gmail.com + port: 587 + username: pollex.testing@gmail.com + password: ilismmmhtscppxft + properties: + mail: + smtp: + auth: true + starttls: + enable: true messages: cache-duration: PT1S # 1 second, see the ISO 8601 standard thymeleaf: @@ -120,15 +126,17 @@ e-service-login-func: ValidateUsrLogin e-service-login-sys: epos front-end-domain: http://localhost:3000 - send-notify-msg: false sms: + send-notify-msg: false url: https://localhost:8081/testSMS source-code: ePos sender: POS sms-type: '0017' subject: '慦�像��' email: + send-notify-msg: false url: https://localhost:8081/testEmail function-id: epos sender-email: noreply@pcalife.com.tw + method: 'POLLEX_GMAIL' file-folder-path: C://pam_file diff --git a/pamapi/src/main/resources/config/application-pollex.yml b/pamapi/src/main/resources/config/application-pollex.yml index e1b1955..e6a2ae8 100644 --- a/pamapi/src/main/resources/config/application-pollex.yml +++ b/pamapi/src/main/resources/config/application-pollex.yml @@ -43,10 +43,16 @@ # Remove 'faker' if you do not want the sample data to be loaded automatically contexts: pollex, faker mail: - host: localhost - port: 25 - username: - password: + host: smtp.gmail.com + port: 587 + username: pollex.testing@gmail.com + password: ilismmmhtscppxft + properties: + mail: + smtp: + auth: true + starttls: + enable: true messages: cache-duration: PT1S # 1 second, see the ISO 8601 standard thymeleaf: @@ -118,15 +124,17 @@ e-service-login-func: ValidateUsrLogin e-service-login-sys: epos front-end-domain: http://dev.pollex.com.tw:5566/pam - send-notify-msg: false sms: + send-notify-msg: false url: https://localhost:8081/testSMS source-code: ePos sender: POS sms-type: '0017' subject: '慦�像��' email: + send-notify-msg: true url: https://localhost:8081/testEmail function-id: epos sender-email: noreply@pcalife.com.tw + method: 'POLLEX_GMAIL' file-folder-path: C://pam_file diff --git a/pamapi/src/main/resources/config/application-prod.yml b/pamapi/src/main/resources/config/application-prod.yml index 71773a9..90ff8b7 100644 --- a/pamapi/src/main/resources/config/application-prod.yml +++ b/pamapi/src/main/resources/config/application-prod.yml @@ -140,15 +140,17 @@ e-service-login-func: ValidateUsrLogin e-service-login-sys: epos front-end-domain: https://vtwlifeopensysuat.pru.intranet.asia/pam - send-notify-msg: true sms: + send-notify-msg: true url: https://vtwlifeopensysuat.pru.intranet.asia/MesgQueueMgmnt/rest/smsSendMsgResource source-code: ePos sender: POS sms-type: '0017' subject: '慦�像��' email: + send-notify-msg: true url: https://vtwlifeopensysuat.pru.intranet.asia/tsgw/mq/mqSendMail function-id: epos sender-email: noreply@pcalife.com.tw + method: 'PAM_EMAIL_SERVICE' file-folder-path: /sfs_omo/vtwlifewpsfs01/SensitiveData4AP$/OMO diff --git a/pamapi/src/main/resources/config/application-sit.yml b/pamapi/src/main/resources/config/application-sit.yml index 4f4c25c..402dcef 100644 --- a/pamapi/src/main/resources/config/application-sit.yml +++ b/pamapi/src/main/resources/config/application-sit.yml @@ -118,15 +118,17 @@ e-service-login-func: ValidateUsrLogin e-service-login-sys: epos front-end-domain: https://vtwlifeopensyssit.pru.intranet.asia/pam - send-notify-msg: true sms: + send-notify-msg: true url: https://vtwlifeopensysuat.pru.intranet.asia/MesgQueueMgmnt/rest/smsSendMsgResource source-code: ePos sender: POS sms-type: '0017' subject: '慦�像��' email: + send-notify-msg: true url: https://vtwlifeopensysuat.pru.intranet.asia/tsgw/mq/mqSendMail function-id: epos sender-email: noreply@pcalife.com.tw + method: 'PAM_EMAIL_SERVICE' file-folder-path: /sfs_omo/vtwlifewuftp66/sensitivedata4ap$/OMOSIT diff --git a/pamapi/src/main/resources/config/application-uat.yml b/pamapi/src/main/resources/config/application-uat.yml index 15f5390..28d8c16 100644 --- a/pamapi/src/main/resources/config/application-uat.yml +++ b/pamapi/src/main/resources/config/application-uat.yml @@ -118,15 +118,17 @@ e-service-login-func: ValidateUsrLogin e-service-login-sys: epos front-end-domain: https://vtwlifeopensysuat.pru.intranet.asia/pam - send-notify-msg: true sms: + send-notify-msg: true url: https://vtwlifeopensysuat.pru.intranet.asia/MesgQueueMgmnt/rest/smsSendMsgResource source-code: ePos sender: POS sms-type: '0017' subject: '慦�像��' email: + send-notify-msg: true url: https://vtwlifeopensysuat.pru.intranet.asia/tsgw/mq/mqSendMail function-id: epos sender-email: noreply@pcalife.com.tw + method: 'PAM_EMAIL_SERVICE' file-folder-path: /sfs_omo/vtwlifewuftp66/sensitivedata4ap$/OMO -- Gitblit v1.8.0