I'm new to Twilio and I am trying to send and receive sms via python. Here is my code
import os
from twilio.rest import TwilioRestClient
from twilio import twiml
from flask import Flask, request, redirect
app = Flask(__name__)
port = int(os.environ.get('PORT', 5000))
# put your own credentials here
ACCOUNT_SID = "..."
AUTH_TOKEN = "..."
client = TwilioRestClient(ACCOUNT_SID, AUTH_TOKEN)
def respond (recipient, twilio_account, body):
message = client.messages.create(
to=recipient,
from_=twilio_account,
body=body,
)
#app.route('/sms', methods=['POST'])
def receive_sms():
number = request.form['From']
body = request.form['Body']
# print "Message received from {0} saying {1}".format(number, body)
response_message = "Message received from {0} saying {1}".format(number, body)
resp = twiml.Response()
resp.message(response_message)
return str(resp)
if __name__ == '__main__':
app.run(debug=True, host="0.0.0.0", port=port)
I keep getting a 11200 error everytime I text my Twilio number. What is happening?
This error indicates that Twilio didn't receive a response from your code within 15 seconds.
I don't see any reason your code would run slowly, but Twilio may not be able to access it at all. Have you taken any steps to let requests into your local network from the Internet?
One useful strategy is to use something like ngrok while you're still in development to tunnel traffic in from the outside world. After installing ngrok you can run
ngrok http 5000
to tunnel traffic in to your localhost port 5000. Then configure Twilio to connect to the ngrok tunnel.
Related
This question already has an answer here:
aiosmtpd - python smtp server
(1 answer)
Closed 3 months ago.
I had "successfully" made an SMTP server. The code works fine connecting to SMTP clients. But it is neither able to recieve emails nor send it. I tried with various test servers and also the standard gmail/yahoo etc.
Here is the code:
# Copyright 2014-2021 The aiosmtpd Developers
# SPDX-License-Identifier: Apache-2.0
import asyncio
from asyncio.base_events import Server
import logging
import aiosmtpd
from aiosmtpd.controller import DEFAULT_READY_TIMEOUT, Controller
import ssl
from aiosmtpd.smtp import Envelope, Session
from smtplib import SMTP as SMTPCLient
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain('cert.pem', 'privkey.pem')
class ExampleHandler():
async def handle_RCPT(self, server, session, envelope, address, rcpt_options):
if address.endswith('#example.com'):
print('not relaying to that domain bro :(')
return '550 not relaying to that domain'
envelope.rcpt_tos.append(address)
print(address+" "+"is added to rcpt_tos")
# Make an envelope for the recipient with the same content.
return '250 OK'
# async def handle_EHLO(self, server, session, envelope):
# print('EHLO from %s' % envelope.mail_from)
# return '250-Hello, how are you?\n250-I am fine\n250 HELP'
async def handle_DATA(self, server, session, envelope):
print('Message from %s' % envelope.mail_from)
print('Message for %s' % envelope.rcpt_tos)
print('Message data:\n')
for ln in envelope.content.decode('utf8', errors='replace').splitlines():
print(f'> {ln}'.strip())
print()
print('End of message')
# Dump the contents of envelope.content to a file.
fi=open('./mailbox/firstletter.txt','w')
fi.write(envelope.content.decode('utf8', errors='replace'))
fi.close()
# print everything in DATA.
# Send the envelope to the recipient.
return '250 Message will be delivered'
#Define Relay server.
async def amain(loop):
cont = Controller(ExampleHandler(),hostname='x.x.x.x', port=25, server_hostname='Galam Limited',ready_timeout=5000)
# Combining ExampleHandler and Controller into a single Controller.
cont.start()
if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG)
loop = asyncio.get_event_loop()
loop.create_task(amain(loop=loop))
try:
loop.run_forever()
except KeyboardInterrupt:
pass
You can test the server reachability . I am stuck and spent 2 whole days to no avail. The issue is definetely not connectivity, I put the port 25 open. Made sure there are no external issues with godaddy either. Any help will be appreicated.
Edit:1
A quick peak at the wire shark data shows absolutely no packet is being transmitted to the outside when I run the client script.
Here is the clinet script I used for testing.
from smtplib import SMTP as Client
from aiosmtpd.controller import Controller
class controller:
hostname='192.168.1.33'
port=25
client = Client(controller.hostname, controller.port)
r = client.sendmail('a#galam.in', ['tester#192.168.1.200'], """\
From: Anne Person <anne#galam.in>
To: Bart Person <tester#192.168.1.200>
Subject: A test
Message-ID: <ant>
Hi Bart, this is Anne.
""")
SMTP 250 code means that a successful connection has been established however the remote host you are sending mails to might have categorized the domain the mail is being sent from as not legitimate.
This can happen if your domain is not authenticated/verified.
You can relay your messages through a trusted SMTP service like sendgrid
You can also check if your domain is verified by sending a mail from your service to check-auth#verifier.port25.com. Port25 is an automated tool that verified your DNS records, SPF records etc.
Hope this works for you!
I have set up a tornado HTTP server which is working as a proxy server.
I am using the python requests library to use it as a proxy server.
When I try to fetch HTTP url's with it, it works fine. But it isn't intercepting HTTPS requests.
The proxy server part:
class ProxyServer(HTTPServerConnectionDelegate):
def start_request(self, server_conn, request_conn):
print('In start request')
return ClientDelegator(request_conn)
def on_close(self):
pass
def client_send_error(self):
self.write('Error happened.')
self.finish()
def main():
server = HTTPServer(ProxyServer())
server.bind(8888)
server.start(0)
tornado.ioloop.IOLoop.current().start()
if __name__ == "__main__":
main()
The requests part:
import requests
url = 'https://example.com'
proxy = {'http' : '127.0.0.1:8888'}
r = requests.get(url, proxies=proxy, verify=False)
print(r.text)
When I use http://example.com, the connection starts as 'In start request' gets printed. However, when I use https://example.com then the connection doesn't start. The ProxyServer doesn't enter start_request.
What am I doing wrong?
Your proxy variable only specifies a proxy for http, not https. You need to set the proxy for both protocols separately.
Am trying to generate a get request from a flask server to another, on destination side when I print the port, I keep getting random ports with each request
CLIENT:
from flask import Flask, redirect, request
import requests
app = Flask(__name__)
#app.route('/acqlock/<resource_name>')
def acquire_resource(resource_name):
print request.url
response = requests.get('http://127.0.0.1:8080/acqlock/' + resource_name)
return response.text
if __name__ == "__main__":
app.run(host="localhost", port=8081)
SERVER :
from flask import Flask, redirect, request
app = Flask(__name__)
#app.route('/')
#app.route('/acqlock/<resource_name>')
def acquire_lock(resource_name):
print request.url
print request.environ.get('REMOTE_PORT')
if __name__ == "__main__":
app.run(port=int("8080"))
it keeps printing http://127.0.0.1:8080/acqlock/file 58077 eventhough I was expecting it to print http://127.0.0.1:8081 8081 as the server is generating the request
This is normal. Remember that requests is the client here, it has to create a new HTTP connection to another server. TCP connections on the client side need a port as well, and when you create a socket to a remote server you are assigned a port number by the OS for the client-side of the connection.
That you are making this outgoing HTTP connection in the context of an incoming HTTP connection is neither here nor there. It is a different connection, in a different direction.
If you need to identify where the request came from, add information to the request. You can add custom headers, a cookie, query parameters, or post data.
I have written this HTTP web server in python which simply sends reply "Website Coming Soon!" to the browser/client, but I want that this web server should sends back the URL given by the client, like if I write
http://localhost:13555/ChessBoard_x16_y16.bmp
then server should reply back the same url instead of "Website Coming Soon!" message.
please tell how can I do this?
Server Code:
import sys
import http.server
from http.server import HTTPServer
from http.server import SimpleHTTPRequestHandler
#import usb.core
class MyHandler(SimpleHTTPRequestHandler): #handles client requests (by me)
#def init(self,req,client_addr,server):
# SimpleHTTPRequestHandler.__init__(self,req,client_addr,server)
def do_GET(self):
response="Website Coming Soon!"
self.send_response(200)
self.send_header("Content-type", "application/json;charset=utf-8")
self.send_header("Content-length", len(response))
self.end_headers()
self.wfile.write(response.encode("utf-8"))
self.wfile.flush()
print(response)
HandlerClass = MyHandler
Protocol = "HTTP/1.1"
port = 13555
server_address = ('localhost', port)
HandlerClass.protocol_version = Protocol
try:
httpd = HTTPServer(server_address, MyHandler)
print ("Server Started")
httpd.serve_forever()
except:
print('Shutting down server due to some problems!')
httpd.socket.close()
You can do what you're asking, sort of, but it's a little complicated.
When a client (e.g., a web browser) connects to your web server, it sends a request that look like this:
GET /ChessBoard_x16_y16.bmp HTTP/1.1
Host: localhost:13555
This assumes your client is using HTTP/1.1, which is likely true of anything you'll find these days. If you expect HTTP/1.0 or earlier clients, life is much more difficult because there is no Host: header.
Using the value of the Host header and the path passed as an argument to the GET request, you can construct a URL that in many cases will match the URL the client was using.
But it won't necessarily match in all cases:
There may be a proxy in between the client and your server, in which case both the path and hostname/port seen by your code may be different from that used by the client.
There may be packet manipulation rules in place that modify the destination ip address and/or port, so that the connection seen by your code does not match the parameters used by the client.
In your do_GET method, you can access request headers via the
self.headers attribute and the request path via self.path. For example:
def do_GET(self):
response='http://%s/%s' % (self.headers['host'],
self.path)
I am attempting to pass binary data over websockets, more specifically compressed strings over websockets. In my current setup I use tornado as the server with a websocket client transmitting the binary data. The binary data is formed by compressing the data with zlib. Both client and server are as simple as they get and are shown below.
Server:
import tornado.websocket
import tornado.httpserver
import tornado.ioloop
import tornado.web
class WebSocketServer(tornado.websocket.WebSocketHandler):
def open(self):
print 'OPEN'
def on_message(self, message):
print 'len = {}'.format(len(message))
print 'GOT MESSAGE: {}'.format(message.decode('zlib'))
def on_close(self):
print 'CLOSE'
app = tornado.web.Application([
(r'/', WebSocketServer)
])
http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(9500)
tornado.ioloop.IOLoop.instance().start()
Client:
import websocket
host = 'localhost'
port_ws = 9500
ws = websocket.create_connection('ws://{}:{}/'.format(host, port_ws))
message = 'this is my message'.encode('zlib')
print 'Length of message is {}'.format(len(message))
ws.send(message)
The client does not throw any errors, it prints out that the message: Length of message is 24. The message is encoded as a str as per the zlib standard. The server on the other end does not show that it received any messages, it just understands that a client had connected, and then disconnected. Does anyone know where the problem is? I am not sure if the problem lays within tornado or the websockets library. Any suggestions?
EDIT: In response to the comment below (#plg), I modified the scripts above to show that:
Non-encoded messages can be send from client to the tornado server
Tornado can reply with an encoded message
Server:
import tornado.websocket
import tornado.httpserver
import tornado.ioloop
import tornado.web
class WebSocketServer(tornado.websocket.WebSocketHandler):
def open(self):
print 'OPEN'
def on_message(self, message):
print 'len = {}'.format(len(message))
print 'GOT MESSAGE: {}'.format(message)
self.write_message(message.encode('zlib'))
def on_close(self):
print 'CLOSE'
app = tornado.web.Application([
(r'/', WebSocketServer)
])
http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(9500)
tornado.ioloop.IOLoop.instance().start()
Client:
import websocket
host = 'localhost'
port_ws = 9500
ws = websocket.create_connection('ws://{}:{}/'.format(host, port_ws))
#message = 'this is my message'.encode('zlib')
message = 'this is my message'
print 'Length of message is {}'.format(len(message))
ws.send(message)
assert ws.recv().decode('zlib') == message
The system works just fine. The assert does not throw an error. The decoded message matches the send message. So I guess there is a problem with either:
Sending an encoded message from the client
Tornado receiving encoded messages
To be quite honest, I do believe that the first option is more probable than tornado. In my opinion, I believe tornado would alert me if an incoming message is not properly decoded as per the websocket standard. Any more suggestions?
EDIT: More development on who is at fault. Instead of using my own server to relay back and fourth my connection, I relayed the connection to ws://echo.websocket.org/. My testing application is as shows:
import websocket
host = 'localhost'
port_ws = 9500
ws = websocket.create_connection('ws://echo.websocket.org/')
message = 'this is my message'
ws.send(message.encode('zlib'))
got = ws.recv().decode('zlib')
print 'GOT: {}'.format(got)
assert got == message
This actually passed the test, the data was received just fine. So I guess there is something wrong with tornado receiving the data?
After looking though the source code of the websocket library, I found that by default it is formatting the packets as text. By changing the line:
ws.send('message')
# to:
ws.send('message', opcode=websocket.ABNF.OPCODE_BINARY)
# or better yet:
ws.send_binary('message')
The packet will be sent over just fine. Tornado I guess was just ignoring the fake binary packets since they were marked as text and contained binary.
Thanks to this commit tornado supports websocket compression extensions.