diff --git a/src/im/instant_messaging.cpp b/src/im/instant_messaging.cpp
index b9057ee1f7f857bc46e156ff79160a4e12bedb03..bbf90bd3bce6efa6e932436862adf32084ce8ba8 100644
--- a/src/im/instant_messaging.cpp
+++ b/src/im/instant_messaging.cpp
@@ -87,7 +87,7 @@ createMessageBody(pj_pool_t* pool,
         // split paramPair into arg and value by '='
         auto paramSplit = paramPair.find('=');
         if (std::string::npos == paramSplit) {
-            JAMI_DBG("bad parameter: '%.*s'", (int)paramPair.size(), paramPair.data());
+            JAMI_DBG("bad parameter: '%.*s'", (int) paramPair.size(), paramPair.data());
             throw im::InstantMessageException("invalid parameter");
         }
 
@@ -149,7 +149,8 @@ im::sendSipMessage(pjsip_inv_session* session, const std::map<std::string, std::
         return;
     }
 
-    constexpr pjsip_method msg_method = {PJSIP_OTHER_METHOD, CONST_PJ_STR("MESSAGE")};
+    constexpr pjsip_method msg_method = {PJSIP_OTHER_METHOD,
+                                         CONST_PJ_STR(sip_utils::SIP_METHODS::MESSAGE)};
 
     {
         auto dialog = session->dlg;
@@ -183,8 +184,8 @@ im::sendSipMessage(pjsip_inv_session* session, const std::map<std::string, std::
 static std::pair<std::string, std::string>
 parseMessageBody(const pjsip_msg_body* body)
 {
-    std::string header = sip_utils::as_view(body->content_type.type)
-                 + "/" + sip_utils::as_view(body->content_type.subtype);
+    std::string header = sip_utils::as_view(body->content_type.type) + "/"
+                         + sip_utils::as_view(body->content_type.subtype);
 
     // iterate over parameters
     auto param = body->content_type.param.next;
@@ -194,8 +195,7 @@ parseMessageBody(const pjsip_msg_body* body)
     }
 
     // get the payload, assume we can interpret it as chars
-    return {std::move(header),
-            std::string(static_cast<char*>(body->data), (size_t)body->len)};
+    return {std::move(header), std::string(static_cast<char*>(body->data), (size_t) body->len)};
 }
 
 /**
diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp
index 77c57ec61b9a4ed6dfe7f7f66484d70a40c62d93..8e9fe1da92966a9859049a821b183029865ae138 100644
--- a/src/jamidht/jamiaccount.cpp
+++ b/src/jamidht/jamiaccount.cpp
@@ -3937,7 +3937,8 @@ JamiAccount::sendSIPMessage(SipConnection& conn,
     pjsip_tx_data* tdata;
 
     // Build SIP message
-    constexpr pjsip_method msg_method = {PJSIP_OTHER_METHOD, sip_utils::CONST_PJ_STR("MESSAGE")};
+    constexpr pjsip_method msg_method = {PJSIP_OTHER_METHOD,
+                                         sip_utils::CONST_PJ_STR(sip_utils::SIP_METHODS::MESSAGE)};
     pj_str_t pjFrom = sip_utils::CONST_PJ_STR(from);
     pj_str_t pjTo = sip_utils::CONST_PJ_STR(toURI);
 
diff --git a/src/manager.cpp b/src/manager.cpp
index b47ccfb36847b1f1c6d15e97ea376d84c9fa8fe2..870336ca653a45dbe99ce7ff1d5fdbffc8a9cfc4 100644
--- a/src/manager.cpp
+++ b/src/manager.cpp
@@ -1950,7 +1950,7 @@ Manager::sendCallTextMessage(const std::string& accountId,
             }
         }
     } else {
-        JAMI_ERR("Failed to send message to %s: inexistant call ID", callID.c_str());
+        JAMI_ERR("Failed to send message to %s: inexistent call ID", callID.c_str());
     }
 }
 
diff --git a/src/sip/sip_utils.cpp b/src/sip/sip_utils.cpp
index edfed41bed70672a15e4895ad70fdf7276a26396..9dd46906c2f871d4d5d7c6ee23565ee1581304df 100644
--- a/src/sip/sip_utils.cpp
+++ b/src/sip/sip_utils.cpp
@@ -223,7 +223,7 @@ std::string_view
 getPeerUserAgent(const pjsip_rx_data* rdata)
 {
     if (rdata == nullptr or rdata->msg_info.msg == nullptr) {
-        JAMI_ERR("Unexpected null poiter!");
+        JAMI_ERR("Unexpected null pointer!");
         return {};
     }
 
@@ -236,6 +236,29 @@ getPeerUserAgent(const pjsip_rx_data* rdata)
     return {};
 }
 
+std::vector<std::string>
+getPeerAllowMethods(const pjsip_rx_data* rdata)
+{
+    if (rdata == nullptr or rdata->msg_info.msg == nullptr) {
+        JAMI_ERR("Unexpected null pointer!");
+        return {};
+    }
+
+    std::vector<std::string> methods;
+
+    pjsip_allow_hdr* allow = static_cast<pjsip_allow_hdr*>(
+        pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_ALLOW, nullptr));
+
+    if (allow != nullptr) {
+        methods.reserve(allow->count);
+        for (unsigned i = 0; i < allow->count; i++) {
+            methods.emplace_back(allow->values[i].ptr, allow->values[i].slen);
+        }
+    }
+
+    return methods;
+}
+
 void
 logMessageHeaders(const pjsip_hdr* hdr_list)
 {
diff --git a/src/sip/sip_utils.h b/src/sip/sip_utils.h
index 9b72323fac12754fbdd1bf2c941fc40fb2276c96..ffe68f42adb31f65820fa87638cd2541af9d5b7b 100644
--- a/src/sip/sip_utils.h
+++ b/src/sip/sip_utils.h
@@ -39,6 +39,18 @@
 namespace jami {
 namespace sip_utils {
 
+// SIP methods. Only list methods that need to be explicitly
+// handled
+
+namespace SIP_METHODS {
+constexpr std::string_view MESSAGE = "MESSAGE";
+constexpr std::string_view INFO = "INFO";
+constexpr std::string_view OPTIONS = "OPTIONS";
+constexpr std::string_view PUBLISH = "PUBLISH";
+constexpr std::string_view REFER = "REFER";
+constexpr std::string_view NOTIFY = "NOTIFY";
+} // namespace SIP_METHODS
+
 static constexpr int DEFAULT_SIP_PORT {5060};
 static constexpr int DEFAULT_SIP_TLS_PORT {5061};
 static constexpr int DEFAULT_AUTO_SELECT_PORT {0};
@@ -99,6 +111,7 @@ std::string_view getHostFromUri(std::string_view sipUri);
 void addContactHeader(const std::string& contact, pjsip_tx_data* tdata);
 void addUserAgentHeader(const std::string& userAgent, pjsip_tx_data* tdata);
 std::string_view getPeerUserAgent(const pjsip_rx_data* rdata);
+std::vector<std::string> getPeerAllowMethods(const pjsip_rx_data* rdata);
 void logMessageHeaders(const pjsip_hdr* hdr_list);
 
 std::string sip_strerror(pj_status_t code);
diff --git a/src/sip/sipaccount.cpp b/src/sip/sipaccount.cpp
index ac92eae687e3ead235b0495663fbbed318f5ddfa..0c3193014890edda93da48e8b488ad9c9cb91d60 100644
--- a/src/sip/sipaccount.cpp
+++ b/src/sip/sipaccount.cpp
@@ -2243,7 +2243,8 @@ SIPAccount::sendTextMessage(const std::string& to,
 
     auto toUri = getToUri(to);
 
-    constexpr pjsip_method msg_method = {PJSIP_OTHER_METHOD, CONST_PJ_STR("MESSAGE")};
+    constexpr pjsip_method msg_method = {PJSIP_OTHER_METHOD,
+                                         CONST_PJ_STR(sip_utils::SIP_METHODS::MESSAGE)};
     std::string from(getFromUri());
     pj_str_t pjFrom = sip_utils::CONST_PJ_STR(from);
     pj_str_t pjTo = sip_utils::CONST_PJ_STR(toUri);
diff --git a/src/sip/sipcall.cpp b/src/sip/sipcall.cpp
index bf245c80f10fb4112cab5275da0a25d65c7db4b6..02a90e8eae34184fe1f67fcf318b2c22552cb662 100644
--- a/src/sip/sipcall.cpp
+++ b/src/sip/sipcall.cpp
@@ -1460,8 +1460,29 @@ SIPCall::sendTextMessage(const std::map<std::string, std::string>& messages, con
     } else {
         if (inviteSession_) {
             try {
+                // Ignore if the peer does not allow "MESSAGE" SIP method
+                // NOTE:
+                // The SIP "Allow" header is not mandatory as per RFC-3261. If it's
+                // not present and since "MESSAGE" method is an extention method,
+                // we choose to assume that the peer does not support the "MESSAGE"
+                // method to prevent unexpected behavior when interoperating with
+                // some SIP implementations.
+                if (not isSipMethodAllowedByPeer(sip_utils::SIP_METHODS::MESSAGE)) {
+                    JAMI_WARN() << fmt::format("[call:{}] Peer does not allow \"{}\" method]",
+                                               getCallId(),
+                                               sip_utils::SIP_METHODS::MESSAGE);
+
+                    // Print peer's allowed methods
+                    JAMI_INFO() << fmt::format("[call:{}] Peer's allowed methods: {}",
+                                               getCallId(),
+                                               peerAllowedMethods_);
+                    return;
+                }
+
                 im::sendSipMessage(inviteSession_.get(), messages);
+
             } catch (...) {
+                JAMI_ERR("[call:%s] Failed to send SIP text message", getCallId().c_str());
             }
         } else {
             pendingOutMessages_.emplace_back(messages, from);
@@ -1650,6 +1671,22 @@ SIPCall::setPeerUaVersion(std::string_view ua)
     }
 }
 
+void
+SIPCall::setPeerAllowMethods(std::vector<std::string> methods)
+{
+    std::lock_guard<std::recursive_mutex> lock {callMutex_};
+    peerAllowedMethods_ = std::move(methods);
+}
+
+bool
+SIPCall::isSipMethodAllowedByPeer(const std::string_view method) const
+{
+    std::lock_guard<std::recursive_mutex> lock {callMutex_};
+
+    return std::find(peerAllowedMethods_.begin(), peerAllowedMethods_.end(), method)
+           != peerAllowedMethods_.end();
+}
+
 void
 SIPCall::onPeerRinging()
 {
@@ -3182,6 +3219,7 @@ SIPCall::merge(Call& call)
     localVideoPort_ = subcall.localVideoPort_;
     peerUserAgent_ = subcall.peerUserAgent_;
     peerSupportMultiStream_ = subcall.peerSupportMultiStream_;
+    peerAllowedMethods_ = subcall.peerAllowedMethods_;
 
     Call::merge(subcall);
     if (isIceEnabled())
@@ -3234,8 +3272,8 @@ SIPCall::setupIceResponse()
 
     if (not remoteHasValidIceAttributes()) {
         // If ICE attributes are not present, skip the ICE initialization
-        // step (most likely ICE is not used).
-        JAMI_ERR("[call:%s] no ICE data in remote SDP", getCallId().c_str());
+        // step (most likely peer does not support/enable ICE).
+        JAMI_WARN("[call:%s] no ICE data in remote SDP", getCallId().c_str());
         return;
     }
 
diff --git a/src/sip/sipcall.h b/src/sip/sipcall.h
index 303bfb1a0691d48e83bd70c15b63a2f8a51995ba..d89f4e03b278c6005872d54511b79acc857cea67 100644
--- a/src/sip/sipcall.h
+++ b/src/sip/sipcall.h
@@ -178,6 +178,16 @@ public:
      */
     void setPeerUaVersion(std::string_view ua);
 
+    /**
+     * Set peer's allowed methods
+     */
+    void setPeerAllowMethods(std::vector<std::string> methods);
+
+    /**
+     * Check if a SIP method is allowed by peer
+     */
+    bool isSipMethodAllowedByPeer(const std::string_view method) const;
+
     /**
      * Return the SDP's manager of this call
      */
@@ -415,6 +425,9 @@ private:
     // Flag to indicate the the peer's Daemon version support multi-stream.
     bool peerSupportMultiStream_ {false};
 
+    // Peer's allowed methods.
+    std::vector<std::string> peerAllowedMethods_;
+
     // Vector holding the current RTP sessions.
     std::vector<RtpStream> rtpStreams_;
 
diff --git a/src/sip/sipvoiplink.cpp b/src/sip/sipvoiplink.cpp
index 5c2d7975f7eb8f472edbb4f0449370d398d76a4d..aad68002c620a54f6ba06c3ea299dcee406b3bc1 100644
--- a/src/sip/sipvoiplink.cpp
+++ b/src/sip/sipvoiplink.cpp
@@ -299,7 +299,7 @@ transaction_request_cb(pjsip_rx_data* rdata)
     if (method->id == PJSIP_OTHER_METHOD) {
         std::string_view request = sip_utils::as_view(method->name);
 
-        if (request.find("NOTIFY") != std::string_view::npos) {
+        if (request.find(sip_utils::SIP_METHODS::NOTIFY) != std::string_view::npos) {
             if (body and body->data) {
                 std::string_view body_view(static_cast<char*>(body->data), body->len);
                 auto pos = body_view.find("Voice-Message: ");
@@ -323,7 +323,7 @@ transaction_request_cb(pjsip_rx_data* rdata)
                                                                        urgentCount);
                 }
             }
-        } else if (request.find("MESSAGE") != std::string_view::npos) {
+        } else if (request.find(sip_utils::SIP_METHODS::MESSAGE) != std::string_view::npos) {
             // Reply 200 immediately (RFC 3428, ch. 7)
             try_respond_stateless(endpt_, rdata, PJSIP_SC_OK, nullptr, nullptr, nullptr);
             // Process message content in case of multi-part body
@@ -452,6 +452,7 @@ transaction_request_cb(pjsip_rx_data* rdata)
     call->setPeerDisplayName(peerDisplayName);
     call->setState(Call::ConnectionState::PROGRESSING);
     call->getSDP().setPublishedIP(addrSdp);
+    call->setPeerAllowMethods(sip_utils::getPeerAllowMethods(rdata));
 
     // Set the temporary media list. Might change when we receive
     // the accept from the client.
@@ -714,10 +715,10 @@ SIPVoIPLink::SIPVoIPLink()
     TRY(pjsip_inv_usage_init(endpt_, &inv_cb));
 
     static constexpr pj_str_t allowed[] = {
-        CONST_PJ_STR("INFO"),
-        CONST_PJ_STR("OPTIONS"),
-        CONST_PJ_STR("MESSAGE"),
-        CONST_PJ_STR("PUBLISH"),
+        CONST_PJ_STR(sip_utils::SIP_METHODS::INFO),
+        CONST_PJ_STR(sip_utils::SIP_METHODS::OPTIONS),
+        CONST_PJ_STR(sip_utils::SIP_METHODS::MESSAGE),
+        CONST_PJ_STR(sip_utils::SIP_METHODS::PUBLISH),
     };
 
     pjsip_endpt_add_capability(endpt_,
@@ -911,11 +912,15 @@ invite_session_state_changed_cb(pjsip_inv_session* inv, pjsip_event* ev)
                  pjsip_inv_state_name(inv->state),
                  inv->cause);
     }
-
+    pjsip_rx_data* rdata {nullptr};
     if (ev->type == PJSIP_EVENT_RX_MSG) {
-        call->setPeerUaVersion(sip_utils::getPeerUserAgent(ev->body.rx_msg.rdata));
+        rdata = ev->body.rx_msg.rdata;
     } else if (ev->type == PJSIP_EVENT_TSX_STATE and ev->body.tsx_state.type == PJSIP_EVENT_RX_MSG) {
-        call->setPeerUaVersion(sip_utils::getPeerUserAgent(ev->body.tsx_state.src.rdata));
+        rdata = ev->body.tsx_state.src.rdata;
+    }
+    if (rdata != nullptr) {
+        call->setPeerUaVersion(sip_utils::getPeerUserAgent(rdata));
+        call->setPeerAllowMethods(sip_utils::getPeerAllowMethods(rdata));
     }
 
     switch (inv->state) {
@@ -1348,15 +1353,15 @@ transaction_state_changed_cb(pjsip_inv_session* inv, pjsip_transaction* tsx, pjs
     JAMI_DBG("%s", msgbuf);
 #endif // DEBUG_SIP_MESSAGE
 
-    if (methodName == "REFER")
+    if (methodName == sip_utils::SIP_METHODS::REFER)
         onRequestRefer(inv, rdata, msg, *call);
-    else if (methodName == "INFO")
+    else if (methodName == sip_utils::SIP_METHODS::INFO)
         onRequestInfo(inv, rdata, msg, *call);
-    else if (methodName == "NOTIFY")
+    else if (methodName == sip_utils::SIP_METHODS::NOTIFY)
         onRequestNotify(inv, rdata, msg, *call);
-    else if (methodName == "OPTIONS")
+    else if (methodName == sip_utils::SIP_METHODS::OPTIONS)
         handleIncomingOptions(rdata);
-    else if (methodName == "MESSAGE") {
+    else if (methodName == sip_utils::SIP_METHODS::MESSAGE) {
         if (msg->body)
             runOnMainThread([call, m = im::parseSipMessage(msg)]() mutable {
                 call->onTextMessage(std::move(m));