diff --git a/application/src/main/java/org/thingsboard/server/service/sms/AbstractSmsSender.java b/application/src/main/java/org/thingsboard/server/service/sms/AbstractSmsSender.java index 1a7619aec8..d62965d117 100644 --- a/application/src/main/java/org/thingsboard/server/service/sms/AbstractSmsSender.java +++ b/application/src/main/java/org/thingsboard/server/service/sms/AbstractSmsSender.java @@ -25,6 +25,7 @@ import java.util.regex.Pattern; public abstract class AbstractSmsSender implements SmsSender { private static final Pattern E_164_PHONE_NUMBER_PATTERN = Pattern.compile("^\\+[1-9]\\d{1,14}$"); + private static final Pattern PHONE_NUMBERS_SID_MESSAGE_SERVICE_SID = Pattern.compile("^(PN|MG).*$"); private static final int MAX_SMS_MESSAGE_LENGTH = 1600; private static final int MAX_SMS_SEGMENT_LENGTH = 70; @@ -37,6 +38,14 @@ public abstract class AbstractSmsSender implements SmsSender { return phoneNumber; } + protected String validatePhoneTwilioNumber(String phoneNumber) throws SmsParseException { + phoneNumber = phoneNumber.trim(); + if (!E_164_PHONE_NUMBER_PATTERN.matcher(phoneNumber).matches() && !PHONE_NUMBERS_SID_MESSAGE_SERVICE_SID.matcher(phoneNumber).matches()) { + throw new SmsParseException("Invalid phone number format. Phone number must be in E.164 format/Phone Number's SID/Messaging Service SID."); + } + return phoneNumber; + } + protected String prepareMessage(String message) { message = message.replaceAll("^\"|\"$", "").replaceAll("\\\\n", "\n"); if (message.length() > MAX_SMS_MESSAGE_LENGTH) { diff --git a/application/src/main/java/org/thingsboard/server/service/sms/twilio/TwilioSmsSender.java b/application/src/main/java/org/thingsboard/server/service/sms/twilio/TwilioSmsSender.java index 27c441410c..c4bba6ab26 100644 --- a/application/src/main/java/org/thingsboard/server/service/sms/twilio/TwilioSmsSender.java +++ b/application/src/main/java/org/thingsboard/server/service/sms/twilio/TwilioSmsSender.java @@ -33,7 +33,7 @@ public class TwilioSmsSender extends AbstractSmsSender { if (StringUtils.isEmpty(config.getAccountSid()) || StringUtils.isEmpty(config.getAccountToken()) || StringUtils.isEmpty(config.getNumberFrom())) { throw new IllegalArgumentException("Invalid twilio sms provider configuration: accountSid, accountToken and numberFrom should be specified!"); } - this.numberFrom = this.validatePhoneNumber(config.getNumberFrom()); + this.numberFrom = this.validatePhoneTwilioNumber(config.getNumberFrom()); this.twilioRestClient = new TwilioRestClient.Builder(config.getAccountSid(), config.getAccountToken()).build(); } diff --git a/ui-ngx/src/app/modules/home/components/sms/twilio-sms-provider-configuration.component.html b/ui-ngx/src/app/modules/home/components/sms/twilio-sms-provider-configuration.component.html index b6308223ac..3af73e8932 100644 --- a/ui-ngx/src/app/modules/home/components/sms/twilio-sms-provider-configuration.component.html +++ b/ui-ngx/src/app/modules/home/components/sms/twilio-sms-provider-configuration.component.html @@ -18,14 +18,14 @@
admin.number-from - + {{ 'admin.number-from-required' | translate }} - {{ 'admin.phone-number-pattern' | translate }} + {{ 'admin.phone-number-pattern-twilio' | translate }} - + admin.twilio-account-sid @@ -36,7 +36,7 @@ admin.twilio-account-token - + {{ 'admin.twilio-account-token-required' | translate }} diff --git a/ui-ngx/src/app/modules/home/components/sms/twilio-sms-provider-configuration.component.ts b/ui-ngx/src/app/modules/home/components/sms/twilio-sms-provider-configuration.component.ts index 759b9448ee..f4c31cd442 100644 --- a/ui-ngx/src/app/modules/home/components/sms/twilio-sms-provider-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/sms/twilio-sms-provider-configuration.component.ts @@ -21,8 +21,9 @@ import { AppState } from '@app/core/core.state'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { isDefinedAndNotNull } from '@core/utils'; import { - phoneNumberPattern, - SmsProviderConfiguration, SmsProviderType, + phoneNumberPatternTwilio, + SmsProviderConfiguration, + SmsProviderType, TwilioSmsProviderConfiguration } from '@shared/models/settings.models'; @@ -40,7 +41,7 @@ export class TwilioSmsProviderConfigurationComponent implements ControlValueAcce twilioSmsProviderConfigurationFormGroup: FormGroup; - phoneNumberPattern = phoneNumberPattern; + phoneNumberPatternTwilio = phoneNumberPatternTwilio; private requiredValue: boolean; @@ -71,9 +72,9 @@ export class TwilioSmsProviderConfigurationComponent implements ControlValueAcce ngOnInit() { this.twilioSmsProviderConfigurationFormGroup = this.fb.group({ - numberFrom: [null, [Validators.required, Validators.pattern(phoneNumberPattern)]], - accountSid: [null, [Validators.required]], - accountToken: [null, [Validators.required]] + numberFrom: [null, [Validators.required, Validators.pattern(phoneNumberPatternTwilio)]], + accountSid: [null, Validators.required], + accountToken: [null, Validators.required] }); this.twilioSmsProviderConfigurationFormGroup.valueChanges.subscribe(() => { this.updateModel(); diff --git a/ui-ngx/src/app/shared/models/settings.models.ts b/ui-ngx/src/app/shared/models/settings.models.ts index b4a428daf8..3877488671 100644 --- a/ui-ngx/src/app/shared/models/settings.models.ts +++ b/ui-ngx/src/app/shared/models/settings.models.ts @@ -65,6 +65,7 @@ export interface UpdateMessage { } export const phoneNumberPattern = /^\+[1-9]\d{1,14}$/; +export const phoneNumberPatternTwilio = /^\+[1-9]\d{1,14}$|^(MG|PN).*$/; export enum SmsProviderType { AWS_SNS = 'AWS_SNS', diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index dff58d17d0..223a0f026a 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -122,7 +122,9 @@ "number-to": "Phone Number To", "number-to-required": "Phone Number To is required.", "phone-number-hint": "Phone Number in E.164 format, ex. +19995550123", + "phone-number-hint-twilio": "Phone Number in E.164 format/Phone Number's SID/Messaging Service SID, ex. +19995550123/PNXXX/MGXXX", "phone-number-pattern": "Invalid phone number. Should be in E.164 format, ex. +19995550123.", + "phone-number-pattern-twilio": "Invalid phone number. Should be in E.164 format/Phone Number's SID/Messaging Service SID, ex. +19995550123/PNXXX/MGXXX.", "sms-message": "SMS message", "sms-message-required": "SMS message is required.", "sms-message-max-length": "SMS message can't be longer 1600 characters",