diff --git a/src/channels/chan_voicemngr.c b/src/channels/chan_voicemngr.c
index 9f968184e740e3fbb199738b15a2cb92aa509886..766289e4883b38cacd8d794d4f315f7ccfa27ca9 100644
--- a/src/channels/chan_voicemngr.c
+++ b/src/channels/chan_voicemngr.c
@@ -2602,12 +2602,11 @@ void handle_dtmf_calling(struct chan_voicemngr_subchannel *sub)
 	char dtmf_last_char = p->dtmfbuf[(dtmfbuf_len - 1)];
 	char dtmf_one_before_last_char = p->dtmfbuf[(dtmfbuf_len > 1 ? dtmfbuf_len - 2 : 0)];
 
-	sub->direct_extension = 0;
-	if (ast_exists_extension(NULL, p->context_direct, p->dtmfbuf, 1, p->cid_num) && !ast_matchmore_extension(NULL, p->context_direct, p->dtmfbuf, 1, p->cid_num))
+	if (ast_exists_extension(NULL, p->context_direct, p->dtmfbuf, 1, p->cid_num) &&
+			!ast_matchmore_extension(NULL, p->context_direct, p->dtmfbuf, 1, p->cid_num))
 	{
 		//We have a full match in the "direct" context, so have asterisk place a call immediately
 		ast_debug(9, "Direct extension matching %s found\n", p->dtmfbuf);
-		sub->direct_extension = 1;
 		chan_voicemngr_start_calling(sub, p->context_direct);
 	}
 
@@ -3141,28 +3140,14 @@ static void handle_dtmf(enum LINE_EVENT event,
 	if (p->dtmf_first < 0) { // DTMF pressed
 		p->dtmf_first = dtmf_button;
 		ast_debug(9,"Pressed DTMF %s\n", dtmfMap->name);
-		if (owner) {
-			struct ast_channel *bridged_chan = ast_channel_bridge_peer(owner);
-			if (bridged_chan) {
-				const struct ast_channel_tech *chan_tech = ast_channel_tech(bridged_chan);
-				if (chan_tech && chan_tech->type && *chan_tech->type) {
-					ast_debug(1, "debug_tmp: the type of the bridged channel is %s, sub->direct_extension = %d\n",
-							chan_tech->type, sub->direct_extension);
-				} else {
-					ast_debug(1, "debug_tmp: the type of the bridged channel is unknown, sub->direct_extension = %d\n",
-							sub->direct_extension);
-				}
-				ast_channel_unref(bridged_chan);
-			} else {
-				ast_debug(1, "debug_tmp: there is no bridged channel, sub->direct_extension = %d. is there a bridge? %s\n",
-						sub->direct_extension, ast_channel_internal_bridge(owner) ? "yes" : "no");
-			}
-		}
-		if (owner && chan_voicemngr_should_relay_dtmf(sub) && (sub->dtmf_mode == AST_SIP_DTMF_INFO || sub->conference_initiator == 1 || sub->direct_extension == 1)) {
-			// INCALL
+		/* Frame AST_FRAME_DTMF_BEGIN must be queued to the channel if the call is terminated by Asterisk core or applications,
+		 * e.g. VoiceMail, call forwarding. Otherwise DTMF digits won't be collected if DTMF relay method is not SIP INFO.
+		 * There is no bridge created for those calls. A bridge is always created for normal 2-way or 3-way calls no matter they are
+		 * internal or external. */
+		if (owner && chan_voicemngr_should_relay_dtmf(sub) &&
+				(sub->dtmf_mode == AST_SIP_DTMF_INFO || sub->conference_initiator == 1 || !ast_channel_internal_bridge(owner))) {
 			send_outgoing_dtmf(owner, dtmf_button, AST_FRAME_DTMF_BEGIN);
 		}
-
 		/* Do not send AST_FRAME_DTMF_BEGIN to allow DSP-generated tone to pass through */
 	} else if (p->dtmf_first == dtmf_button) { // DTMF released
 		ast_log(LOG_NOTICE,"Released DTMF %s\n", dtmfMap->name);
@@ -3196,25 +3181,11 @@ static void handle_dtmf(enum LINE_EVENT event,
 				sub->channel_state = DIALING;
 				//ast_debug(5,"Set to state %s.\n", state2str(sub->channel_state));
 			} else if (sub->channel_state == INCALL) {
-				if (owner) {
-					struct ast_channel *bridged_chan = ast_channel_bridge_peer(owner);
-					if (bridged_chan) {
-						const struct ast_channel_tech *chan_tech = ast_channel_tech(bridged_chan);
-						if (chan_tech && chan_tech->type && *chan_tech->type) {
-							ast_debug(1, "debug_tmp: the type of the bridged channel is %s, sub->direct_extension = %d\n",
-									chan_tech->type, sub->direct_extension);
-						} else {
-							ast_debug(1, "debug_tmp: the type of the bridged channel is unknown, sub->direct_extension = %d\n",
-									sub->direct_extension);
-						}
-						ast_channel_unref(bridged_chan);
-					} else {
-						ast_debug(1, "debug_tmp: there is no bridged channel, sub->direct_extension = %d. is there a bridge? %s\n",
-								sub->direct_extension, ast_channel_internal_bridge(owner) ? "yes" : "no");
-					}
-				}
-				if (owner && (sub->dtmf_mode == AST_SIP_DTMF_INFO || sub->conference_initiator == 1 || sub->direct_extension)) {
-					// INCALL
+				/* Frame AST_FRAME_DTMF_END must be queued to the channel if the call is terminated by Asterisk core or applications,
+				 * e.g. VoiceMail, call forwarding. Otherwise DTMF digits won't be collected if DTMF relay method is not SIP INFO.
+				 * There is no bridge created for those calls. A bridge is always created for normal 2-way or 3-way calls no matter they are
+				 * internal or external. */
+				if (owner && (sub->dtmf_mode == AST_SIP_DTMF_INFO || sub->conference_initiator == 1 || !ast_channel_internal_bridge(owner))) {
 					send_outgoing_dtmf(owner, dtmf_button, AST_FRAME_DTMF_END);
 				}
 			} else {
@@ -3928,7 +3899,6 @@ static struct chan_voicemngr_pvt *chan_voicemngr_allocate_pvt(void)
 				sub->sip_client_id = -1;
 				sub->period = default_ptime;												// 20 ms
 				sub->dtmf_mode = AST_SIP_DTMF_RFC_4733;
-				sub->direct_extension = 0;
 				sub->dtmf_pt = RTP_PT_DTMF;
 				sub->conference_initiator = 0;
 				tmp->sub[i] = sub;
@@ -5811,7 +5781,6 @@ static int chan_voicemngr_close_connection(struct chan_voicemngr_subchannel *sub
 		sub->codec = -1;
 		sub->call_id = CALLID_INVALID;
 		sub->updated_codec = 0;
-		sub->direct_extension = 0;
 		ast_debug(1, "Virtual Asterisk connection %d/%d destroyed\n", p->line_id, sub->connection_id);
 	}
 
diff --git a/src/channels/chan_voicemngr.h b/src/channels/chan_voicemngr.h
index 4ad5e061cb809b6fa9ef8d2b35324d228c2f141d..304761d1e76b0c526b03945c8c41adeb2e9add7a 100644
--- a/src/channels/chan_voicemngr.h
+++ b/src/channels/chan_voicemngr.h
@@ -190,7 +190,6 @@ struct chan_voicemngr_subchannel {
 	int updated_codec;
 	int sip_client_id;	/* The SIP client used for the current call: -1 = not set, 0 = internal call, 1..MAX_SIP_CLIENTS = sip client id*/
 	int congestion_timer_id;
-	int direct_extension;
 };
 
 struct chan_voicemngr_channel_tech {