Separate the message object from the transport action
Asterisk documents MESSAGE() as the read/write message object and MessageSend() as the application that hands its current body to a technology selected by the destination prefix. Set or inspect MESSAGE(body), MESSAGE(from) and MESSAGE(to) as content and logical identity; then treat the MessageSend() destination as the routing instruction. These are related inputs, not interchangeable strings.
Confirm the installed Asterisk release, loaded messaging and PJSIP modules, originating dialplan path and whether the object was created locally or inherited from an incoming message. Reusing an inbound object can also retain fields or custom data. Clear or copy only reviewed values rather than assuming a fresh blank envelope.
Resolve the PJSIP destination into one Request-URI
Every PJSIP form documented by MessageSend() begins with the pjsip: technology prefix, but the remainder can name an endpoint, endpoint and AoR, an endpoint plus explicit SIP URI, the default endpoint plus URI, or a dialstring-like PJSIP/user@endpoint form. Freeze the exact input and the resulting Request-URI. Endpoint, AoR, current contact and URI user are separate routing objects.
Do not infer routing from the To header. In the dialstring-like form, Asterisk replaces the user part of the endpoint contact URI. An endpoint label can select policy and transport while a contact supplies the network target. Inspect both the loaded configuration and current contact before changing DNS, authentication or message content.
Keep Request-URI, To and From precedence visible
MessageSend(destination,from,to) can override the From and To values already stored by MESSAGE(). The destination still constructs the Request-URI. Record the final Request-URI, To URI, From URI, endpoint, transport and outbound proxy separately because a provider or device can route on one field while authorizing or displaying another.
Use SIP or SIPS URIs that match the intended policy and avoid untrusted string concatenation. An accepted From header is not authenticated identity, and a SIPS URI or TLS hop is not body-level end-to-end confidentiality. Redact message bodies and personal identifiers from shared traces unless their exact value is necessary and authorized.
Route incoming MESSAGE requests through the intended context
For received PJSIP MESSAGE requests, current res_pjsip documentation says an endpoint message_context routes them to the named dialplan context; if it is absent, the endpoint context is used. That lookup is separate from an outbound MessageSend() destination. Prove endpoint identification, the loaded context, extension match and dialplan execution before blaming an outbound route.
MESSAGE() exposes the incoming source, recipient and UTF-8 body. MESSAGE_DATA() can read or write message-associated custom data, but an inbound value is not automatically a reviewed outbound header. Copy only an allowlisted field, preserve content type and authorization, and do not build an open relay.
Interpret MESSAGE_SEND_STATUS narrowly
Asterisk documents INVALID_PROTOCOL, INVALID_URI, SUCCESS and FAILURE in MESSAGE_SEND_STATUS. Its SUCCESS means the message was successfully passed to the protocol handler; the documentation explicitly says delivery is not necessarily guaranteed. Preserve the application return, emitted SIP request and final SIP response as three separate observations.
RFC 3428 adds later boundaries: 200 means the final user agent accepted the message, not that a person read it; 202 means a gateway or store-and-forward service accepted it without end-to-end delivery assurance. A timeout, 4xx, 5xx or 6xx needs the exact responsible hop and response rather than a generic delivered-or-failed label.
Bound body size, overlap and acceptance testing
RFC 3428 treats each pager-model MESSAGE as independent and says MESSAGE does not establish a dialog. It also limits out-of-dialog requests to 1300 bytes unless the sender positively knows the path avoids a congestion-unsafe hop or stays below the path MTU boundary. The RFC prohibits starting a new out-of-dialog MESSAGE transaction to the same URI while an earlier one remains pending.
Acceptance should prove the intended Request-URI, headers, body type and size, authentication, final response, endpoint presentation and any separate user-receipt mechanism. Do not describe SIP MESSAGE as carrier SMS, durable chat, encrypted content or guaranteed user delivery without independent evidence. No PBX, endpoint, request, response, packet, device interface or message was tested for this guide.
[message-out]
exten => send,1,Set(MESSAGE(body)=Maintenance window begins at 22:00 UTC)
same => n,Set(MESSAGE(from)=sip:ops@example.invalid)
same => n,MessageSend(pjsip:desk-201)
same => n,NoOp(Message handler status: ${MESSAGE_SEND_STATUS})
same => n,Return()Sources & applicability
Primary references for the technical details above. Operational examples and planning checklists are VoIP.info editorial guidance.
- Asterisk MessageSend dialplan application ↗
- Asterisk MESSAGE dialplan function ↗
- Asterisk MESSAGE_DATA dialplan function ↗
- Asterisk res_pjsip endpoint configuration ↗
- Asterisk 22 PJSIP_ENDPOINT reference ↗
- RFC 3428: SIP MESSAGE method ↗
Examples require adaptation to your topology. No live PBX or hardware testing is claimed.