Я пробую сервис Twilio для взаимодействия с людьми через SMS/MMS. Я примерно понял, как отправлять MMS-сообщения, чтобы начать «разговор», и, похоже, это работает хорошо. Однако сейчас я пытаюсь создать систему, которая будет отвечать на входящие сообщения на мой тестовый номер с поддержкой SMS/MMS. Я работаю с одним из примеров, которые я нашел на сайте документации Twilio, для создания веб-службы ASP.NET MVC для обработки диалога (VB.NET):
Imports System.Web.Mvc
Imports Twilio.AspNet.Common
Imports Twilio.AspNet.Mvc
Imports Twilio.TwiML
Namespace Controllers
Public Class SMSController
Inherits TwilioController
' GET: SMS
Function Index(ByVal IncomingSMS As SmsRequest) As TwiMLResult
Dim SMSResponse As New MessagingResponse
Dim SMSMessage As String = IncomingSMS.Body
Dim JediCode As String = "There is no emotion, there is peace."
Dim SithCode As String = "Peace is a lie. There is only Passion."
JediCode += vbCrLf & "There is no ignorance, there is knowledge."
JediCode += vbCrLf & "There is no passion, there is serenity."
JediCode += vbCrLf & "There is no chaos, there is harmony."
JediCode += vbCrLf & "There is no death, there is the Force."
SithCode += vbCrLf & "Through Passion, I gain Strength."
SithCode += vbCrLf & "Through Strength, I gain Power."
SithCode += vbCrLf & "Through Power, I gain Victory."
SithCode += vbCrLf & "Through Victory my chains are Broken."
SithCode += vbCrLf & "The Force shall free me."
If SMSMessage IsNot Nothing Then
If SMSMessage.ToUpper.Trim = "JEDI" Then
SMSResponse.Message(JediCode)
ElseIf SMSMessage.ToUpper.Trim = "SITH" Then
SMSResponse.Message(SithCode)
Else
SMSResponse.Message("Ahsoka? Is that you?")
End If
Else
SMSResponse.Message("What did you want to know?")
End If
Return TwiML(SMSResponse)
End Function
End Class
End Namespace
Да, это все просто «игровые» вещи, которые я использую для тестирования и в конечном итоге буду заменен чем-то более подходящим для этой цели, но я хочу попытаться разобраться во всем этом, прежде чем я слишком углублюсь в реальность вещей. .
Я настроил сайт на своем сервере IIS, зарегистрировал DNS и даже настроил свой SSL-сертификат. Кажется, все отлично работает с моим простым тестированием до сих пор, но есть пара вещей, которые я до сих пор не смог понять, и я надеюсь, что кто-то здесь может указать мне правильное направление.
Я задам каждый по отдельности, но вот первый: как мне получить вложение из MMS-сообщения?
Я хотел бы иметь возможность получать PDF-файлы (и, возможно, файлы других типов) и передавать их по электронной почте соответствующему лицу или отделу. Я знаю, как отправлять сообщения по электронной почте, но мне не удалось найти соответствующую документацию о том, как получить вложения в MMS-сообщении, чтобы фактически включить их в этот процесс электронной почты.
Когда я пытаюсь получить доступ к свойствам объекта IncomingSMS (SmsRequest), я не нахожу ссылки на Media ни в одном из них — ни NumMedia, ни MediaUri, ничего. Кажется, не существует типа объекта MmsRequest (во всяком случае, я его еще не нашел).
Что я упускаю из виду, чтобы иметь возможность получить PDF-файл, который я отправил на свой тестовый номер, для дальнейшей обработки? Должен ли я изменить определение метода, чтобы принять объект как MessageResource или что-то в этом роде?
Обновлено: я забыл упомянуть, что я проверил консоль Twilio и увидел, что сообщение, по-видимому, было успешно получено с вложением, поэтому я знаю, что по крайней мере эта часть работает правильно.
Я задал второй связанный вопрос, который идет вместе с этим, чтобы помочь «доработать» некоторые вещи для наших целей.





Используемый вами класс SmsRequest взят из вспомогательной библиотеки Twilio для ASP.NET, цель которой — упростить интеграцию Twilio в ASP.NET. Однако SmsRequest и другие классы не охватывают все возможные параметры веб-перехватчика. Если в классе отсутствуют параметры, вы все равно можете получить параметры вручную, а не полагаться на привязку модели MVC.
На основе этого примера C# я создал пример VB.NET, чтобы показать, как получать и сохранять входящие файлы MMS:
Imports System.IO
Imports System.Net.Http
Imports System.Threading.Tasks
Imports MimeTypes
Imports Twilio.AspNet.Mvc
Imports Twilio.TwiML
Imports Twilio.TwiML.Messaging
Public Class HomeController
Inherits TwilioController
Shared httpClient As HttpClient = New HttpClient
Async Function Index() As Task(Of TwiMLResult)
Dim response As New MessagingResponse
Dim message As New Message
Dim numMedia = Short.Parse(If(Request.Form.Get("NumMedia"), 0))
If numMedia = 0 Then
response.Message("No file received.")
Return TwiML(response)
End If
For mediaIndex As Integer = 0 To numMedia - 1
Dim mediaUrl = Request.Form.Get($"MediaUrl{mediaIndex}")
Dim contentType = Request.Form.Get($"MediaContentType{mediaIndex}")
Dim saveFilePath = Server.MapPath(String.Format(
"~/App_Data/{0}{1}",
Path.GetFileName(mediaUrl),
MimeTypeMap.GetExtension(ContentType)
))
Await DownloadUrlToFileAsync(mediaUrl, saveFilePath)
Next
response.Message("File received.")
Return TwiML(response)
End Function
Private Async Function DownloadUrlToFileAsync(mediaUrl As String, saveFilePath As String) As Task
Dim Response = Await httpClient.GetAsync(mediaUrl)
Dim httpStream = Await Response.Content.ReadAsStreamAsync()
Using fileStream As Stream = IO.File.Create(saveFilePath)
Await httpStream.CopyToAsync(fileStream)
Await fileStream.FlushAsync()
End Using
End Function
End Class
Вероятно, вы можете немного упростить код, предполагая, что по MMS будет отправлен только один файл, но это хорошая идея, чтобы обрабатывать и другие случаи.
Чтобы получить правильное расширение файла, я использую это Библиотека MimeTypeMap, но можно накатить собственное решение.
По умолчанию файлы из входящих MMS общедоступны по MediaUrl{mediaIndex} URL-адресу, но рекомендуется включить базовую аутентификацию для этих медиафайлов.
Если вы включаете обычную аутентификацию для медиафайлов, вам необходимо добавить заголовок аутентификации в HTTP-запросы, например:
Imports System.IO
Imports System.Net.Http
Imports System.Net.Http.Headers
Imports System.Threading.Tasks
Imports MimeTypes
Imports Twilio.AspNet.Mvc
Imports Twilio.TwiML
Imports Twilio.TwiML.Messaging
Public Class HomeController
Inherits TwilioController
Shared httpClient As HttpClient = CreateHttpClient()
Private Shared Function CreateHttpClient() As HttpClient
Dim client As New HttpClient
Dim appSettings As NameValueCollection = ConfigurationManager.AppSettings
If Boolean.Parse(If(appSettings.Get("TwilioUseBasicAuthForMedia"), False)) Then
Dim authString = $"{appSettings.Get("TwilioAccountSid")}:{appSettings.Get("TwilioAuthToken")}"
authString = Convert.ToBase64String(Encoding.ASCII.GetBytes(authString))
client.DefaultRequestHeaders.Authorization = New AuthenticationHeaderValue("Basic", authString)
End If
Return client
End Function
...
End Class
Я получаю TwilioUseBasicAuthForMedia, TwilioAccountSid и TwilioAuthToken из настроек приложения Web.config.
(Убедитесь, что вы не проверяете эти секреты в системе управления версиями, а используйте вместо этого UserSecretsConfigBuilder, чтобы безопасно установить секреты).
Вы можете отправить сообщение о проблеме GitHub и/или PR, чтобы добавить поддержку этих отсутствующих параметров в SmsRequest. Хотя это будет не так просто, как обычная привязка модели, потому что количество параметров увеличивается по мере того, как больше файлов отправляется по MMS.
Понятно! Дайте мне знать, если мне нужно что-то уточнить. Удачи!
Я включил код извлечения мультимедиа в мой код контроллера MVC выше и протестировал его, загрузив файл. Он успешно сохранил файл по моему локальному пути. Однако у меня есть тот же код для ответа пользователю (и тот же URL-адрес контроллера MVC в консоли Twilio), но мой клиент обмена сообщениями получил «общий» ответ для настройки URL-адреса SMS номера из Twilio вместо тех, которые определены в моем контроллере. . Кроме того, у меня есть сообщение 11200 HTTP retrieval failure в журналах. Я позаботился о том, чтобы опубликовать все свои изменения, но я должен что-то упустить.
Может быть, в вашем коде чего-то не хватает, что может привести к неправильной работе AsyncAwait? Это может привести к некоторому странному поведению. Не стесняйтесь делиться кодом, используя Pastebin или что-то в этом роде.
Большое спасибо. Этот Gist — это то, чем я сейчас пользуюсь. Как я уже сказал, файлы извлекаются, но «соответствующий» ответ What did you want to know? (поскольку тела сообщения нет) не отправляется обратно. Кроме того, он не создает файл журнала, который я указал для устранения неполадок. Я отключил настраиваемые отчеты об ошибках ASP.NET (на данный момент), и когда я углубляюсь в ошибку на консоли Twilio, я вижу в ответе сообщение с указанием Username can not be null.
Я продолжу отвечать в Gist, а не здесь, поскольку ошибки больше не связаны с исходным вопросом.
Спасибо. Я также связался со службой поддержки и получил предложение использовать платформу Studio для некоторых других моих требований к реализации, но я все еще рассматриваю эту сборку, поскольку у меня все «на месте».