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..84aa972e8a 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 @@ -24,7 +24,7 @@ import java.util.regex.Pattern; @Slf4j public abstract class AbstractSmsSender implements SmsSender { - private static final Pattern E_164_PHONE_NUMBER_PATTERN = Pattern.compile("^\\+[1-9]\\d{1,14}$"); + protected static final Pattern E_164_PHONE_NUMBER_PATTERN = Pattern.compile("^\\+[1-9]\\d{1,14}$"); private static final int MAX_SMS_MESSAGE_LENGTH = 1600; private static final int MAX_SMS_SEGMENT_LENGTH = 70; 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..1988013fb0 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 @@ -19,21 +19,34 @@ import com.twilio.http.TwilioRestClient; import com.twilio.rest.api.v2010.account.Message; import com.twilio.type.PhoneNumber; import org.apache.commons.lang3.StringUtils; +import org.thingsboard.rule.engine.api.sms.exception.SmsParseException; import org.thingsboard.server.common.data.sms.config.TwilioSmsProviderConfiguration; import org.thingsboard.rule.engine.api.sms.exception.SmsException; import org.thingsboard.rule.engine.api.sms.exception.SmsSendException; import org.thingsboard.server.service.sms.AbstractSmsSender; +import java.util.regex.Pattern; + public class TwilioSmsSender extends AbstractSmsSender { + private static final Pattern PHONE_NUMBERS_SID_MESSAGE_SERVICE_SID = Pattern.compile("^(PN|MG).*$"); + private TwilioRestClient twilioRestClient; private String numberFrom; + private 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; + } + public TwilioSmsSender(TwilioSmsProviderConfiguration config) { 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 7b62f680a8..7c0b26028e 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",