DEV Community

Bo
Bo

Posted on • Updated on

Set Twilio Incoming SMS Hook

Set webhook URL

1, Go to "Develop > Phone numbers > Manage > Active Numbers", click the phone number you want to set the hook.

2, Scroll to the bottom to the page, in the "Messaging" section, click "Modify the Messaging Service configuration"

twilio messaging configuration

3, In this page, you will see several options under the "Incoming messages" section:

incoming messages

For example you can disable the incoming message which will disallow message sending to your number such that twilio won't charge your account.

Since this article is for setting the incoming hooks, so let's choose the "Send to a webhook" option, then in the input box, write our hook URL (see below) and set the method to be POST.

Code our webhook server

Now let's code our webhook server. Say our webhook URL in the above step is set to "https://example.org/twilio-hook", here we need to add an HTTP Post Endpoint to get the incoming message (here I am using the Golang's Fiber Web Framework):

package main

import (
    "encoding/xml"
    "fmt"
    "log"

    "github.com/gofiber/fiber/v2"
)

type TMLResp struct {
    XMLName xml.Name `xml:"Response"`
    Message string   `xml:"Message,omitempty"`
}

func buildTMLResp(msg string) string {
    b, _ := xml.Marshal(TMLResp{
        Message: msg,
    })
    return fmt.Sprintf("%s\n%s", xml.Header, b)
}

type SMSRequest struct {
    From string `form:"From"`
    Body string `form:"Body"`
}

func main() {
    app := fiber.New()

    app.Post("/twilio-hook", func(c *fiber.Ctx) error {
        log.Println("Body:")
        log.Println(string(c.Body()))
        reqParams := SMSRequest{}
        if err := c.BodyParser(&reqParams); err != nil {
            return c.SendStatus(fiber.StatusBadRequest)
        }
        // add our other logics here
        log.Printf("From: %s Message: %s\n", reqParams.From, reqParams.Body)
        c.Set(fiber.HeaderContentType, "application/xml")
        resp := fmt.Sprintf(
            "City: %s\nMessage: %s",
            reqParams.City,
            reqParams.Body,
        )
        return c.SendString(buildTMLResp(resp))
        // if we don't want to reply the message, just return an empty response
        // c.SendString(buildTMLResp(""))
    })

    app.Listen(":6767")
}
Enter fullscreen mode Exit fullscreen mode

The above code will print the incoming message body, do some further logic then return a Twilio XML that twilio can further auto reply that message to the user who sent SMS to your number.

The incoming message body are parameters with form-url-encoded format, it contains several fields like below (in the code aove we use the .BodyParser method to parse the message to a struct which only contains the fields we are interested):

Please notice some GEO fields (FromZip, ToCity, etc.) might be missing if Twilio can't detect them.

ToCountry=US
ToState=NY
SmsMessageSid=SMc17347ab5ba2aab4e87fa7c0c1ff5d73
NumMedia=0
ToCity=WATER+MILL
FromZip=11901
SmsSid=SMc17347ab5ba2bab4e77fa6c0c1ef5d63
FromState=NY
SmsStatus=received
FromCity=RIVERHEAD
Body=Test+msg
FromCountry=US
To=%2B19171234567
MessagingServiceSid=MG3aae3946423ce3ebd25e4c37a84a385c
ToZip=11968
NumSegments=1
MessageSid=SMc17347ab5ba2aab4e87fa7c0c1ff5d73
AccountSid=AC7a6bfbacbc909235584ecef67565643b
From=%2B19171234568
ApiVersion=2010-04-01
Enter fullscreen mode Exit fullscreen mode

The XML Message we sent back to Twilio is like this:

<Response>
    <Message>We got your message, thank you!</Message>
</Response>
Enter fullscreen mode Exit fullscreen mode

Once Twilio got this XML response, it will reply a SMS with the content inside the <Message></Message> tag to the user.

If we don't want to reply that user, we can simply return an empty response, like an empty string:

c.Set(fiber.HeaderContentType, "application/xml")
return c.SendString("<Response></Response>")
// or in the above code, use
// return c.SendString(buildTMLResp(""))
Enter fullscreen mode Exit fullscreen mode

Auto forward message

You can use the TwiML to further forward a message, like:

<Response>
    <Message to='+13105555555'>{{From}}: {{Body}}</Message>
</Response>
Enter fullscreen mode Exit fullscreen mode

Or you can use Twilio's GUI tool to do it and you can use this tool to forward to multiple numbers:
Twilio GUI Tool: Forward to multiple numbers

This will create a Twilio Cloud Function. Once you saved and published it, twilio will config that function as your incoming message's hook.

Reference

Discussion (0)