diff --git a/src/im/instant_messaging.cpp b/src/im/instant_messaging.cpp
index 685cdd9ca87e1ea4cf98d10e15e3405d04ed727c..17a13105658fd38b3476cad1fd7384d5aca518e4 100644
--- a/src/im/instant_messaging.cpp
+++ b/src/im/instant_messaging.cpp
@@ -51,35 +51,28 @@ createMessageBody(pj_pool_t* pool,
      * 2. parse the first result by spliting by '/' into a type and subtype
      * 3. parse any following strings into arg=value by splitting by '='
      */
-
-    // NOTE: we duplicate all the c_str when creating pj_str_t strings because we're potentially
-    // working with local vars which might be destroyed before the message is sent and thus the
-    // the mem they pointed to could be something else at the time the message is actually sent
-
-    std::string mimeType, parameters;
+    std::string_view mimeType, parameters;
     auto sep = payload.first.find(';');
     if (std::string::npos == sep) {
         mimeType = payload.first;
     } else {
-        mimeType = payload.first.substr(0, sep);
-        parameters = payload.first.substr(sep + 1);
+        mimeType = std::string_view(payload.first).substr(0, sep);
+        parameters = std::string_view(payload.first).substr(sep + 1);
     }
 
     // split mime type to type and subtype
     sep = mimeType.find('/');
     if (std::string::npos == sep) {
-        JAMI_DBG("bad mime type: '%.30s'", mimeType.c_str());
+        JAMI_DBG("bad mime type: '%.*s'", (int) mimeType.size(), mimeType.data());
         throw im::InstantMessageException("invalid mime type");
     }
 
-    const auto& type = mimeType.substr(0, sep);
-    const auto& subtype = mimeType.substr(sep + 1);
+    auto type = sip_utils::CONST_PJ_STR(mimeType.substr(0, sep));
+    auto subtype = sip_utils::CONST_PJ_STR(mimeType.substr(sep + 1));
+    auto message = sip_utils::CONST_PJ_STR(payload.second);
 
     // create part
-    auto type_pj = pj_strdup3(pool, type.c_str());
-    auto subtype_pj = pj_strdup3(pool, subtype.c_str());
-    auto message_pj = pj_strdup3(pool, payload.second.c_str());
-    *body_p = pjsip_msg_body_create(pool, &type_pj, &subtype_pj, &message_pj);
+    *body_p = pjsip_msg_body_create(pool, &type, &subtype, &message);
 
     if (not parameters.size())
         return;
@@ -87,29 +80,25 @@ createMessageBody(pj_pool_t* pool,
     // now try to add parameters one by one
     do {
         sep = parameters.find(';');
-        const auto& paramPair = parameters.substr(0, sep);
-        if (not paramPair.size())
+        auto paramPair = parameters.substr(0, sep);
+        if (paramPair.empty())
             break;
 
         // split paramPair into arg and value by '='
         auto paramSplit = paramPair.find('=');
         if (std::string::npos == paramSplit) {
-            JAMI_DBG("bad parameter: '%.30s'", paramPair.c_str());
+            JAMI_DBG("bad parameter: '%.*s'", (int)paramPair.size(), paramPair.data());
             throw im::InstantMessageException("invalid parameter");
         }
 
-        const auto& arg = paramPair.substr(0, paramSplit);
-        const auto& value = paramPair.substr(paramSplit + 1);
-
-        // add to the body content type
-        auto arg_pj = pj_strdup3(pool, arg.c_str());
-        pj_strtrim(&arg_pj);
-        auto value_pj = pj_strdup3(pool, value.c_str());
-        pj_strtrim(&value_pj);
-
+        auto arg = sip_utils::CONST_PJ_STR(paramPair.substr(0, paramSplit));
+        auto value = sip_utils::CONST_PJ_STR(paramPair.substr(paramSplit + 1));
+        pj_strtrim(&arg);
+        pj_strtrim(&value);
+        pj_str_t arg_pj, value_pj;
         pjsip_param* param = PJ_POOL_ALLOC_T(pool, pjsip_param);
-        param->name = arg_pj;
-        param->value = value_pj;
+        param->name = *pj_strdup(pool, &arg_pj, &arg);
+        param->value = *pj_strdup(pool, &value_pj, &value);
         pj_list_push_back(&(*body_p)->content_type.param, param);
 
         // next parameter?
@@ -194,26 +183,19 @@ 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)
 {
-    const std::string type {body->content_type.type.ptr, (size_t) body->content_type.type.slen};
-    const std::string subtype {body->content_type.subtype.ptr,
-                               (size_t) body->content_type.subtype.slen};
-    std::string header = 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;
     while (param != &body->content_type.param) {
-        const std::string arg {param->name.ptr, (size_t) param->name.slen};
-        const std::string value {param->value.ptr, (size_t) param->value.slen};
-
-        header += ";" + arg + "=" + value;
-
+        header += ";" + sip_utils::as_view(param->name) + "=" + sip_utils::as_view(param->value);
         param = param->next;
     }
 
     // get the payload, assume we can interpret it as chars
-    const std::string payload {static_cast<char*>(body->data), body->len};
-
-    return std::make_pair(header, payload);
+    return {std::move(header),
+            std::string(static_cast<char*>(body->data), (size_t)body->len)};
 }
 
 /**
@@ -239,14 +221,14 @@ im::parseSipMessage(const pjsip_msg* msg)
 
     if (pj_strcmp(&typeMultipart, &msg->body->content_type.type) != 0) {
         // treat as single content type message
-        ret.insert(parseMessageBody(msg->body));
+        ret.emplace(parseMessageBody(msg->body));
     } else {
         /* multipart type message, we will treat it as multipart/mixed even if the subtype is
          * something else, eg: related
          */
         auto part = pjsip_multipart_get_first_part(msg->body);
         while (part != nullptr) {
-            ret.insert(parseMessageBody(part->body));
+            ret.emplace(parseMessageBody(part->body));
             part = pjsip_multipart_get_next_part(msg->body, part);
         }
     }