how to send json header in websocket tornado python? - python-2.7

def on_message(self, message):
for client in ChatWebSocket.clients:
print(client)
t=json.loads(message)
client.write_message(json.dumps('Content-type:application/json\n'))
client.write_message(json.dumps({'a':t['b']}))
print(t['b'])
the problem is client is accepting it like a normal string and not a header
please help

From Tornado's documentation:
WebSocketHandler.write_message(message, binary=False)
Sends the given message to the client of this Web Socket.
The message may be either a string or a dict (which will be encoded as json). If the binary argument is false, the message will be sent as utf8; in binary mode any byte string is allowed.
So you don't need to dump anything. Just send the dict as is and Tornado will encode it as JSON anyways:
false, the message will be sent as utf8; in binary mode any byte string is allowed.
So you don't need to dump anything. Just send the dict as is and Tornado will
def on_message(self, message):
for client in ChatWebSocket.clients:
print(client)
t = json.loads(message)
client.write_message({'a': t['b']})
print(t['b'])

Related

Send emails by reading email address from S3

I am trying the following -
Read the email address from a csv file in S3, first column has email address, second column has the subject, third column has the body of the email.
Send email with the subject and body to the email address read from S3.
I was able to read the file in S3 into a DF using Lambda, but unable to send the email. Any ideas on how to do this using AWS services
you can use same lambda function to create smtp server of your own to send emails. e.g. while parsing data from the S3 csv file, for each entry in csv send email.
#!/usr/bin/env python
import smtplib
from email.mime.text import MIMEText
sender = 'xx#xx.com' # parsed data
receivers = ['yy#yy.com'] # parsed data
port = 1025
msg = MIMEText('email text') # parsed data
msg['Subject'] = 'Test mail'
msg['From'] = sender
msg['To'] = receivers
with smtplib.SMTP('localhost', port) as server:
server.sendmail(sender, receivers, msg.as_string())
print("email sent")
You can send emails from within a Lambda function by invoking the SES service. There is an example of creating a Lambda function (implemented in Java) that shows how to send an email message as part of a larger workflow created using AWS Step Functions. See this example:
Create AWS serverless workflows by using the AWS SDK for Java

Missing form data in request

I have following code
class MyClass(restful.Resource):
def get(self):
headers = {'Content-Type': 'text/html'}
return make_response(render_template('myfile.html'),200,headers)
def post(self):
session['CONSUMER_KEY']=request.form.get('consumer_key')
session['CONSUMER_SECRET']=request.form.get('consumer_secret')
render_template('myfile.html')
api.add_resource(MyClass,"/mag/",endpoint="mag")
I have written following test:
def mytest(self):
content_type={"Content-Type": "application / x - www - form - urlencoded","Content-Disposition": "form-data"}
response = self.client.post(
api.url_for(MyClass), data = json.dumps({'consumer_key':'testconsumerkey',
'consumer_secret':'testconsumersecret'}),
headers=content_type
)
The issue is form data is blank and thats the values are not getting set in session. When i debug i see that request.data is populated but request.form is an empty dictionary. Can someone suggest how I can send form data in a post request from a test
EDIT: Environment details
Python 2.7, Flask web framework, self.client is . I am using flask.ext.testing
You seem to be confused as to what the expected format for the post body should be. Should it be JSON data (which is what you send in the test case), or should it be in the application/x-www-form-urlencoded format (which is what you claim to send in the test case, and what the endpoint will read)?
If you wish to receive JSON data, you'll need to change the endpoint to read the data from request.get_json(). You'll also need to use application/json as the Content-Type header in the test case.
If you wish to receive urlencoded post data, then just simplify the test case by removing the Content-Type header and the json.dumps. Just pass the data dict to the data argument.

Sending message to server using python SocketIO

I have a situation where I have a python client try to send a message to a server using SocketIO. I'm using sock.emit to send a json message as shown below
sock = SocketIO(url, None, ...)
message = {'ob': 'house',
'ids': ['54fjadb70f9756','39f1ax451f6567']}
self.sock.emit(message)
server expects the follow:
{"ob":"house","ids":['54fjadb70f9756','39f1ax451f6567']}
the server is current receive the following message:
{"args": [], "name": "{\"ids\": [\"54fjadb70f9756\", \"39f1ax451f6567\"], \"ob\": \"house\"}"}
then complains about an invalid message.
How would I send the message so that the server receives it as expected i.e which the original message structure I specified? it seems emit is changing the structure of the message when I send it, is it possible to override and change emit to that it retain the original message structure? is so how would I do that?
Socket.io .emit() takes two arguments. The first argument is a message name which should be a plain string. The second argument is optional and can be data which will be JSON encoded data.
So, you are trying to send your data as the message name. That will not work. You need to create a message name and send the data as the argument for that message name.
sock = SocketIO(url, None, ...)
message = {'ob': 'house',
'ids': ['54fjadb70f9756','39f1ax451f6567']}
sock.emit("someMessageName", message)
Then, on the server, you need to have a listener for that specific message name and then you can receive the data when that message listener is invoked.

Is there any nicer way to get the full message from gmail with google-api

I'm working on a project where I, among other things, need to read the message in e-mails from my google account. I came up with a solution that works but wonder if there are any simpler ways?
The first part of the code is pretty standard to get access to the mailbox. But I post it so you can see what I did to get it to work.
SCOPES = 'https://www.googleapis.com/auth/gmail.modify'
CLIENT_SECRET ='A.json'
store =file.Storage('storage.json')
credz=store.get()
flags = tools.argparser.parse_args(args=[])
if not credz or credz.invalid:
flow = client.flow_from_clientsecrets(CLIENT_SECRET,SCOPES)
if flags:
credz = tools.run_flow(flow, store, flags)
GMAIL = build('gmail','v1',http=credz.authorize(Http()))
response = GMAIL.users().messages().list(userId='me',q='').execute()
messages = []
if 'messages' in response:
messages.extend(response['messages'])
print len(messages)
while 'nextPageToken' in response:
page_token = response['nextPageToken']
response = service.users().messages().list(userId='me', q=query,pageToken=page_token).execute()
messages.extend(response['messages'])
FromMeInd=0
for message in messages:
ReadMessage(GMAIL,'me',message['id'])
It is this part that I'm more interested to imporve. Is there any other way to more directly get the message with python and the gmail-api. I've looked through the api documentation but could not get any more efficient way to read it.
def ReadMessage(service,userID,messID):
message = service.users().messages().get(userId=userID, id=messID,format='full').execute()
decoded=base64.urlsafe_b64decode(message['payload']['body']['data'].encode('ASCII'))
print decoded
You can get the body as raw and then parse it using the standard Python email module
According to the official API: https://developers.google.com/gmail/api/v1/reference/users/messages/get:
import email
message = service.users().messages().get(userId='me', id=msg_id,
format='raw').execute()
print 'Message snippet: %s' % message['snippet']
msg_str = base64.urlsafe_b64decode(message['raw'].encode('ASCII'))
mime_msg = email.message_from_string(msg_str)
You'll get a mime message with a payload containing mime parts, e.g. plain text, HTML, quoted printable, attachments, etc.

Send login credentials to another server

I have two servers running django. I'll call one server my "logging" server and another my "client" server. The client server wants to log a message with the logging server by passing over a username, password, and message over the internet. With my current implementation I'm hitting an error when trying to decrypt the encrypted message, username, and password that was sent over the wire. It looks like I should be trying to decrypt a "byte string" according to the pycrypto documentation, but I can't seem to create a byte string correctly since I haven't been able to get around this problem. Also, it feels like my implementation is taking me down a rabbit hole of security vulnerabilities and codec confusion. Is there a package that I should look at which already implements this type of functionality? If so what would that implementation look like?
client:
from Crypto.Hash import MD5
from Crypto.PublicKey import RSA
from base64 import b64decode
import urllib2
import urllib
#I realize recreating the hash everytime is slow. I just included it here for simplicity.
logger_public_signature_message = "I am a client :)"
logger_public_signature_hash = MD5.new(logger_public_signature_message).digest()
client_private_key = #private key
logger_public_key = #public key
client_private = RSA.importKey(client_private_key)
client_public = client_private.publickey()
logger_public = RSA.importKey(logger_public_key)
message = "my message"
username = "user"
password = "password"
encrypted_message = logger_public.encrypt(message, "ignored_param")
encrypted_username = logger_public.encrypt(username, "ignored_param")
encrypted_password = logger_public.encrypt(password, "ignored_param")
signature = client_private.sign(logger_public_signature_hash, '')
params = { "message": encrypted_message, "username": encrypted_username, "password": encrypted_password, "signature": signature }
url_encoded_params = urllib.urlencode(params)
url = 'http://localhost:8000/url/to/logger/'
req = urllib2.Request(url, url_encoded_params)
logger:
from Crypto.Hash import MD5
from Crypto.PublicKey import RSA
from base64 import b64decode
def log(request):
#I realize recreating the hash everytime is slow. I just included it here for simplicity.
logger_public_signature_message = "I am a client :)"
logger_public_signature_hash = MD5.new(logger_public_signature_message).digest()
client_public_key = #client public key
logger_private_key = #logger private key
client_public = RSA.importKey(client_public_key)
logger_private = RSA.importKey(logger_private_key)
p = request.POST
encrypted_message = urllib2.unquote(p["message"])
encrypted_username = urllib2.unquote(p["username"])
encrypted_password = urllib2.unquote(p["password"])
signature = urllib2.unquote(p["signature"])
#I'm hitting exceptions when trying to decrypt the encrypted messages.
#The exceptions are: "ValueError: Message too large" I think the issue is that
#I'm trying to decrypt a base64 string where I should be trying to decrypt a byte
#string from reading the documentation. But I haven't been able I guess to correctly
#create a byte string because I can't get it to work.
decrypted_message = logger_private.decrypt(encrypted_message.encode("base64"))
decrypted_username = logger_private.decrypt(encrypted_username.encode("base64"))
decrypted_password = logger_private.decrypt(encrypted_password.encode("base64"))
verified = client_public.verify(logger_public_signature_hash, signature)
I think you are putting a lot of effort into stuff, that doesn't need to be handled by Django.
Here is what I would usually do:
Use HTTPS, as transport encryption layer
Use HTTP Basic Auth. Basic auth is implemented in urllib2 as well as requests.
But there is an even better solution: Django REST framework
It provides you will a full blown REST API including different authentication solutions.
If you need any help, setting up one of these options, let me know and I'll add an example.
May it be that you would use sentry for logging? Of course if it isn't task for training.
I look at the sentry since it been django application, and now it surely is excellent production-ready solution.
We're using it in banking-sphere software development.
You are very close to decrypting the values on the server. The result of the encryption on the client is a tuple. When you urllib2.unquote the items on the server, you then recreate tuples from them.
For example:
>>> c = public.encrypt('Hello', "ignored")
>>> c
('3\xae0\x1f\xd7\xe4b\xd4\xf1\xf4\x88!Be\xff!\x1e\xda\x82\x10\x9bRy\x0c\xa0v\xed\x84\xf9\xe35\xc6QG\xcf\xb7\x1b\xea\x9fe\t\x9b\x8d\xd6\xf3\x8cw\xde\x17\xb5\xf7\x9a+\x84i%#\x8a\xdf\xf4\xdd\xc8wY',)
which in your code you pack into params like this:
>>> params = { "message" : c }
>>> params
{'message': ('3\xae0\x1f\xd7\xe4b\xd4\xf1\xf4\x88!Be\xff!\x1e\xda\x82\x10\x9bRy\x0c\xa0v\xed\x84\xf9\xe35\xc6QG\xcf\xb7\x1b\xea\x9fe\t\x9b\x8d\xd6\xf3\x8cw\xde\x17\xb5\xf7\x9a+\x84i%#\x8a\xdf\xf4\xdd\xc8wY',)}
>>> urllib.urlencode(params)
'message=%28%273%5Cxae0%5Cx1f%5Cxd7%5Cxe4b%5Cxd4%5Cxf1%5Cxf4%5Cx88%21Be%5Cxff%21%5Cx1e%5Cxda%5Cx82%5Cx10%5Cx9bRy%5Cx0c%5Cxa0v%5Cxed%5Cx84%5Cxf9%5Cxe35%5Cxc6QG%5Cxcf%5Cxb7%5Cx1b%5Cxea%5Cx9fe%5Ct%5Cx9b%5Cx8d%5Cxd6%5Cxf3%5Cx8cw%5Cxde%5Cx17%5Cxb5%5Cxf7%5Cx9a%2B%5Cx84i%25%40%5Cx8a%5Cxdf%5Cxf4%5Cxdd%5Cxc8wY%27%2C%29'
I would guess that urllib2.unquote(p["message"]) returns this (but I did not try this):
"('3\\xae0\\x1f\\xd7\\xe4b\\xd4\\xf1\\xf4\\x88!Be\\xff!\\x1e\\xda\\x82\\x10\\x9bRy\\x0c\\xa0v\\xed\\x84\\xf9\\xe35\\xc6QG\\xcf\\xb7\\x1b\\xea\\x9fe\\t\\x9b\\x8d\\xd6\\xf3\\x8cw\\xde\\x17\\xb5\\xf7\\x9a+\\x84i%#\\x8a\\xdf\\xf4\\xdd\\xc8wY',)"
then you can recreate the tuple at the server like this (m is the unquoted message):
>>> from ast import literal_eval
>>> literal_eval(m)
('3\xae0\x1f\xd7\xe4b\xd4\xf1\xf4\x88!Be\xff!\x1e\xda\x82\x10\x9bRy\x0c\xa0v\xed\x84\xf9\xe35\xc6QG\xcf\xb7\x1b\xea\x9fe\t\x9b\x8d\xd6\xf3\x8cw\xde\x17\xb5\xf7\x9a+\x84i%#\x8a\xdf\xf4\xdd\xc8wY',)
once you have the tuple back, you can decrypt it:
>>> private.decrypt(literal_eval(m))
'Hello'
It would be better to find a vetted and standard mechanism to do this rather than roll your own. For example, in your scheme, I could capture different messages between the client and server, and then mix and match messages and username/password pairs, making it appear that the messages came from different users.
However, with just this minor tweak (recreating the tuples from the "unquoted" strings) your code should decrypt just fine.