diff --git a/CHANGES b/CHANGES
index bf7bc75de92bcaf6978b8089bfb2b544f327f402..38228e37a23406b2d70be99dabe9d693a40532f8 100644
--- a/CHANGES
+++ b/CHANGES
@@ -79,6 +79,17 @@ res_pjsip
    configure these options then you already had to do a reload after making
    changes.
 
+ * Added "ignore_uri_user_options" global configuration option for
+   compatibility with an ITSP that sends URI user field options.  When enabled
+   the user field is truncated at the first semicolon.
+   Example:
+   URI: "sip:1235557890;phone-context=national@x.x.x.x;user=phone"
+   The user field is "1235557890;phone-context=national"
+   Which is truncated to this: "1235557890"
+
+   Note: The caller-id and redirecting number strings obtained from incoming
+   SIP URI user fields are now always truncated at the first semicolon.
+
 app_confbridge
 ------------------
   * Some sounds played into the bridge are played asynchronously. This, for
diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample
index e6b32495ba36f5864c41de7d143f24acec8f4725..c6293b6fbcaaa5dd8a30e46587d9b1be243978f9 100644
--- a/configs/samples/pjsip.conf.sample
+++ b/configs/samples/pjsip.conf.sample
@@ -991,6 +991,22 @@
                     ; If disabled then unsolicited mwi will start processing
                     ; on the endpoint's next contact update.
 
+;ignore_uri_user_options=no ; Enable/Disable ignoring SIP URI user field options.
+                    ; If you have this option enabled and there are semicolons
+                    ; in the user field of a SIP URI then the field is truncated
+                    ; at the first semicolon.  This effectively makes the semicolon
+                    ; a non-usable character for PJSIP endpoint names, extensions,
+                    ; and AORs.  This can be useful for improving compatability with
+                    ; an ITSP that likes to use user options for whatever reason.
+                    ; Example:
+                    ; URI: "sip:1235557890;phone-context=national@x.x.x.x;user=phone"
+                    ; The user field is "1235557890;phone-context=national"
+                    ; Which becomes this: "1235557890"
+                    ;
+                    ; Note: The caller-id and redirecting number strings obtained
+                    ; from incoming SIP URI user fields are always truncated at the
+                    ; first semicolon.
+
 ; MODULE PROVIDING BELOW SECTION(S): res_pjsip_acl
 ;==========================ACL SECTION OPTIONS=========================
 ;[acl]
diff --git a/contrib/ast-db-manage/config/versions/a6ef36f1309_ps_globals_add_ignore_uri_user_options.py b/contrib/ast-db-manage/config/versions/a6ef36f1309_ps_globals_add_ignore_uri_user_options.py
new file mode 100644
index 0000000000000000000000000000000000000000..1556521d55279674429bd50d47f0fdbc42c64ff2
--- /dev/null
+++ b/contrib/ast-db-manage/config/versions/a6ef36f1309_ps_globals_add_ignore_uri_user_options.py
@@ -0,0 +1,32 @@
+"""ps_globals add ignore_uri_user_options
+
+Revision ID: a6ef36f1309
+Revises: 7f3e21abe318
+Create Date: 2016-08-31 12:24:22.368956
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = 'a6ef36f1309'
+down_revision = '7f3e21abe318'
+
+from alembic import op
+import sqlalchemy as sa
+from sqlalchemy.dialects.postgresql import ENUM
+
+YESNO_NAME = 'yesno_values'
+YESNO_VALUES = ['yes', 'no']
+
+def upgrade():
+    ############################# Enums ##############################
+
+    # yesno_values have already been created, so use postgres enum object
+    # type to get around "already created" issue - works okay with mysql
+    yesno_values = ENUM(*YESNO_VALUES, name=YESNO_NAME, create_type=False)
+
+    op.add_column('ps_globals', sa.Column('ignore_uri_user_options', yesno_values))
+
+
+def downgrade():
+    op.drop_column('ps_globals', 'ignore_uri_user_options')
+
diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index 8a5ad29c59810d9f745320c0199d394ffdce59b8..92bdabb662f772ee4b71482600fba9de3a664cef 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -2446,6 +2446,38 @@ int ast_sip_get_mwi_tps_queue_low(void);
  */
 unsigned int ast_sip_get_mwi_disable_initial_unsolicited(void);
 
+/*!
+ * \brief Retrieve the global setting 'ignore_uri_user_options'.
+ * \since 13.12.0
+ *
+ * \retval non zero if ignore the user field options.
+ */
+unsigned int ast_sip_get_ignore_uri_user_options(void);
+
+/*!
+ * \brief Truncate the URI user field options string if enabled.
+ * \since 13.12.0
+ *
+ * \param str URI user field string to truncate if enabled
+ *
+ * \details
+ * We need to be able to handle URI's looking like
+ * "sip:1235557890;phone-context=national@x.x.x.x;user=phone"
+ *
+ * Where the URI user field is:
+ * "1235557890;phone-context=national"
+ *
+ * When truncated the string will become:
+ * "1235557890"
+ */
+#define AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(str)				\
+	do {														\
+		char *__semi = strchr((str), ';');						\
+		if (__semi && ast_sip_get_ignore_uri_user_options()) {	\
+			*__semi = '\0';										\
+		}														\
+	} while (0)
+
 /*!
  * \brief Retrieve the system debug setting (yes|no|host).
  *
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index 7bb10c07f01b59035ebceca2653d6283f1f2181a..d1ebf64e433fb64fd5b5e5cac840708863492c36 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -1550,6 +1550,30 @@
 						</para>
 					</description>
 				</configOption>
+				<configOption name="ignore_uri_user_options">
+					<synopsis>Enable/Disable ignoring SIP URI user field options.</synopsis>
+					<description>
+						<para>If you have this option enabled and there are semicolons
+						in the user field of a SIP URI then the field is truncated
+						at the first semicolon.  This effectively makes the semicolon
+						a non-usable character for PJSIP endpoint names, extensions,
+						and AORs.  This can be useful for improving compatability with
+						an ITSP that likes to use user options for whatever reason.
+						</para>
+						<example title="Sample SIP URI">
+							sip:1235557890;phone-context=national@x.x.x.x;user=phone
+						</example>
+						<example title="Sample SIP URI user field">
+							1235557890;phone-context=national
+						</example>
+						<example title="Sample SIP URI user field truncated">
+							1235557890
+						</example>
+						<note><para>The caller-id and redirecting number strings
+						obtained from incoming SIP URI user fields are always truncated
+						at the first semicolon.</para></note>
+					</description>
+				</configOption>
 			</configObject>
 		</configFile>
 	</configInfo>
diff --git a/res/res_pjsip/config_global.c b/res/res_pjsip/config_global.c
index 281630ae43ac510955c6a445bfcf80566b669294..fc1227d2523305581584b874d3d84c2b5528aa53 100644
--- a/res/res_pjsip/config_global.c
+++ b/res/res_pjsip/config_global.c
@@ -47,6 +47,7 @@
 #define DEFAULT_MWI_TPS_QUEUE_HIGH AST_TASKPROCESSOR_HIGH_WATER_LEVEL
 #define DEFAULT_MWI_TPS_QUEUE_LOW -1
 #define DEFAULT_MWI_DISABLE_INITIAL_UNSOLICITED 0
+#define DEFAULT_IGNORE_URI_USER_OPTIONS 0
 
 /*!
  * \brief Cached global config object
@@ -100,6 +101,8 @@ struct global_config {
 		/*! Nonzero to disable sending unsolicited mwi to all endpoints on startup */
 		unsigned int disable_initial_unsolicited;
 	} mwi;
+	/*! Nonzero if URI user field options are ignored. */
+	unsigned int ignore_uri_user_options;
 };
 
 static void global_destructor(void *obj)
@@ -384,6 +387,20 @@ unsigned int ast_sip_get_mwi_disable_initial_unsolicited(void)
 	return disable_initial_unsolicited;
 }
 
+unsigned int ast_sip_get_ignore_uri_user_options(void)
+{
+	unsigned int ignore_uri_user_options;
+	struct global_config *cfg;
+
+	cfg = get_global_cfg();
+	if (!cfg) {
+		return DEFAULT_IGNORE_URI_USER_OPTIONS;
+	}
+
+	ignore_uri_user_options = cfg->ignore_uri_user_options;
+	ao2_ref(cfg, -1);
+	return ignore_uri_user_options;
+}
 
 /*!
  * \internal
@@ -533,6 +550,9 @@ int ast_sip_initialize_sorcery_global(void)
 	ast_sorcery_object_field_register(sorcery, "global", "mwi_disable_initial_unsolicited",
 		DEFAULT_MWI_DISABLE_INITIAL_UNSOLICITED ? "yes" : "no",
 		OPT_BOOL_T, 1, FLDSET(struct global_config, mwi.disable_initial_unsolicited));
+	ast_sorcery_object_field_register(sorcery, "global", "ignore_uri_user_options",
+		DEFAULT_IGNORE_URI_USER_OPTIONS ? "yes" : "no",
+		OPT_BOOL_T, 1, FLDSET(struct global_config, ignore_uri_user_options));
 
 	if (ast_sorcery_instance_observer_add(sorcery, &observer_callbacks_global)) {
 		return -1;
diff --git a/res/res_pjsip/pjsip_options.c b/res/res_pjsip/pjsip_options.c
index a282224c92fd05111f60f06f808d0c97b18470e5..09fe1559bfb0d8d5de4d18a28aef24a2299443d5 100644
--- a/res/res_pjsip/pjsip_options.c
+++ b/res/res_pjsip/pjsip_options.c
@@ -750,8 +750,7 @@ static pj_bool_t options_on_rx_request(pjsip_rx_data *rdata)
 	pjsip_sip_uri *sip_ruri;
 	char exten[AST_MAX_EXTENSION];
 
-	if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method,
-			     &pjsip_options_method)) {
+	if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_options_method)) {
 		return PJ_FALSE;
 	}
 
@@ -768,13 +767,20 @@ static pj_bool_t options_on_rx_request(pjsip_rx_data *rdata)
 	sip_ruri = pjsip_uri_get_uri(ruri);
 	ast_copy_pj_str(exten, &sip_ruri->user, sizeof(exten));
 
+	/*
+	 * We may want to match in the dialplan without any user
+	 * options getting in the way.
+	 */
+	AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(exten);
+
 	if (ast_shutting_down()) {
 		/*
 		 * Not taking any new calls at this time.
 		 * Likely a server availability OPTIONS poll.
 		 */
 		send_options_response(rdata, 503);
-	} else if (!ast_strlen_zero(exten) && !ast_exists_extension(NULL, endpoint->context, exten, 1, NULL)) {
+	} else if (!ast_strlen_zero(exten)
+		&& !ast_exists_extension(NULL, endpoint->context, exten, 1, NULL)) {
 		send_options_response(rdata, 404);
 	} else {
 		send_options_response(rdata, 200);
diff --git a/res/res_pjsip_caller_id.c b/res/res_pjsip_caller_id.c
index 429cb6107832cbe66539d96df18781a7ef1a9c17..16b19ec2ba4cfc645888e1cb2ea6e1fe2870f52a 100644
--- a/res/res_pjsip_caller_id.c
+++ b/res/res_pjsip_caller_id.c
@@ -46,11 +46,29 @@ static void set_id_from_hdr(pjsip_fromto_hdr *hdr, struct ast_party_id *id)
 	char cid_num[AST_CHANNEL_NAME];
 	pjsip_sip_uri *uri;
 	pjsip_name_addr *id_name_addr = (pjsip_name_addr *) hdr->uri;
+	char *semi;
 
 	uri = pjsip_uri_get_uri(id_name_addr);
 	ast_copy_pj_str(cid_name, &id_name_addr->display, sizeof(cid_name));
 	ast_copy_pj_str(cid_num, &uri->user, sizeof(cid_num));
 
+	/* Always truncate caller-id number at a semicolon. */
+	semi = strchr(cid_num, ';');
+	if (semi) {
+		/*
+		 * We need to be able to handle URI's looking like
+		 * "sip:1235557890;phone-context=national@x.x.x.x;user=phone"
+		 *
+		 * Where the uri->user field will result in:
+		 * "1235557890;phone-context=national"
+		 *
+		 * People don't care about anything after the semicolon
+		 * showing up on their displays even though the RFC
+		 * allows the semicolon.
+		 */
+		*semi = '\0';
+	}
+
 	ast_free(id->name.str);
 	id->name.str = ast_strdup(cid_name);
 	if (!ast_strlen_zero(cid_name)) {
diff --git a/res/res_pjsip_diversion.c b/res/res_pjsip_diversion.c
index 82c3caaed6ea3a40532ee3b99737982a82a46bbe..301d9fc9212cc3f5eed84f4067523c5fd3f608ea 100644
--- a/res/res_pjsip_diversion.c
+++ b/res/res_pjsip_diversion.c
@@ -148,11 +148,32 @@ static void set_redirecting_id(pjsip_name_addr *name_addr, struct ast_party_id *
 			       struct ast_set_party_id *update)
 {
 	pjsip_sip_uri *uri = pjsip_uri_get_uri(name_addr->uri);
+	char *semi;
+	pj_str_t uri_user;
+
+	uri_user = uri->user;
+
+	/* Always truncate redirecting number at a semicolon. */
+	semi = pj_strchr(&uri_user, ';');
+	if (semi) {
+		/*
+		 * We need to be able to handle URI's looking like
+		 * "sip:1235557890;phone-context=national@x.x.x.x;user=phone"
+		 *
+		 * Where the uri->user field will result in:
+		 * "1235557890;phone-context=national"
+		 *
+		 * People don't care about anything after the semicolon
+		 * showing up on their displays even though the RFC
+		 * allows the semicolon.
+		 */
+		pj_strset(&uri_user, (char *) pj_strbuf(&uri_user), semi - pj_strbuf(&uri_user));
+	}
 
-	if (pj_strlen(&uri->user)) {
+	if (pj_strlen(&uri_user)) {
 		update->number = 1;
 		data->number.valid = 1;
-		set_redirecting_value(&data->number.str, &uri->user);
+		set_redirecting_value(&data->number.str, &uri_user);
 	}
 
 	if (pj_strlen(&name_addr->display)) {
diff --git a/res/res_pjsip_endpoint_identifier_user.c b/res/res_pjsip_endpoint_identifier_user.c
index 6aa2c553206d888e21ba59a5113b2aa4c617caa6..369cb62fc9eb27ef7caf9328fe9b44f4dff11b5e 100644
--- a/res/res_pjsip_endpoint_identifier_user.c
+++ b/res/res_pjsip_endpoint_identifier_user.c
@@ -33,6 +33,7 @@ static int get_from_header(pjsip_rx_data *rdata, char *username, size_t username
 {
 	pjsip_uri *from = rdata->msg_info.from->uri;
 	pjsip_sip_uri *sip_from;
+
 	if (!PJSIP_URI_SCHEME_IS_SIP(from) && !PJSIP_URI_SCHEME_IS_SIPS(from)) {
 		return -1;
 	}
@@ -115,18 +116,25 @@ static struct ast_sip_endpoint *find_endpoint(pjsip_rx_data *rdata, char *endpoi
 
 static struct ast_sip_endpoint *username_identify(pjsip_rx_data *rdata)
 {
-	char username[64], domain[64];
+	char username[64];
+	char domain[64];
 	struct ast_sip_endpoint *endpoint;
 
 	if (get_from_header(rdata, username, sizeof(username), domain, sizeof(domain))) {
 		return NULL;
 	}
+
+	/*
+	 * We may want to be matched without any user options getting
+	 * in the way.
+	 */
+	AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(username);
+
 	ast_debug(3, "Attempting identify by From username '%s' domain '%s'\n", username, domain);
 
 	endpoint = find_endpoint(rdata, username, domain);
 	if (!endpoint) {
 		ast_debug(3, "Endpoint not found for From username '%s' domain '%s'\n", username, domain);
-		ao2_cleanup(endpoint);
 		return NULL;
 	}
 	if (!(endpoint->ident_method & AST_SIP_ENDPOINT_IDENTIFY_BY_USERNAME)) {
diff --git a/res/res_pjsip_messaging.c b/res/res_pjsip_messaging.c
index 7efb1a20e6c44574b462f8c7db476bfb685fa9f0..e63c825b58b49ea646dab26b2488bd528c17f704 100644
--- a/res/res_pjsip_messaging.c
+++ b/res/res_pjsip_messaging.c
@@ -133,6 +133,12 @@ static struct ast_sip_endpoint* get_outbound_endpoint(
 	} else if ((aor_uri = strchr(name, '@'))) {
 		/* format was 'endpoint@' - don't use the rest */
 		*aor_uri = '\0';
+
+		/*
+		 * We may want to match without any user options getting
+		 * in the way.
+		 */
+		AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(name);
 	}
 
 	/* at this point, if name is not empty then it
@@ -448,6 +454,12 @@ static enum pjsip_status_code rx_data_to_ast_msg(pjsip_rx_data *rdata, struct as
 	sip_ruri = pjsip_uri_get_uri(ruri);
 	ast_copy_pj_str(exten, &sip_ruri->user, AST_MAX_EXTENSION);
 
+	/*
+	 * We may want to match in the dialplan without any user
+	 * options getting in the way.
+	 */
+	AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(exten);
+
 	endpt = ast_pjsip_rdata_get_endpoint(rdata);
 	ast_assert(endpt != NULL);
 
@@ -528,7 +540,7 @@ static void msg_data_destroy(void *obj)
 
 static struct msg_data* msg_data_create(const struct ast_msg *msg, const char *to, const char *from)
 {
-	char *tag;
+	char *uri_params;
 	struct msg_data *mdata = ao2_alloc(sizeof(*mdata), msg_data_destroy);
 
 	if (!mdata) {
@@ -553,9 +565,14 @@ static struct msg_data* msg_data_create(const struct ast_msg *msg, const char *t
 		return NULL;
 	}
 
-	/* sometimes from can still contain the tag at this point, so remove it */
-	if ((tag = strchr(mdata->from, ';'))) {
-		*tag = '\0';
+	/*
+	 * Sometimes from URI can contain URI parameters, so remove them.
+	 *
+	 * sip:user;user-options@domain;uri-parameters
+	 */
+	uri_params = strchr(mdata->from, '@');
+	if (uri_params && (uri_params = strchr(mdata->from, ';'))) {
+		*uri_params = '\0';
 	}
 	return mdata;
 }
diff --git a/res/res_pjsip_path.c b/res/res_pjsip_path.c
index 2dde7323e61e56780518a9a332385c9300d7976b..e170a750d8d044d6de4aefe7cccd244ff0a22f6b 100644
--- a/res/res_pjsip_path.c
+++ b/res/res_pjsip_path.c
@@ -40,7 +40,8 @@ static struct ast_sip_aor *find_aor(struct ast_sip_endpoint *endpoint, pjsip_uri
 	char *configured_aors, *aor_name;
 	pjsip_sip_uri *sip_uri;
 	char *domain_name;
-	RAII_VAR(struct ast_str *, id, NULL, ast_free);
+	char *username;
+	struct ast_str *id = NULL;
 
 	if (ast_strlen_zero(endpoint->aors)) {
 		return NULL;
@@ -49,6 +50,14 @@ static struct ast_sip_aor *find_aor(struct ast_sip_endpoint *endpoint, pjsip_uri
 	sip_uri = pjsip_uri_get_uri(uri);
 	domain_name = ast_alloca(sip_uri->host.slen + 1);
 	ast_copy_pj_str(domain_name, &sip_uri->host, sip_uri->host.slen + 1);
+	username = ast_alloca(sip_uri->user.slen + 1);
+	ast_copy_pj_str(username, &sip_uri->user, sip_uri->user.slen + 1);
+
+	/*
+	 * We may want to match without any user options getting
+	 * in the way.
+	 */
+	AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(username);
 
 	configured_aors = ast_strdupa(endpoint->aors);
 
@@ -60,15 +69,16 @@ static struct ast_sip_aor *find_aor(struct ast_sip_endpoint *endpoint, pjsip_uri
 			continue;
 		}
 
-		if (!pj_strcmp2(&sip_uri->user, aor_name)) {
+		if (!strcmp(username, aor_name)) {
 			break;
 		}
 
-		if (!id && !(id = ast_str_create(sip_uri->user.slen + sip_uri->host.slen + 2))) {
-			return NULL;
+		if (!id && !(id = ast_str_create(strlen(username) + sip_uri->host.slen + 2))) {
+			aor_name = NULL;
+			break;
 		}
 
-		ast_str_set(&id, 0, "%.*s@", (int)sip_uri->user.slen, sip_uri->user.ptr);
+		ast_str_set(&id, 0, "%s@", username);
 		if ((alias = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "domain_alias", domain_name))) {
 			ast_str_append(&id, 0, "%s", alias->domain);
 			ao2_cleanup(alias);
@@ -77,10 +87,10 @@ static struct ast_sip_aor *find_aor(struct ast_sip_endpoint *endpoint, pjsip_uri
 		}
 
 		if (!strcmp(aor_name, ast_str_buffer(id))) {
-			ast_free(id);
 			break;
 		}
 	}
+	ast_free(id);
 
 	if (ast_strlen_zero(aor_name)) {
 		return NULL;
diff --git a/res/res_pjsip_pubsub.c b/res/res_pjsip_pubsub.c
index fe16c613ab86b408c4707f8ba6467f329f20c223..015ef99c7f3067a06ca09920c48d8be746834afc 100644
--- a/res/res_pjsip_pubsub.c
+++ b/res/res_pjsip_pubsub.c
@@ -1378,6 +1378,12 @@ static int sub_persistence_recreate(void *obj)
 	resource = ast_alloca(resource_size);
 	ast_copy_pj_str(resource, &request_uri->user, resource_size);
 
+	/*
+	 * We may want to match without any user options getting
+	 * in the way.
+	 */
+	AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(resource);
+
 	handler = subscription_get_handler_from_rdata(rdata);
 	if (!handler || !handler->notifier) {
 		ast_log(LOG_WARNING, "Failed recreating '%s' subscription: Could not get subscription handler.\n",
@@ -2750,6 +2756,12 @@ static pj_bool_t pubsub_on_rx_subscribe_request(pjsip_rx_data *rdata)
 	resource = ast_alloca(resource_size);
 	ast_copy_pj_str(resource, &request_uri_sip->user, resource_size);
 
+	/*
+	 * We may want to match without any user options getting
+	 * in the way.
+	 */
+	AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(resource);
+
 	expires_header = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, rdata->msg_info.msg->hdr.next);
 
 	if (expires_header) {
@@ -2963,6 +2975,12 @@ static struct ast_sip_publication *publish_request_initial(struct ast_sip_endpoi
 	resource_name = ast_alloca(resource_size);
 	ast_copy_pj_str(resource_name, &request_uri_sip->user, resource_size);
 
+	/*
+	 * We may want to match without any user options getting
+	 * in the way.
+	 */
+	AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(resource_name);
+
 	resource = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "inbound-publication", resource_name);
 	if (!resource) {
 		ast_debug(1, "No 'inbound-publication' defined for resource '%s'\n", resource_name);
diff --git a/res/res_pjsip_refer.c b/res/res_pjsip_refer.c
index 19367bf3261d5a960558eace8e921136bfd20efd..c1dee8225a095f7863ef4ee2afcd09e0235c57d8 100644
--- a/res/res_pjsip_refer.c
+++ b/res/res_pjsip_refer.c
@@ -814,6 +814,13 @@ static int refer_incoming_blind_request(struct ast_sip_session *session, pjsip_r
 
 	/* Using the user portion of the target URI see if it exists as a valid extension in their context */
 	ast_copy_pj_str(exten, &target->user, sizeof(exten));
+
+	/*
+	 * We may want to match in the dialplan without any user
+	 * options getting in the way.
+	 */
+	AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(exten);
+
 	if (!ast_exists_extension(NULL, context, exten, 1, NULL)) {
 		ast_log(LOG_ERROR, "Channel '%s' from endpoint '%s' attempted blind transfer to '%s@%s' but target does not exist\n",
 			ast_channel_name(session->channel), ast_sorcery_object_get_id(session->endpoint), exten, context);
diff --git a/res/res_pjsip_registrar.c b/res/res_pjsip_registrar.c
index fd87ef7bbbdae294da158b8c48070281c666b848..a8d2bdc4c2c160e6a7e5193d40e7a29e0ef244aa 100644
--- a/res/res_pjsip_registrar.c
+++ b/res/res_pjsip_registrar.c
@@ -626,6 +626,12 @@ static struct ast_sip_aor *find_registrar_aor(struct pjsip_rx_data *rdata, struc
 			username = ast_alloca(uri->user.slen + 1);
 			ast_copy_pj_str(username, &uri->user, uri->user.slen + 1);
 
+			/*
+			 * We may want to match without any user options getting
+			 * in the way.
+			 */
+			AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(username);
+
 			aor_name = find_aor_name(username, domain_name, endpoint->aors);
 			if (aor_name) {
 				ast_debug(3, "Matched aor '%s' by To username\n", aor_name);
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index a26359ffb18c6bef586f6227c4d8562f900d4aa3..7e885c3bddb1047ac8cca51c4bd9ba7da1ae6a7a 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -1982,6 +1982,12 @@ static enum sip_get_destination_result get_destination(struct ast_sip_session *s
 	sip_ruri = pjsip_uri_get_uri(ruri);
 	ast_copy_pj_str(session->exten, &sip_ruri->user, sizeof(session->exten));
 
+	/*
+	 * We may want to match in the dialplan without any user
+	 * options getting in the way.
+	 */
+	AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(session->exten);
+
 	pickup_cfg = ast_get_chan_features_pickup_config(session->channel);
 	if (!pickup_cfg) {
 		ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
@@ -3095,6 +3101,13 @@ static pjsip_redirect_op session_inv_on_redirected(pjsip_inv_session *inv, const
 		char exten[AST_MAX_EXTENSION];
 
 		ast_copy_pj_str(exten, &uri->user, sizeof(exten));
+
+		/*
+		 * We may want to match in the dialplan without any user
+		 * options getting in the way.
+		 */
+		AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(exten);
+
 		ast_channel_call_forward_set(session->channel, exten);
 	} else if (session->endpoint->redirect_method == AST_SIP_REDIRECT_URI_CORE) {
 		char target_uri[PJSIP_MAX_URL_SIZE];