Why does the Python script to send data to Slack web hook not work when variable is pulled from a line? - python-2.7

Language: Python 2.7
Hello all. I found a really helpful script here: Python to Slack Web Hook
that shows how to send messages to a Slack web hook.
import json
import requests
# Set the webhook_url to the one provided by Slack when you create the webhook at https://my.slack.com/services/new/incoming-webhook/
webhook_url = 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX'
slack_data = {"text": "<https://alert-system.com/alerts/1234|Click here> for details!"}
response = requests.post(
webhook_url, data=json.dumps(slack_data),
headers={'Content-Type': 'application/json'}
)
if response.status_code != 200:
raise ValueError(
'Request to slack returned an error %s, the response is:\n%s'
% (response.status_code, response.text)
)
It works flawlessly when I run .py file.
Now, I have a file that has many lines of messages that I want to send to Slack. I have it formatted correctly already in the file, no spaces etc.. It's just a matter of grabbing it and passing it so slack_data = line1 etc..
So, I modify the file with something like this:
with open('export.txt', 'r') as e:
for line in e:
slack_data = line
Now if I do a print slack_data right after that, the information returns on the screen exactly as it should be, so I'm thinking it's good. I haven't began to get it working for each line yet, because it's not even working on the first line.
I get an invalid payload 400 when I run it.
EDIT: Slack support said the what they were receiving has escape characters inserted into for some reason.
"{\"text\": \"<https://alert-system.com/alerts/1234|Click here> for details!"}\n"
Any direction or assistance is appreciated.
Thanks!!

Just posting as it might help somebody. For me the below snippet worked:
data = json.dumps(slack_data)
response = requests.post(
URL, json={"text": data},
headers={'Content-Type': 'application/json'}
)
As #Geo pointed out the final payload that we are going to send should have keyword "text", else it will fail.
Moreover, in post method I have to replace data= with json= else it kept throwing error for invalid payload with 400

Since I already had the data preformatted in the file as JSON already, it was just a matter of removing json.dumps out of the code.
OLD:
#response = requests.post(webhook_url, data=json.dumps(slack_data), headers={'Content-Type': 'application/json'})
NEW:
response = requests.post(webhook_url, data=slack_data, headers={'Content-Type': 'application/json'})
Once I did that, everything worked like a charm.

If you change the code to this:
with open('export.txt', 'r') as e:
slack_data = e.read()
do you still get the 400?

Related

pytest-django how test excel response [duplicate]

Right now I'm just checking the response of the link like so:
self.client = Client()
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
Is there a Django-ic way to test a link to see if a file download event actually takes place? Can't seem to find much resource on this topic.
If the url is meant to produce a file rather than a "normal" http response, then its content-type and/or content-disposition will be different.
the response object is basically a dictionary, so you could so something like
self.assertEquals(
response.get('Content-Disposition'),
"attachment; filename=mypic.jpg"
)
more info:
https://docs.djangoproject.com/en/dev/ref/request-response/#telling-the-browser-to-treat-the-response-as-a-file-attachment
UPD:
If you want to read the actual contents of the attached file, you can use response.content. Example for a zip file:
try:
f = io.BytesIO(response.content)
zipped_file = zipfile.ZipFile(f, 'r')
self.assertIsNone(zipped_file.testzip())
self.assertIn('my_file.txt', zipped_file.namelist())
finally:
zipped_file.close()
f.close()

Python : urllib2 put request returns 301 error

I'm trying to make a put request via the urllib2 module of Python 2.7. When I perform a GET it works just fine but when I try to turn it into a PUT it returns me a 301 http error.
My code is above :
opener = urllib2.build_opener(urllib2.HTTPHandler)
req = urllib2.Request(reqUrl)
base64string = base64.encodestring('%s:%s' % (v_username, v_password)).replace('\n', '')
req.add_header("Authorization", "Basic %s" % base64string)
req.add_header("Content-Type", "application/rdf+xml")
req.add_header("Accept", "application/rdf+xml")
req.add_header("OSLC-Core-Version", "2.0")
req.get_method = lambda: 'PUT'
req.allow_redirects=True
url = opener.open(req)
If I suppress the line
req.get_method = lambda: 'PUT'
it works but it's a get request (or a post if I pass some data) but it has to be a PUT and I don't how to do it differently with this module.
The error is
urllib2.HTTPError: HTTP Error 301: Moved Permanently.
Does anyone understand this more than I do? I'm quite a newbie with REST request and there are some specificity that remains obscure to me.
I'm not certain, but could it be that urllib is handling the 301 automatically for the GET but not for the PUT? According to the RFC, user agents can redirect GETs automatically, but not PUTs.
This page seems to suggest that urllib does indeed handle the 301 redirection automatically, and it seems plausible it wouldn't automatically handle the PUT redirect given the RFC. Guess you should find out what the redirect is to and redirect there.
Thanks Ken F, you helped me understand the problem. I changed the handler directly in the urllib2.py file (not sure if it's very clean but whatever) so it can handle PUT requests:
if (code in (301, 302, 303, 307) and m in ("GET", "HEAD")
or code in (301, 302, 303) and m in ("POST", "PUT")):
Indeed, when the request was neither GET nor POST, it automatically raised an error. I'm surprised I couldn't find anyone else with the same issue.

Mandrill python API attachment error message

I'm writing a web app for customer/order handling in python with asana integration.
For a registered incoming order, an invoice is created as .pdf. This file I want to send to asana as an email attachment using mandrill, because the asana python API doesn't provide attachments yet.
Because mandrill wants the content of the attachment as a base64-encoded string, I create a binary of the pdf using this function:
def binaryFile(self, pathToFile):
binary_obj = xmlrpclib.Binary( open(pathToFile).read() )
return binary_obj
Together with the path of the file, I throw this into mandrill like so:
'attachments': [{'content': binaryFile,
'name': pathOfFile,
'type': 'application/pdf'}]
When I try to send the whole thing, this is what I get:
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site- packages/mandrill.py", line 1215, in send
return self.master.call('messages/send', _params)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mandrill.py", line 131, in call
params = json.dumps(params)
OverflowError: Overlong 3 byte UTF-8 sequence detected when encoding string
Who can hint at what I am doing wrong?
Thank you.
All right ok, I found the mistake myself, it's in the base64-encoding of course. I'm now doing it like so:
import base64
def filetobase64(self, inputfilename):
return base64.b64encode(open(inputfilename, 'rb').read())
Everything works fine now.
No harm meant!

Django to serve generated excel file

I looked at the various questions similar to mine, but I could not find anything a fix for my problem.
In my code, I want to serve a freshly generated excel file residing in my app directory in a folder named files
excelFile = ExcelCreator.ExcelCreator("test")
excelFile.create()
response = HttpResponse(content_type='application/vnd.ms-excel')
response['Content-Disposition'] = 'attachment; filename="test.xls"'
return response
So when I click on the button that run this part of the code, it sends to the user an empty file. By looking at my code, I can understand that behavior because I don't point to that file within my response...
I saw some people use the file wrapper (which I don't quite understand the use). So I did like that:
response = HttpResponse(FileWrapper(excelFile.file),content_type='application/vnd.ms-excel')
But then, I receive the error message from server : A server error occurred. Please contact the administrator.
Thanks for helping me in my Django quest, I'm getting better with all of your precious advices!
First, you need to understand how this works, you are getting an empty file because that is what you are doing, actually:
response = HttpResponse(content_type='application/vnd.ms-excel')
response['Content-Disposition'] = 'attachment; filename="test.xls"'
HttpResponse receives as first arg the content of the response, take a look to its contructor:
def __init__(self, content='', mimetype=None, status=None, content_type=None):
so you need to create the response with the content that you wish, is this case, with the content of your .xls file.
You can use any method to do that, just be sure the content is there.
Here a sample:
import StringIO
output = StringIO.StringIO()
# read your content and put it in output var
out_content = output.getvalue()
output.close()
response = HttpResponse(out_content, mimetype='application/vnd.ms-excel')
response['Content-Disposition'] = 'attachment; filename="test.xls"'
I would recommend you use:
python manage.py runserver
to run your application from the command line. From here you will see the console output of your application and any exceptions that are thrown as it runs. This may provide a quick resolution to your problem.

Djrill throwing 'TypeError' when send_mail method is used

I am currently trying to integrate mandrill into this Django-based website for emails. Djrill is the recommended package for Django and sits in place of the default SMTP/email backend, passing emails through to a Mandrill account.
When I try to test that this new backend is working by running this command:
send_mail('Test email', body, 'noreply#*********.com', [user.email], fail_silently=False)
It throws the following error: http://pastebin.ca/2239978
Can anybody point me to my mistake?
Update:
As #DavidRobinson mentions in a comment, you are not getting a successful response from the mandrill API authentication call. You should double check your API key.
If that is correct, try using curl to post {"key": <your api key>, "email": <your from email>} to MANDRILL_API_URL + "/users/verify-sender.json" and see if you get a 200.
Something like this:
curl -d key=1234567890 -d email=noreply#mydomain.com http://mandrill.whatever.com/user/verify-sender.json
Original answer:
There is also an issue in Djrill that prevents a useful error message from propagating up. That last line of the stack trace is the problem.
This is the entire open method taken from the source:
def open(self, sender):
"""
"""
self.connection = None
valid_sender = requests.post(
self.api_verify, data={"key": self.api_key, "email": sender})
if valid_sender.status_code == 200:
data = json.loads(valid_sender.content)
if data["is_enabled"]:
self.connection = True
return True
else:
if not self.fail_silently:
raise
See how it just says raise without an exception argument? That syntax is only allowed inside an except block, and raises the exception currently being handled. It doesn't work outside an except block.
An open issue in Djrill mentions a send failure and links a fork that supposedly fixes it. I suspect Djrill isn't well supported and you might try that fork or another solution entirely.