This is an automated email from the ASF dual-hosted git repository.
Aias00 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hertzbeat.git
The following commit(s) were added to refs/heads/master by this push:
new b0d8516822 [feature] add SSL certificate verification toggle for email
server (#4327)
b0d8516822 is described below
commit b0d8516822853af240b72cf1c52277eb52d57ec0
Author: NekoPunch <[email protected]>
AuthorDate: Tue Aug 25 20:26:32 2026 -0700
[feature] add SSL certificate verification toggle for email server (#4327)
---
.../notice/impl/EmailAlertNotifyHandlerImpl.java | 13 ++++++++
.../impl/EmailAlertNotifyHandlerImplTest.java | 36 ++++++++++++++++++++++
.../common/entity/dto/MailServerConfig.java | 2 ++
web-app/src/app/pojo/EmailNoticeSender.ts | 1 +
.../message-server/message-server.component.html | 8 +++++
web-app/src/assets/i18n/en-US.json | 1 +
web-app/src/assets/i18n/ja-JP.json | 1 +
web-app/src/assets/i18n/ko-KR.json | 1 +
web-app/src/assets/i18n/pt-BR.json | 1 +
web-app/src/assets/i18n/zh-CN.json | 1 +
web-app/src/assets/i18n/zh-TW.json | 1 +
11 files changed, 66 insertions(+)
diff --git
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/EmailAlertNotifyHandlerImpl.java
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/EmailAlertNotifyHandlerImpl.java
index f2d8f7eb02..a0e9fac809 100644
---
a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/EmailAlertNotifyHandlerImpl.java
+++
b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/EmailAlertNotifyHandlerImpl.java
@@ -98,6 +98,7 @@ public class EmailAlertNotifyHandlerImpl extends
AbstractAlertNotifyHandlerImpl
Properties props = sender.getJavaMailProperties();
props.put("mail.smtp.ssl.enable",
emailNoticeSenderConfig.isEmailSsl());
props.put("mail.smtp.starttls.enable",
emailNoticeSenderConfig.isEmailStarttls());
+ applySslCertVerify(props,
emailNoticeSenderConfig.isEmailSslCertVerify());
fromUsername =
emailNoticeSenderConfig.getEmailUsername();
useDatabase = true;
}
@@ -111,6 +112,7 @@ public class EmailAlertNotifyHandlerImpl extends
AbstractAlertNotifyHandlerImpl
Properties props = sender.getJavaMailProperties();
props.put("mail.smtp.ssl.enable", sslEnable);
props.put("mail.smtp.starttls.enable", starttlsEnable);
+ applySslCertVerify(props, true);
}
} catch (Exception e) {
log.error("Type not found {}", e.getMessage());
@@ -133,6 +135,17 @@ public class EmailAlertNotifyHandlerImpl extends
AbstractAlertNotifyHandlerImpl
}
}
+ // the sender is a singleton, so both branches must set the props to avoid
stale state
+ private void applySslCertVerify(Properties props, boolean verify) {
+ if (verify) {
+ props.remove("mail.smtp.ssl.trust");
+ props.remove("mail.smtp.ssl.checkserveridentity");
+ } else {
+ props.put("mail.smtp.ssl.trust", "*");
+ props.put("mail.smtp.ssl.checkserveridentity", "false");
+ }
+ }
+
@Override
public byte type() {
return 1;
diff --git
a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/notice/impl/EmailAlertNotifyHandlerImplTest.java
b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/notice/impl/EmailAlertNotifyHandlerImplTest.java
index 901b27fae5..31fe45fdad 100644
---
a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/notice/impl/EmailAlertNotifyHandlerImplTest.java
+++
b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/notice/impl/EmailAlertNotifyHandlerImplTest.java
@@ -17,6 +17,8 @@
package org.apache.hertzbeat.alert.notice.impl;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.lenient;
@@ -124,6 +126,40 @@ class EmailAlertNotifyHandlerImplTest {
verify(mailSender).send(any(MimeMessage.class));
}
+ @Test
+ public void testSkipSslCertVerifyTrustsAllHosts() throws Exception {
+ Properties props = stubMailConfig(false);
+ emailAlertNotifyHandler.send(receiver, template, groupAlert);
+ assertEquals("*", props.get("mail.smtp.ssl.trust"));
+ assertEquals("false", props.get("mail.smtp.ssl.checkserveridentity"));
+ }
+
+ @Test
+ public void testEnableSslCertVerifyClearsStaleTrustProps() throws
Exception {
+ Properties props = stubMailConfig(true);
+ props.put("mail.smtp.ssl.trust", "*");
+ props.put("mail.smtp.ssl.checkserveridentity", "false");
+ emailAlertNotifyHandler.send(receiver, template, groupAlert);
+ assertNull(props.get("mail.smtp.ssl.trust"));
+ assertNull(props.get("mail.smtp.ssl.checkserveridentity"));
+ }
+
+ private Properties stubMailConfig(boolean sslCertVerify) {
+ MailServerConfig config = new MailServerConfig();
+ config.setEmailHost("smtp.example.com");
+ config.setEmailPort(465);
+ config.setEmailUsername("[email protected]");
+ config.setEmailPassword("password");
+ config.setEnable(true);
+ config.setEmailSslCertVerify(sslCertVerify);
+ when(generalConfigDao.findByType(any()))
+
.thenReturn(GeneralConfig.builder().content(JsonUtil.toJson(config)).build());
+ Properties props = new Properties();
+ when(mailSender.getJavaMailProperties()).thenReturn(props);
+ when(mailSender.createMimeMessage()).thenReturn(mimeMessage);
+ return props;
+ }
+
@Test
public void testNotifyAlertFailure() {
when(mailSender.createMimeMessage()).thenThrow(new
RuntimeException("Test Error"));
diff --git
a/hertzbeat-common-core/src/main/java/org/apache/hertzbeat/common/entity/dto/MailServerConfig.java
b/hertzbeat-common-core/src/main/java/org/apache/hertzbeat/common/entity/dto/MailServerConfig.java
index 3c99b34ab6..b51b3ea06d 100644
---
a/hertzbeat-common-core/src/main/java/org/apache/hertzbeat/common/entity/dto/MailServerConfig.java
+++
b/hertzbeat-common-core/src/main/java/org/apache/hertzbeat/common/entity/dto/MailServerConfig.java
@@ -56,5 +56,7 @@ public class MailServerConfig {
private boolean emailStarttls = false;
+ private boolean emailSslCertVerify = true;
+
private boolean enable = true;
}
diff --git a/web-app/src/app/pojo/EmailNoticeSender.ts
b/web-app/src/app/pojo/EmailNoticeSender.ts
index 9d4ffea819..1a8a1c6788 100644
--- a/web-app/src/app/pojo/EmailNoticeSender.ts
+++ b/web-app/src/app/pojo/EmailNoticeSender.ts
@@ -25,6 +25,7 @@ export class EmailNoticeSender {
emailPassword!: string;
emailSsl: boolean = true;
emailStarttls: boolean = false;
+ emailSslCertVerify: boolean = true;
enable!: boolean;
creator!: string;
modifier!: string;
diff --git
a/web-app/src/app/routes/setting/settings/message-server/message-server.component.html
b/web-app/src/app/routes/setting/settings/message-server/message-server.component.html
index a804f51547..57290b5203 100644
---
a/web-app/src/app/routes/setting/settings/message-server/message-server.component.html
+++
b/web-app/src/app/routes/setting/settings/message-server/message-server.component.html
@@ -134,6 +134,14 @@
<nz-switch [(ngModel)]="emailSender.emailStarttls" required
name="emailStarttls" id="emailStarttls"></nz-switch>
</nz-form-control>
</nz-form-item>
+ <nz-form-item *ngIf="emailSender.emailSsl || emailSender.emailStarttls">
+ <nz-form-label nzSpan="7" nzFor="emailSslCertVerify"
nzRequired="true">{{
+ 'alert.notice.sender.mail.ssl-cert-verify' | i18n
+ }}</nz-form-label>
+ <nz-form-control nzSpan="12">
+ <nz-switch [(ngModel)]="emailSender.emailSslCertVerify" required
name="emailSslCertVerify" id="emailSslCertVerify"></nz-switch>
+ </nz-form-control>
+ </nz-form-item>
<nz-form-item>
<nz-form-label nzSpan="7" nzFor="emailEnable" nzRequired="true">{{
'common.enable' | i18n }}</nz-form-label>
<nz-form-control nzSpan="12">
diff --git a/web-app/src/assets/i18n/en-US.json
b/web-app/src/assets/i18n/en-US.json
index 32ac9d0b7f..0b5c837cc5 100644
--- a/web-app/src/assets/i18n/en-US.json
+++ b/web-app/src/assets/i18n/en-US.json
@@ -147,6 +147,7 @@
"alert.notice.sender.mail.port": "Email Port",
"alert.notice.sender.mail.ssl": "Enable SSL",
"alert.notice.sender.mail.starttls": "Enable STARTTLS",
+ "alert.notice.sender.mail.ssl-cert-verify": "Verify SSL Certificate",
"alert.notice.sender.mail.username": "Email Account",
"alert.notice.sender.sms.tencent.appId": "Tencent Sms AppId",
"alert.notice.sender.sms.tencent.secretId": "Tencent Sms SecretId",
diff --git a/web-app/src/assets/i18n/ja-JP.json
b/web-app/src/assets/i18n/ja-JP.json
index dcdcaeef5d..8df517eec8 100644
--- a/web-app/src/assets/i18n/ja-JP.json
+++ b/web-app/src/assets/i18n/ja-JP.json
@@ -146,6 +146,7 @@
"alert.notice.sender.mail.port": "メールポート",
"alert.notice.sender.mail.ssl": "SSLを有効化",
"alert.notice.sender.mail.starttls": "STARTTLSを有効化",
+ "alert.notice.sender.mail.ssl-cert-verify": "SSL証明書を検証",
"alert.notice.sender.mail.username": "メールアカウント",
"alert.notice.sender.sms.tencent.appId": "Tencent Sms AppId",
"alert.notice.sender.sms.tencent.secretId": "Tencent Sms SecretId",
diff --git a/web-app/src/assets/i18n/ko-KR.json
b/web-app/src/assets/i18n/ko-KR.json
index 0dd23716b5..1a77de3774 100644
--- a/web-app/src/assets/i18n/ko-KR.json
+++ b/web-app/src/assets/i18n/ko-KR.json
@@ -147,6 +147,7 @@
"alert.notice.sender.mail.port": "이메일 포트",
"alert.notice.sender.mail.ssl": "SSL 활성화",
"alert.notice.sender.mail.starttls": "STARTTLS 활성화",
+ "alert.notice.sender.mail.ssl-cert-verify": "SSL 인증서 검증",
"alert.notice.sender.mail.username": "이메일 계정",
"alert.notice.sender.sms.tencent.appId": "Tencent SMS AppId",
"alert.notice.sender.sms.tencent.secretId": "Tencent SMS SecretId",
diff --git a/web-app/src/assets/i18n/pt-BR.json
b/web-app/src/assets/i18n/pt-BR.json
index e8761d9a90..bf2a3e6e36 100644
--- a/web-app/src/assets/i18n/pt-BR.json
+++ b/web-app/src/assets/i18n/pt-BR.json
@@ -233,6 +233,7 @@
"alert.notice.sender.mail.port": "Porta do Email",
"alert.notice.sender.mail.ssl": "Habilitar SSL",
"alert.notice.sender.mail.starttls": "Habilitar STARTTLS",
+ "alert.notice.sender.mail.ssl-cert-verify": "Verificar Certificado SSL",
"alert.notice.sender.mail.enable": "Habilitar Configuração de Email",
"alert.notice.sender.sms.type": "Tipo de SMS",
"alert.notice.sender.sms.type.tencent": "SMS Tencent",
diff --git a/web-app/src/assets/i18n/zh-CN.json
b/web-app/src/assets/i18n/zh-CN.json
index 5282863db7..9c1059dbf0 100644
--- a/web-app/src/assets/i18n/zh-CN.json
+++ b/web-app/src/assets/i18n/zh-CN.json
@@ -147,6 +147,7 @@
"alert.notice.sender.mail.port": "邮箱端口",
"alert.notice.sender.mail.ssl": "是否启用SSL",
"alert.notice.sender.mail.starttls": "是否启用STARTTLS",
+ "alert.notice.sender.mail.ssl-cert-verify": "是否校验SSL证书",
"alert.notice.sender.mail.username": "邮箱账号",
"alert.notice.sender.sms.tencent.appId": "腾讯短信AppId",
"alert.notice.sender.sms.tencent.secretId": "腾讯短信SecretId",
diff --git a/web-app/src/assets/i18n/zh-TW.json
b/web-app/src/assets/i18n/zh-TW.json
index 239c8375b5..8e4b95974a 100644
--- a/web-app/src/assets/i18n/zh-TW.json
+++ b/web-app/src/assets/i18n/zh-TW.json
@@ -146,6 +146,7 @@
"alert.notice.sender.mail.port": "郵件端口",
"alert.notice.sender.mail.ssl": "是否啟用SSL",
"alert.notice.sender.mail.starttls": "是否啟用STARTTLS",
+ "alert.notice.sender.mail.ssl-cert-verify": "是否校驗SSL證書",
"alert.notice.sender.mail.username": "郵件帳號",
"alert.notice.sender.sms.tencent.appId": "騰訊短訊AppId",
"alert.notice.sender.sms.tencent.secretId": "騰訊短訊SecretId",
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]