[improve] remove UniSMS SMS provider as the service has shut down (#4395)

Co-authored-by: shown <yuluo08290126@gmail.com>
This commit is contained in:
Duansg
2026-09-24 10:36:13 +08:00
committed by GitHub
co-authored by shown
parent 0b351ff9c6
commit 57504a302d
28 changed files with 21 additions and 726 deletions
@@ -23,7 +23,6 @@ import org.apache.hertzbeat.alert.service.impl.SmsLocalSmsClientImpl;
import org.apache.hertzbeat.alert.service.impl.AwsSmsClientImpl;
import org.apache.hertzbeat.alert.service.impl.TencentSmsClientImpl;
import org.apache.hertzbeat.alert.service.impl.TwilioSmsClientImpl;
import org.apache.hertzbeat.alert.service.impl.UniSmsClientImpl;
import org.apache.hertzbeat.alert.service.impl.AlibabaSmsClientImpl;
import org.apache.hertzbeat.base.dao.GeneralConfigDao;
import org.apache.hertzbeat.common.constants.GeneralConfigTypeEnum;
@@ -37,7 +36,6 @@ import static org.apache.hertzbeat.common.constants.SmsConstants.ALIBABA;
import static org.apache.hertzbeat.common.constants.SmsConstants.AWS;
import static org.apache.hertzbeat.common.constants.SmsConstants.TENCENT;
import static org.apache.hertzbeat.common.constants.SmsConstants.TWILIO;
import static org.apache.hertzbeat.common.constants.SmsConstants.UNISMS;
import static org.apache.hertzbeat.common.constants.SmsConstants.SMSLOCAL;
/**
@@ -129,9 +127,6 @@ public class SmsClientFactory {
case TENCENT:
currentSmsClient = new TencentSmsClientImpl(smsConfig.getTencent());
break;
case UNISMS:
currentSmsClient = new UniSmsClientImpl(smsConfig.getUnisms());
break;
case ALIBABA:
currentSmsClient = new AlibabaSmsClientImpl(smsConfig.getAlibaba());
break;
@@ -1,198 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.apache.hertzbeat.alert.service.impl;
import lombok.extern.slf4j.Slf4j;
import org.apache.hertzbeat.common.entity.dto.sms.UniSmsProperties;
import org.apache.hertzbeat.alert.service.SmsClient;
import org.apache.hertzbeat.common.entity.alerter.GroupAlert;
import org.apache.hertzbeat.common.entity.alerter.NoticeReceiver;
import org.apache.hertzbeat.common.entity.alerter.NoticeTemplate;
import org.apache.hertzbeat.common.support.exception.SendMessageException;
import org.apache.hertzbeat.common.util.JsonUtil;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.hertzbeat.alert.util.CryptoUtils;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;
import java.util.stream.Collectors;
import tools.jackson.databind.JsonNode;
import static org.apache.hertzbeat.common.constants.SmsConstants.UNISMS;
/**
* UniSMS client implementation <br/>
* doc:<a href="https://unisms.apistd.com/docs/api/send">https://unisms.apistd.com/docs/api/send</a>
*/
@Slf4j
public class UniSmsClientImpl implements SmsClient {
private static final String API_URL = "https://uni.apistd.com";
private static final String ACTION = "sms.message.send";
private static final String SUCCESS_CODE = "0";
private static final String HMAC_ALGORITHM = "hmac-sha256";
private final UniSmsProperties config;
public UniSmsClientImpl(UniSmsProperties config) {
this.config = config;
}
@Override
public void sendMessage(NoticeReceiver receiver, NoticeTemplate noticeTemplate, GroupAlert alert) {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
// build request parameters
Map<String, Object> params = new HashMap<>();
params.put("to", receiver.getPhone());
params.put("signature", config.getSignature());
params.put("templateId", config.getTemplateId());
// build template data
Map<String, String> templateData = new HashMap<>();
String instance = alert.getCommonLabels().getOrDefault("instance", alert.getGroupKey());
String priority = alert.getCommonLabels().getOrDefault("priority", "unknown");
String content = alert.getCommonAnnotations().get("summary");
content = content == null ? alert.getCommonAnnotations().get("description") : content;
if (content == null) {
content = alert.getCommonAnnotations().values().stream().findFirst().orElse(null);
}
templateData.put("instance", instance);
templateData.put("priority", priority);
templateData.put("content", content);
params.put("templateData", templateData);
// build URL and request headers
String url;
if ("hmac".equalsIgnoreCase(config.getAuthMode())) {
url = buildHmacUrl();
} else {
url = buildSimpleUrl();
}
// send HTTP request
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("Content-Type", "application/json");
httpPost.setHeader("Accept", "application/json");
String payload = JsonUtil.toJson(params);
httpPost.setEntity(new StringEntity(payload, StandardCharsets.UTF_8));
log.debug("Sending SMS request via UniSMS");
try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
handleResponse(response);
}
} catch (SendMessageException e) {
log.warn("Failed to send SMS via UniSMS");
throw e;
} catch (Exception e) {
log.warn("Failed to send SMS via UniSMS, failure type: {}", e.getClass().getSimpleName());
throw SmsFailureMessages.requestFailed("UniSMS");
}
}
private String buildSimpleUrl() {
return String.format("%s/?action=%s&accessKeyId=%s",
API_URL, ACTION, config.getAccessKeyId());
}
private String buildHmacUrl() {
long timestamp = System.currentTimeMillis();
String nonce = generateNonce();
// build query parameters
Map<String, String> params = new TreeMap<>();
params.put("accessKeyId", config.getAccessKeyId());
params.put("action", ACTION);
params.put("algorithm", HMAC_ALGORITHM);
params.put("nonce", nonce);
params.put("timestamp", String.valueOf(timestamp));
// build sign text
String signText = params.entrySet().stream()
.map(entry -> entry.getKey() + "=" + entry.getValue())
.collect(Collectors.joining("&"));
// calculate signature
String signature = CryptoUtils.hmacSha256Base64(config.getAccessKeySecret(), signText);
return String.format("%s/?action=%s&accessKeyId=%s&algorithm=%s&timestamp=%d&nonce=%s&signature=%s",
API_URL, ACTION, config.getAccessKeyId(), HMAC_ALGORITHM, timestamp, nonce, signature);
}
private String generateNonce() {
return UUID.randomUUID().toString().replace("-", "").substring(0, 16);
}
private void handleResponse(CloseableHttpResponse response) throws IOException {
int statusCode = response.getStatusLine().getStatusCode();
String responseBody = EntityUtils.toString(response.getEntity());
log.debug("UniSMS response status: {}", statusCode);
if (statusCode != 200) {
throw SmsFailureMessages.httpStatus("UniSMS", statusCode);
}
JsonNode jsonResponse = JsonUtil.fromJson(responseBody);
if (jsonResponse == null || jsonResponse.get("code") == null) {
throw SmsFailureMessages.invalidResponse("UniSMS");
}
String code = jsonResponse.get("code").asText();
if (!SUCCESS_CODE.equals(code)) {
throw SmsFailureMessages.providerCode("UniSMS", code);
}
log.info("Successfully sent SMS via UniSMS");
}
@Override
public String getType() {
return UNISMS;
}
@Override
public boolean checkConfig() {
if (config == null
|| config.getAccessKeyId() == null
|| config.getAccessKeyId().isBlank()
|| config.getSignature() == null
|| config.getSignature().isBlank()
|| config.getTemplateId() == null
|| config.getTemplateId().isBlank()) {
return false;
}
// HMAC mode requires additional check for accessKeySecret
if ("hmac".equalsIgnoreCase(config.getAuthMode())
&& (config.getAccessKeySecret() == null || config.getAccessKeySecret().isBlank())) {
return false;
}
return true;
}
}
@@ -34,7 +34,6 @@ import org.apache.hertzbeat.common.entity.dto.sms.AwsSmsProperties;
import org.apache.hertzbeat.common.entity.dto.sms.SmslocalSmsProperties;
import org.apache.hertzbeat.common.entity.dto.sms.TencentSmsProperties;
import org.apache.hertzbeat.common.entity.dto.sms.TwilioSmsProperties;
import org.apache.hertzbeat.common.entity.dto.sms.UniSmsProperties;
import org.apache.hertzbeat.common.support.exception.SendMessageException;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.CloseableHttpResponse;
@@ -78,11 +77,6 @@ class SmsClientLoggingTest {
withSuccessfulResponse("{\"Code\":\"OK\"}",
() -> new AlibabaSmsClientImpl(alibabaProperties).sendMessage(receiver, null, alert));
UniSmsProperties uniProperties =
new UniSmsProperties(ACCESS_KEY, "unisms-secret", "sign", "template", "hmac");
withSuccessfulResponse("{\"code\":\"0\"}",
() -> new UniSmsClientImpl(uniProperties).sendMessage(receiver, null, alert));
withSuccessfulResponse("{\"sid\":\"message-id\"}",
() -> new TwilioSmsClientImpl(twilioProperties()).sendMessage(receiver, null, alert));
@@ -108,8 +102,6 @@ class SmsClientLoggingTest {
() -> new AwsSmsClientImpl(awsProperties()).sendMessage(receiver(), null, alert()));
SendMessageException alibabaFailure = withResponse(502, body,
() -> new AlibabaSmsClientImpl(alibabaProperties()).sendMessage(receiver(), null, alert()));
SendMessageException uniFailure = withResponse(429, body,
() -> new UniSmsClientImpl(uniProperties()).sendMessage(receiver(), null, alert()));
SendMessageException twilioFailure = withResponse(429, body,
() -> new TwilioSmsClientImpl(twilioProperties()).sendMessage(receiver(), null, alert()));
SendMessageException tencentFailure = withResponse(429, body,
@@ -119,14 +111,12 @@ class SmsClientLoggingTest {
assertEquals("AWS SMS request failed with HTTP status 503", awsFailure.getMessage());
assertEquals("Alibaba Cloud SMS request failed with HTTP status 502", alibabaFailure.getMessage());
assertEquals("UniSMS request failed with HTTP status 429", uniFailure.getMessage());
assertEquals("Twilio SMS request failed with HTTP status 429", twilioFailure.getMessage());
assertEquals("Tencent Cloud SMS request failed with HTTP status 429", tencentFailure.getMessage());
assertEquals("SMSLocal request failed with HTTP status 429", smslocalFailure.getMessage());
assertNoSensitiveSentinels(output.getAll()
+ awsFailure.getMessage()
+ alibabaFailure.getMessage()
+ uniFailure.getMessage()
+ twilioFailure.getMessage()
+ tencentFailure.getMessage()
+ smslocalFailure.getMessage());
@@ -138,10 +128,6 @@ class SmsClientLoggingTest {
200,
"{\"Code\":\"THROTTLED\",\"Message\":\"" + PROVIDER_BODY + "\"}",
() -> new AlibabaSmsClientImpl(alibabaProperties()).sendMessage(receiver(), null, alert()));
SendMessageException uniFailure = withResponse(
200,
"{\"code\":\"RATE_LIMITED\",\"message\":\"" + PROVIDER_BODY + "\"}",
() -> new UniSmsClientImpl(uniProperties()).sendMessage(receiver(), null, alert()));
SendMessageException awsFailure = withResponse(
200,
"{\"message\":\"" + PROVIDER_BODY + "\"}",
@@ -161,14 +147,12 @@ class SmsClientLoggingTest {
() -> new SmsLocalSmsClientImpl(smslocalProperties()).sendMessage(receiver(), null, alert()));
assertEquals("Alibaba Cloud SMS request failed (code: THROTTLED)", alibabaFailure.getMessage());
assertEquals("UniSMS request failed (code: RATE_LIMITED)", uniFailure.getMessage());
assertEquals("AWS SMS provider returned an invalid response", awsFailure.getMessage());
assertEquals("Twilio SMS request failed (code: 21608)", twilioFailure.getMessage());
assertEquals("Tencent Cloud SMS request failed (code: THROTTLED)", tencentFailure.getMessage());
assertEquals("SMSLocal request failed (code: RATE_LIMITED)", smslocalFailure.getMessage());
assertNoSensitiveSentinels(output.getAll()
+ alibabaFailure.getMessage()
+ uniFailure.getMessage()
+ awsFailure.getMessage()
+ twilioFailure.getMessage()
+ tencentFailure.getMessage()
@@ -181,8 +165,6 @@ class SmsClientLoggingTest {
() -> new AwsSmsClientImpl(awsProperties()).sendMessage(receiver(), null, alert()));
SendMessageException alibabaFailure = withNetworkFailure(
() -> new AlibabaSmsClientImpl(alibabaProperties()).sendMessage(receiver(), null, alert()));
SendMessageException uniFailure = withNetworkFailure(
() -> new UniSmsClientImpl(uniProperties()).sendMessage(receiver(), null, alert()));
SendMessageException twilioFailure = withNetworkFailure(
() -> new TwilioSmsClientImpl(twilioProperties()).sendMessage(receiver(), null, alert()));
SendMessageException tencentFailure = withNetworkFailure(
@@ -192,14 +174,12 @@ class SmsClientLoggingTest {
assertEquals("AWS SMS request failed", awsFailure.getMessage());
assertEquals("Alibaba Cloud SMS request failed", alibabaFailure.getMessage());
assertEquals("UniSMS request failed", uniFailure.getMessage());
assertEquals("Twilio SMS request failed", twilioFailure.getMessage());
assertEquals("Tencent Cloud SMS request failed", tencentFailure.getMessage());
assertEquals("SMSLocal request failed", smslocalFailure.getMessage());
assertNoSensitiveSentinels(output.getAll()
+ awsFailure.getMessage()
+ alibabaFailure.getMessage()
+ uniFailure.getMessage()
+ twilioFailure.getMessage()
+ tencentFailure.getMessage()
+ smslocalFailure.getMessage());
@@ -273,10 +253,6 @@ class SmsClientLoggingTest {
return new AlibabaSmsProperties(ACCESS_KEY, "alibaba-secret", "sign", "template");
}
private UniSmsProperties uniProperties() {
return new UniSmsProperties(ACCESS_KEY, "unisms-secret", "sign", "template", "hmac");
}
private TwilioSmsProperties twilioProperties() {
return new TwilioSmsProperties(ACCESS_KEY, "twilio-secret", "twilio-phone");
}
@@ -1,85 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.apache.hertzbeat.alert.service.impl;
import org.apache.hertzbeat.common.entity.dto.sms.UniSmsProperties;
import org.apache.hertzbeat.common.entity.alerter.GroupAlert;
import org.apache.hertzbeat.common.entity.alerter.NoticeReceiver;
import org.apache.hertzbeat.common.support.exception.SendMessageException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.HashMap;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.when;
/**
* Test case for {@link UniSmsClientImpl}
*/
@ExtendWith(MockitoExtension.class)
public class UniSmsClientImplTest {
@Mock
private UniSmsProperties uniSmsProperties;
private UniSmsClientImpl uniSmsClient;
@BeforeEach
void setUp() {
uniSmsClient = new UniSmsClientImpl(uniSmsProperties);
when(uniSmsProperties.getSignature()).thenReturn("2");
when(uniSmsProperties.getTemplateId()).thenReturn("any(String.class)");
when(uniSmsProperties.getAuthMode()).thenReturn("hmac");
when(uniSmsProperties.getAccessKeyId()).thenReturn("hmac");
when(uniSmsProperties.getAccessKeySecret()).thenReturn("hmac");
}
@Test
void testSendMessage() {
assertEquals("unisms", uniSmsClient.getType());
assertTrue(uniSmsClient.checkConfig());
//
NoticeReceiver noticeReceiver = new NoticeReceiver();
noticeReceiver.setPhone("13888888888");
Map<String, String> commonLabels = new HashMap<>();
commonLabels.put("instance", "");
commonLabels.put("priority", "unknown");
Map<String, String> commonAnnotations = new HashMap<>();
commonAnnotations.put("test", "test");
GroupAlert groupAlert = new GroupAlert();
groupAlert.setCommonLabels(commonLabels);
groupAlert.setCommonAnnotations(commonAnnotations);
assertThrows(SendMessageException.class,
() -> uniSmsClient.sendMessage(noticeReceiver, null, groupAlert));
}
}
@@ -27,9 +27,6 @@ public interface SmsConstants {
// Alibaba Cloud SMS
String ALIBABA = "alibaba";
// UniSMS
String UNISMS = "unisms";
// Smslocal SMS
String SMSLOCAL = "smslocal";
@@ -51,11 +51,6 @@ public class SmsConfig {
*/
private AlibabaSmsProperties alibaba;
/**
* UniSMS configuration
*/
private UniSmsProperties unisms;
/**
* Aws configuration
*/
@@ -1,60 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.apache.hertzbeat.common.entity.dto.sms;
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* UniSMS properties
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UniSmsProperties {
/**
* UniSMS access key id
*/
@NotBlank(message = "accessKeyId cannot be empty")
private String accessKeyId;
/**
* UniSMS access key secret, required for HMAC mode
*/
private String accessKeySecret;
/**
* SMS signature
*/
@NotBlank(message = "signature cannot be null")
private String signature;
/**
* SMS template ID
*/
@NotBlank(message = "templateId cannot be null")
private String templateId;
/**
* Authentication mode: simple or hmac, default is simple
*/
@NotBlank(message = "authMode cannot be null")
private String authMode = "simple";
}
@@ -161,14 +161,6 @@ alerter:
access-key-secret:
sign-name:
template-code:
unisms:
# auth-mode: simple or hmac
auth-mode: simple
access-key-id: YOUR_ACCESS_KEY_ID
# hmac mode need to fill in access-key-secret
access-key-secret: YOUR_ACCESS_KEY_SECRET
signature: YOUR_SMS_SIGNATURE
template-id: YOUR_TEMPLATE_ID
smslocal:
api-key: YOUR_API_KEY_HERE
aws:
@@ -315,14 +315,6 @@ alerter:
access-key-secret:
sign-name:
template-code:
unisms:
# auth-mode: simple or hmac
auth-mode: simple
access-key-id: YOUR_ACCESS_KEY_ID
# hmac mode need to fill in access-key-secret
access-key-secret: YOUR_ACCESS_KEY_SECRET
signature: YOUR_SMS_SIGNATURE
template-id: YOUR_TEMPLATE_ID
smslocal:
api-key: YOUR_API_KEY_HERE
aws:
+12 -68
View File
@@ -1,7 +1,7 @@
---
id: alert_sms
title: Alert SMS notification
sidebar_label: Alert SMS notification
id: alert_sms
title: Alert SMS notification
sidebar_label: Alert SMS notification
keywords: [open source monitoring tool, open source alerter, open source SMS alert notification]
---
@@ -9,11 +9,15 @@ keywords: [open source monitoring tool, open source alerter, open source SMS ale
## SMS Service Configuration
Only when you successfully configure your own SMS service will the alert SMS triggered within the monitoring system be sent correctly.
Only when you successfully configure your own SMS service will the alert SMS triggered within the monitoring system be sent correctly.
HertzBeat provides two ways to configure the SMS service: modifying the `application.yml` configuration file directly or configuring it through the HertzBeat frontend interface (Settings > Message Server Setting).
> ⚠️ Note: Only one method can be effective at a time. If both methods are configured and enabled, HertzBeat will prioritize the SMS service configured in the frontend interface.
:::caution
UniSMS officially shut down on 2026-09-15, so HertzBeat no longer supports it as an SMS provider. If your SMS service is configured with `type: unisms`, please switch to another provider below.
:::
### Tencent Cloud SMS Configuration
Add/Fill in the following Tencent Cloud SMS server configuration to `application.yml` (replace parameters with your own SMS server configuration):
@@ -31,7 +35,7 @@ alerter:
template-id: 1343434
```
1. Create a signature (sign-name) in Tencent Cloud SMS
1. Create a signature (sign-name) in Tencent Cloud SMS
![image](/img/docs/help/alert-sms-tencent-cloud-signature.png)
2. Create a message template (template-id) in Tencent Cloud SMS
@@ -42,10 +46,10 @@ alerter:
![image](/img/docs/help/alert-sms-tencent-cloud-template.png)
3. Create an application (app-id) in Tencent Cloud SMS
3. Create an application (app-id) in Tencent Cloud SMS
![image](/img/docs/help/alert-sms-tencent-cloud-app.png)
4. Obtain Tencent Cloud Access Management credentials (secret-id, secret-key)
4. Obtain Tencent Cloud Access Management credentials (secret-id, secret-key)
![image](/img/docs/help/alert-sms-tencent-cloud-access.png)
### Alibaba Cloud SMS Configuration
@@ -100,66 +104,6 @@ alerter:
Now you can configure this information in your hertzbeat application.
### UniSMS Configuration
UniSMS is an aggregated SMS service platform.
:::caution
UniSMS officially shut down on 2026-09-15, and its API and console are no longer available. Please switch to another SMS provider. The configuration below is kept for reference only.
:::
Add/Fill in the following UniSMS configuration to `application.yml` (replace parameters with your own SMS server configuration):
```yaml
alerter:
sms:
enable: true # Whether to enable
type: unisms # SMS provider type, set to unisms
unisms: # UniSMS configuration
# auth-mode: simple or hmac
auth-mode: simple
access-key-id: YOUR_ACCESS_KEY_ID
# hmac mode need to fill in access-key-secret
access-key-secret: YOUR_ACCESS_KEY_SECRET
signature: YOUR_SMS_SIGNATURE
template-id: YOUR_TEMPLATE_ID
```
1. Register UniSMS account
- Visit the UniSMS website
2. Create signature
- Log in to the UniSMS Console
- Go to "SMS Filing - Signature Management" page
- Click "Add Signature"
- Fill in signature information and submit for review
- Wait for signature approval
3. Create message template
- Go to "SMS Filing - Template Management" page
- Click "Add Template"
- Create a template with the following format:
```text
Monitor: {instance}, Alert Level: {priority}. Content: {content}
```
- Submit the template for review
4. Obtain `access-key-id` and `access-key-secret`
- Log in to the UniSMS Console
- Go to "Credential Management" page
- Get AccessKey ID and AccessKey Secret
- Securely save the AccessKey ID and AccessKey Secret
:::note
UniSMS provides two authentication methods for developers to choose from, which can be set in Console - Credential Management, with Simple Mode as default.
- Simple Mode [Default]: This mode only verifies AccessKey ID without request parameter signature, making it easier for developers to integrate quickly.
- HMAC Mode: This mode requires signing request parameters with AccessKey Secret to enhance the security and authenticity of requests.
:::
Now you can configure this information in your hertzbeat application.
### Smslocal SMS Configuration
SMSLocal is an all-in-one SMS service for businesses, with features like multi-way sending, strong security, and 24/7 support. You can refer to smslocal's [Developer Documentation](https://www.smslocal.com/developer/) for configuration.
@@ -202,7 +146,7 @@ alerter:
aws: # AWS Cloud SMS configuration
access-key-id: # Your AccessKey ID
access-key-secret: # Your AccessKey Secret
region: # Region Of Your AWS
region: # Region Of Your AWS
```
1. Create an AWS Cloud account
@@ -1,7 +1,7 @@
---
id: alert_sms
title: 告警短信通知
sidebar_label: 告警短信通知
id: alert_sms
title: 告警短信通知
sidebar_label: 告警短信通知
keywords: [开源监控系统, 开源告警系统, 开源短信告警通知]
---
@@ -13,6 +13,10 @@ keywords: [开源监控系统, 开源告警系统, 开源短信告警通知]
hertzbeat有两种方式配置短信服务,一种是直接修改`application.yml`配置文件,另一种是通过hertzbeat前端界面(系统设置 > 消息服务配置)配置。
> 注意⚠️:两种方式配置的短信服务只能选择一种生效,当两种方式都配置并且开启时,hertzbeat将会优先使用前端界面配置的短信服务。
:::caution
UniSMS 合一短信已于 2026-09-15 正式闭站,hertzbeat 已不再支持该短信服务商。如果您的短信服务配置为 `type: unisms`,请改用下方其他服务商。
:::
### 腾讯云短信配置
在`application.yml`新增/填写如下腾讯平台短信服务器配置(参数需替换为您的短信服务器配置)
@@ -99,64 +103,6 @@ alerter:
现在您可以把这些信息配置到您的hertzbeat应用中。
### uni-sms配置
uni-sms是一个聚合短信服务平台。
:::caution
UniSMS 合一短信已于 2026-09-15 正式闭站,API 与控制台均已无法使用。请改用其他短信服务商,以下配置仅作参考保留。
:::
在`application.yml`新增/填写如下uni-sms短信服务配置(参数需替换为您的短信服务器配置)
```yaml
alerter:
sms:
enable: true # 启用配置
type: unisms # 短信服务商类型,设置为unisms
unisms: # 填写uni-sms短信配置
# auth-mode: simple or hmac
auth-mode: simple
access-key-id: YOUR_ACCESS_KEY_ID
# hmac mode need to fill in access-key-secret
access-key-secret: YOUR_ACCESS_KEY_SECRET
signature: YOUR_SMS_SIGNATURE
template-id: YOUR_TEMPLATE_ID
```
1. 注册uni-sms账号
- 访问uni-sms官网
2. 创建短信签名(signature)
- 登录uni-sms控制台
- 进入"短信报备-签名管理"页面
- 点击"添加签名"
- 填写签名信息并提交审核
- 等待签名审核通过
3. 创建短信模板(template-id)
- 进入"短信报备-模板管理"页面
- 点击"添加模板"
- 创建如下格式的模板:
```text
监控项:{instance},告警级别:{priority}。内容:{content}
```
- 提交模板等待审核
4. 获取`access-key-id`和`access-key-secret`
- 登录uni-sms控制台
- 进入"凭证管理"页面
- 获取AccessKey ID和AccessKey Secret
- 安全保存AccessKey ID和AccessKey Secret
:::note
UniSMS 提供以下两种鉴权方式共开发者选择,可在控制台-凭证管理中设置,默认为简易模式。
- 简易模式 [默认]:此模式仅核验 AccessKey ID,不对请求参数进行验签,方便开发者快速接入。
- HMAC模式:此模式要求使用 AccessKey Secret 对请求参数进行验签,以加强保障请求的安全与真实性。
:::
### AWS Cloud SMS配置
要激活和使用 AWS Cloud SMS 服务,请参考官方 AWS 文档: [SMS Getting Started Guide](https://docs.aws.amazon.com/sms-voice/latest/userguide/what-is-sms-mms.html)
@@ -172,7 +118,7 @@ alerter:
aws: # AWS Cloud SMS configuration
access-key-id: # Your AccessKey ID
access-key-secret: # Your AccessKey Secret
region: # Region Of Your AWS
region: # Region Of Your AWS
```
1. 创建 AWS 账户
-8
View File
@@ -315,14 +315,6 @@ alerter:
access-key-secret:
sign-name:
template-code:
unisms:
# auth-mode: simple or hmac
auth-mode: simple
access-key-id: YOUR_ACCESS_KEY_ID
# hmac mode need to fill in access-key-secret
access-key-secret: YOUR_ACCESS_KEY_SECRET
signature: YOUR_SMS_SIGNATURE
template-id: YOUR_TEMPLATE_ID
smslocal:
api-key: YOUR_API_KEY_HERE
aws:
@@ -216,14 +216,6 @@ alerter:
access-key-secret:
sign-name:
template-code:
unisms:
# auth-mode: simple or hmac
auth-mode: simple
access-key-id: YOUR_ACCESS_KEY_ID
# hmac mode need to fill in access-key-secret
access-key-secret: YOUR_ACCESS_KEY_SECRET
signature: YOUR_SMS_SIGNATURE
template-id: YOUR_TEMPLATE_ID
smslocal:
api-key: YOUR_API_KEY_HERE
aws:
@@ -213,14 +213,6 @@ alerter:
access-key-secret:
sign-name:
template-code:
unisms:
# auth-mode: simple or hmac
auth-mode: simple
access-key-id: YOUR_ACCESS_KEY_ID
# hmac mode need to fill in access-key-secret
access-key-secret: YOUR_ACCESS_KEY_SECRET
signature: YOUR_SMS_SIGNATURE
template-id: YOUR_TEMPLATE_ID
smslocal:
api-key: YOUR_API_KEY_HERE
aws:
@@ -216,14 +216,6 @@ alerter:
access-key-secret:
sign-name:
template-code:
unisms:
# auth-mode: simple or hmac
auth-mode: simple
access-key-id: YOUR_ACCESS_KEY_ID
# hmac mode need to fill in access-key-secret
access-key-secret: YOUR_ACCESS_KEY_SECRET
signature: YOUR_SMS_SIGNATURE
template-id: YOUR_TEMPLATE_ID
smslocal:
api-key: YOUR_API_KEY_HERE
aws:
@@ -213,14 +213,6 @@ alerter:
access-key-secret:
sign-name:
template-code:
unisms:
# auth-mode: simple or hmac
auth-mode: simple
access-key-id: YOUR_ACCESS_KEY_ID
# hmac mode need to fill in access-key-secret
access-key-secret: YOUR_ACCESS_KEY_SECRET
signature: YOUR_SMS_SIGNATURE
template-id: YOUR_TEMPLATE_ID
smslocal:
api-key: YOUR_API_KEY_HERE
aws:
@@ -215,14 +215,6 @@ alerter:
access-key-secret:
sign-name:
template-code:
unisms:
# auth-mode: simple or hmac
auth-mode: simple
access-key-id: YOUR_ACCESS_KEY_ID
# hmac mode need to fill in access-key-secret
access-key-secret: YOUR_ACCESS_KEY_SECRET
signature: YOUR_SMS_SIGNATURE
template-id: YOUR_TEMPLATE_ID
smslocal:
api-key: YOUR_API_KEY_HERE
aws:
-2
View File
@@ -22,7 +22,6 @@ import { AwsSmsConfig } from './AwsSmsConfig';
import { SmslocalSmsConfig } from './SmslocalSmsConfig';
import { TencentSmsConfig } from './TencentSmsConfig';
import { TwilioSmsConfig } from './TwilioSmsConfig';
import { UniSmsConfig } from './UniSmsConfig';
import { SmsType } from './enums/sms-type.enum';
export class SmsNoticeSender {
@@ -30,7 +29,6 @@ export class SmsNoticeSender {
type: SmsType = SmsType.TENCENT;
tencent: TencentSmsConfig = new TencentSmsConfig();
alibaba: AlibabaSmsConfig = new AlibabaSmsConfig();
unisms: UniSmsConfig = new UniSmsConfig();
smslocal: SmslocalSmsConfig = new SmslocalSmsConfig();
aws: AwsSmsConfig = new AwsSmsConfig();
twilio: TwilioSmsConfig = new TwilioSmsConfig();
-26
View File
@@ -1,26 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.
*/
export class UniSmsConfig {
accessKeyId!: string;
accessKeySecret!: string;
signature!: string;
authMode!: string;
templateId!: string;
}
@@ -20,13 +20,7 @@
export enum SmsType {
TENCENT = 'tencent',
ALIBABA = 'alibaba',
UNISMS = 'unisms',
SMSLOCAL = 'smslocal',
AWS = 'aws',
TWILIO = 'twilio'
}
export enum UniSmsAuthMode {
HMAC = 'hmac',
SIMPLE = 'simple'
}
@@ -64,14 +64,6 @@
{{ 'alert.notice.sender.sms.alibaba.templateCode' | i18n }}: {{ smsNoticeSender.alibaba.templateCode }}
</ng-container>
<!-- UniSMS -->
<ng-container *ngSwitchCase="SmsType.UNISMS">
{{ 'alert.notice.sender.sms.unisms.signature' | i18n }}: {{ smsNoticeSender.unisms.signature }}
<br />
{{ 'alert.notice.sender.sms.unisms.templateId' | i18n }}: {{ smsNoticeSender.unisms.templateId }}
<br />
{{ 'alert.notice.sender.sms.unisms.authMode' | i18n }}: {{ smsNoticeSender.unisms.authMode }}
</ng-container>
<ng-container *ngSwitchCase="SmsType.TWILIO">
{{ 'alert.notice.sender.sms.twilio.accountSid' | i18n }}: {{ smsNoticeSender.twilio.accountSid }}
<br />
@@ -170,7 +162,6 @@
<nz-select [(ngModel)]="smsType" name="type" id="type" (ngModelChange)="onSmsTypeChange($event)">
<nz-option [nzValue]="SmsType.TENCENT" nzLabel="{{ 'alert.notice.sender.sms.type.tencent' | i18n }}"></nz-option>
<nz-option [nzValue]="SmsType.ALIBABA" nzLabel="{{ 'alert.notice.sender.sms.type.alibaba' | i18n }}"></nz-option>
<nz-option [nzValue]="SmsType.UNISMS" nzLabel="{{ 'alert.notice.sender.sms.type.unisms' | i18n }}"></nz-option>
<nz-option [nzValue]="SmsType.SMSLOCAL" nzLabel="{{ 'alert.notice.sender.sms.type.smslocal' | i18n }}"></nz-option>
<nz-option [nzValue]="SmsType.AWS" nzLabel="{{ 'alert.notice.sender.sms.type.aws' | i18n }}"></nz-option>
<nz-option [nzValue]="SmsType.TWILIO" nzLabel="{{ 'alert.notice.sender.sms.type.twilio' | i18n }}"></nz-option>
@@ -277,69 +268,6 @@
</nz-form-item>
</ng-container>
<!-- UniSMS -->
<ng-container *ngIf="smsType === SmsType.UNISMS">
<nz-form-item>
<nz-form-label [nzSpan]="7" nzFor="accessKeyId" nzRequired="true">
{{ 'alert.notice.sender.sms.unisms.accessKeyId' | i18n }}
</nz-form-label>
<nz-form-control [nzSpan]="12" [nzErrorTip]="'validation.required' | i18n">
<input
[(ngModel)]="smsNoticeSender.unisms.accessKeyId"
nz-input
required
name="accessKeyId"
type="password"
id="unismsAccessKeyId"
/>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzSpan="7" nzFor="authMode" nzRequired="true">
{{ 'alert.notice.sender.sms.unisms.authMode' | i18n }}
</nz-form-label>
<nz-form-control nzSpan="12">
<nz-select [(ngModel)]="smsNoticeSender.unisms.authMode" name="authMode" id="unismsAuthMode" required>
<nz-option [nzValue]="uniSmsAuthModes.HMAC" nzLabel="HMAC"></nz-option>
<nz-option [nzValue]="uniSmsAuthModes.SIMPLE" nzLabel="Simple"></nz-option>
</nz-select>
</nz-form-control>
</nz-form-item>
<!-- accessKeySecret 根据 authMode 动态显示 -->
<nz-form-item *ngIf="isAccessKeySecretRequired()">
<nz-form-label [nzSpan]="7" nzFor="accessKeySecret" nzRequired="true">
{{ 'alert.notice.sender.sms.unisms.accessKeySecret' | i18n }}
</nz-form-label>
<nz-form-control [nzSpan]="12" [nzErrorTip]="'validation.required' | i18n">
<input
[(ngModel)]="smsNoticeSender.unisms.accessKeySecret"
nz-input
required
name="accessKeySecret"
type="password"
id="unismsAccessKeySecret"
/>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="7" nzFor="signature" nzRequired="true">
{{ 'alert.notice.sender.sms.unisms.signature' | i18n }}
</nz-form-label>
<nz-form-control [nzSpan]="12" [nzErrorTip]="'validation.required' | i18n">
<input [(ngModel)]="smsNoticeSender.unisms.signature" nz-input required name="signature" type="text" id="unismsSignature" />
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzSpan]="7" nzFor="templateId" nzRequired="true">
{{ 'alert.notice.sender.sms.unisms.templateId' | i18n }}
</nz-form-label>
<nz-form-control [nzSpan]="12" [nzErrorTip]="'validation.required' | i18n">
<input [(ngModel)]="smsNoticeSender.unisms.templateId" nz-input required name="templateId" type="text" id="unismsTemplateId" />
</nz-form-control>
</nz-form-item>
</ng-container>
<!-- Smslocal SMS -->
<ng-container *ngIf="smsType === SmsType.SMSLOCAL">
<nz-form-item>
@@ -27,8 +27,7 @@ import { finalize } from 'rxjs/operators';
import { AlibabaSmsConfig } from 'src/app/pojo/AlibabaSmsConfig';
import { SmsNoticeSender } from 'src/app/pojo/SmsNoticeSender';
import { TencentSmsConfig } from 'src/app/pojo/TencentSmsConfig';
import { UniSmsConfig } from 'src/app/pojo/UniSmsConfig';
import { SmsType, UniSmsAuthMode } from 'src/app/pojo/enums/sms-type.enum';
import { SmsType } from 'src/app/pojo/enums/sms-type.enum';
import { AwsSmsConfig } from '../../../../pojo/AwsSmsConfig';
import { EmailNoticeSender } from '../../../../pojo/EmailNoticeSender';
@@ -57,7 +56,6 @@ export class MessageServerComponent implements OnInit {
smsType: SmsType = SmsType.TENCENT;
emailSender = new EmailNoticeSender();
smsNoticeSender = new SmsNoticeSender();
uniSmsAuthModes = UniSmsAuthMode;
SmsType = SmsType;
private tempSmsType: SmsType = SmsType.TENCENT;
private tempSmsNoticeSender = new SmsNoticeSender();
@@ -144,7 +142,6 @@ export class MessageServerComponent implements OnInit {
this.smsNoticeSender = { ...newSender, ...message.data };
this.smsNoticeSender.tencent = { ...new TencentSmsConfig(), ...message.data.tencent };
this.smsNoticeSender.alibaba = { ...new AlibabaSmsConfig(), ...message.data.alibaba };
this.smsNoticeSender.unisms = { ...new UniSmsConfig(), ...message.data.unisms };
this.smsNoticeSender.smslocal = { ...new SmslocalSmsConfig(), ...message.data.smslocal };
this.smsNoticeSender.aws = { ...new AwsSmsConfig(), ...message.data.aws };
this.smsNoticeSender.twilio = { ...new TwilioSmsConfig(), ...message.data.twilio };
@@ -171,7 +168,6 @@ export class MessageServerComponent implements OnInit {
...this.smsNoticeSender,
tencent: { ...this.smsNoticeSender.tencent },
alibaba: { ...this.smsNoticeSender.alibaba },
unisms: { ...this.smsNoticeSender.unisms },
smslocal: { ...this.smsNoticeSender.smslocal },
aws: { ...this.smsNoticeSender.aws },
twilio: { ...this.smsNoticeSender.twilio }
@@ -185,7 +181,6 @@ export class MessageServerComponent implements OnInit {
...this.tempSmsNoticeSender,
tencent: { ...this.tempSmsNoticeSender.tencent },
alibaba: { ...this.tempSmsNoticeSender.alibaba },
unisms: { ...this.tempSmsNoticeSender.unisms },
smslocal: { ...this.tempSmsNoticeSender.smslocal },
aws: { ...this.tempSmsNoticeSender.aws },
twilio: { ...this.tempSmsNoticeSender.twilio }
@@ -198,10 +193,6 @@ export class MessageServerComponent implements OnInit {
this.smsNoticeSender.type = value;
}
isAccessKeySecretRequired(): boolean {
return this.smsNoticeSender.unisms.authMode === UniSmsAuthMode.HMAC;
}
onSaveSmsServer() {
if (this.senderForm?.invalid) {
Object.values(this.senderForm.controls).forEach(control => {
-6
View File
@@ -158,11 +158,6 @@
"alert.notice.sender.sms.alibaba.accessKeySecret": "Alibaba SMS AccessKeySecret",
"alert.notice.sender.sms.alibaba.signName": "Alibaba SMS Sign Name",
"alert.notice.sender.sms.alibaba.templateCode": "Alibaba SMS Template Code",
"alert.notice.sender.sms.unisms.accessKeyId": "UniSMS AccessKeyId",
"alert.notice.sender.sms.unisms.accessKeySecret": "UniSMS AccessKeySecret",
"alert.notice.sender.sms.unisms.signature": "UniSMS Signature",
"alert.notice.sender.sms.unisms.templateId": "UniSMS TemplateId",
"alert.notice.sender.sms.unisms.authMode": "UniSMS Authentication Mode",
"alert.notice.sender.sms.smslocal.apiKey": "Smslocal ApiKey",
"alert.notice.sender.sms.aws.accessKeyId": "Aws SMS AccessKeyId",
"alert.notice.sender.sms.aws.accessKeySecret": "Aws SMS AccessKeySecret",
@@ -173,7 +168,6 @@
"alert.notice.sender.sms.type": "Sms Type",
"alert.notice.sender.sms.type.alibaba": "Alibaba Sms",
"alert.notice.sender.sms.type.tencent": "Tencent Sms",
"alert.notice.sender.sms.type.unisms": "UniSMS",
"alert.notice.sender.sms.type.smslocal": "Smslocal Sms",
"alert.notice.sender.sms.type.aws": "Aws Sms",
"alert.notice.sender.sms.type.twilio": "Twilio Sms",
-6
View File
@@ -157,11 +157,6 @@
"alert.notice.sender.sms.alibaba.accessKeySecret": "Alibaba SMS AccessKeySecret",
"alert.notice.sender.sms.alibaba.signName": "Alibaba SMS SignName",
"alert.notice.sender.sms.alibaba.templateCode": "Alibaba SMS TemplateCode",
"alert.notice.sender.sms.unisms.accessKeyId": "UniSMS AccessKeyId",
"alert.notice.sender.sms.unisms.accessKeySecret": "UniSMS AccessKeySecret",
"alert.notice.sender.sms.unisms.signature": "UniSMS Signature",
"alert.notice.sender.sms.unisms.templateId": "UniSMS TemplateId",
"alert.notice.sender.sms.unisms.authMode": "UniSMS認証モード",
"alert.notice.sender.sms.smslocal.apiKey": "Smslocal ApiKey",
"alert.notice.sender.sms.aws.accessKeyId": "Aws SMS AccessKeyId",
"alert.notice.sender.sms.aws.accessKeySecret": "Aws SMS AccessKeySecret",
@@ -172,7 +167,6 @@
"alert.notice.sender.sms.type": "SMSタイプ",
"alert.notice.sender.sms.type.alibaba": "Alibaba Sms",
"alert.notice.sender.sms.type.tencent": "Tencent Sms",
"alert.notice.sender.sms.type.unisms": "UniSMS",
"alert.notice.sender.sms.type.smslocal": "Smslocal Sms",
"alert.notice.sender.sms.type.aws": "Aws Sms",
"alert.notice.sender.sms.type.twilio": "Twilio Sms",
-6
View File
@@ -158,11 +158,6 @@
"alert.notice.sender.sms.alibaba.accessKeySecret": "Alibaba SMS AccessKeySecret",
"alert.notice.sender.sms.alibaba.signName": "Alibaba SMS Sign Name",
"alert.notice.sender.sms.alibaba.templateCode": "Alibaba SMS Template Code",
"alert.notice.sender.sms.unisms.accessKeyId": "UniSMS AccessKeyId",
"alert.notice.sender.sms.unisms.accessKeySecret": "UniSMS AccessKeySecret",
"alert.notice.sender.sms.unisms.signature": "UniSMS Signature",
"alert.notice.sender.sms.unisms.templateId": "UniSMS TemplateId",
"alert.notice.sender.sms.unisms.authMode": "UniSMS 인증 방식",
"alert.notice.sender.sms.smslocal.apiKey": "Smslocal ApiKey",
"alert.notice.sender.sms.aws.accessKeyId": "AWS SMS AccessKeyId",
"alert.notice.sender.sms.aws.accessKeySecret": "AWS SMS AccessKeySecret",
@@ -173,7 +168,6 @@
"alert.notice.sender.sms.type": "SMS 유형",
"alert.notice.sender.sms.type.alibaba": "Alibaba SMS",
"alert.notice.sender.sms.type.tencent": "Tencent SMS",
"alert.notice.sender.sms.type.unisms": "UniSMS",
"alert.notice.sender.sms.type.smslocal": "Smslocal SMS",
"alert.notice.sender.sms.type.aws": "AWS SMS",
"alert.notice.sender.sms.type.twilio": "Twilio SMS",
-6
View File
@@ -1278,11 +1278,6 @@
"alert.notice.sender.sms.alibaba.accessKeySecret": "Alibaba SMS AccessKeySecret",
"alert.notice.sender.sms.alibaba.signName": "Nome da Assinatura Alibaba SMS",
"alert.notice.sender.sms.alibaba.templateCode": "Código do Template Alibaba SMS",
"alert.notice.sender.sms.unisms.accessKeyId": "UniSMS AccessKeyId",
"alert.notice.sender.sms.unisms.accessKeySecret": "UniSMS AccessKeySecret",
"alert.notice.sender.sms.unisms.signature": "Assinatura UniSMS",
"alert.notice.sender.sms.unisms.templateId": "UniSMS TemplateId",
"alert.notice.sender.sms.unisms.authMode": "Modo de Autenticação UniSMS",
"alert.notice.sender.sms.smslocal.apiKey": "Smslocal ApiKey",
"alert.notice.sender.sms.aws.accessKeyId": "Aws SMS AccessKeyId",
"alert.notice.sender.sms.aws.accessKeySecret": "Aws SMS AccessKeySecret",
@@ -1290,7 +1285,6 @@
"alert.notice.sender.sms.twilio.accountSid": "Twilio Account SID",
"alert.notice.sender.sms.twilio.authToken": "Twilio Auth Token",
"alert.notice.sender.sms.twilio.twilioPhoneNumber": "Número de Telefone Twilio",
"alert.notice.sender.sms.type.unisms": "UniSMS",
"alert.notice.sender.sms.type.smslocal": "Smslocal Sms",
"alert.notice.sender.sms.type.aws": "Aws Sms",
"alert.notice.sender.sms.type.twilio": "Twilio Sms",
-6
View File
@@ -158,11 +158,6 @@
"alert.notice.sender.sms.alibaba.accessKeySecret": "阿里短信AccessKeySecret",
"alert.notice.sender.sms.alibaba.signName": "阿里短信SignName",
"alert.notice.sender.sms.alibaba.templateCode": "阿里短信TemplateCode",
"alert.notice.sender.sms.unisms.accessKeyId": "合一短信AccessKeyId",
"alert.notice.sender.sms.unisms.accessKeySecret": "合一短信AccessKeySecret",
"alert.notice.sender.sms.unisms.signature": "合一短信Signature",
"alert.notice.sender.sms.unisms.templateId": "合一短信TemplateId",
"alert.notice.sender.sms.unisms.authMode": "合一短信鉴权方式",
"alert.notice.sender.sms.smslocal.apiKey": "Smslocal短信鉴权方式",
"alert.notice.sender.sms.aws.accessKeyId": "Aws SMS AccessKeyId",
"alert.notice.sender.sms.aws.accessKeySecret": "Aws SMS AccessKeySecret",
@@ -173,7 +168,6 @@
"alert.notice.sender.sms.type": "短信类型",
"alert.notice.sender.sms.type.alibaba": "阿里短信",
"alert.notice.sender.sms.type.tencent": "腾讯短信",
"alert.notice.sender.sms.type.unisms": "合一短信(UniSMS)",
"alert.notice.sender.sms.type.smslocal": "当地短信(Smslocal)",
"alert.notice.sender.sms.type.aws": "Aws Sms",
"alert.notice.sender.sms.type.twilio": "Twilio Sms",
-6
View File
@@ -157,11 +157,6 @@
"alert.notice.sender.sms.alibaba.accessKeySecret": "阿里短訊AccessKeySecret",
"alert.notice.sender.sms.alibaba.signName": "阿里短訊SignName",
"alert.notice.sender.sms.alibaba.templateCode": "阿里短訊TemplateCode",
"alert.notice.sender.sms.unisms.accessKeyId": "合一簡訊AccessKeyId",
"alert.notice.sender.sms.unisms.accessKeySecret": "合一簡訊AccessKeySecret",
"alert.notice.sender.sms.unisms.signature": "合一簡訊Signature",
"alert.notice.sender.sms.unisms.templateId": "合一簡訊TemplateId",
"alert.notice.sender.sms.unisms.authMode": "合一簡訊驗證方式",
"alert.notice.sender.sms.smslocal.apiKey": "Smslocal短訊ApiKey",
"alert.notice.sender.sms.aws.accessKeyId": "Aws SMS AccessKeyId",
"alert.notice.sender.sms.aws.accessKeySecret": "Aws SMS AccessKeySecret",
@@ -172,7 +167,6 @@
"alert.notice.sender.sms.type": "騰訊類型",
"alert.notice.sender.sms.type.alibaba": "阿裏短訊",
"alert.notice.sender.sms.type.tencent": "騰訊短訊",
"alert.notice.sender.sms.type.unisms": "合一簡訊(UniSMS)",
"alert.notice.sender.sms.type.smslocal": "当地短訊(Smslocal)",
"alert.notice.sender.sms.type.aws": "Aws Sms",
"alert.notice.template": "通知模板",