How to best implement simple crash / error reporting? - python

What would be the best way to implement a simple crash / error reporting mechanism?
Details: my app is cross-platform (mac/windows/linux) and written in Python, so I just need something that will send me a small amount of text, e.g. just a timestamp and a traceback (which I already generate and show in my error dialog).
It would be fine if it could simply email it, but I can't think of a way to do this without including a username and password for the smtp server in the application...
Should I implement a simple web service on the server side and have my app send it an HTTP request with the info? Any better ideas?

The web service is the best way, but there are some caveats:
You should always ask the user if it is ok to send error feedback information.
You should be prepared to fail gracefully if there are network errors. Don't let a failure to report a crash impede recovery!
You should avoid including user identifying or sensitive information unless the user knows (see #1) and you should either use SSL or otherwise protect it. Some jurisdictions impose burdens on you that you might not want to deal with, so it's best to simply not save such information.
Like any web service, make sure your service is not exploitable by miscreants.

I can't think of a way to do this without including a username and password for the smtp server in the application...
You only need a username and password for authenticating yourself to a smarthost. You don't need it to send mail directly, you need it to send mail through a relay, e.g. your ISP's mail server. It's perfectly possible to send email without authentication - that's why spam is so hard to stop.
Having said that, some ISPs block outbound traffic on port 25, so the most robust alternative is an HTTP POST, which is unlikely to be blocked by anything. Be sure to pick a URL that you won't feel restricted by later on, or better yet, have the application periodically check for updates, so if you decide to change domains or something, you can push an update in advance.
Security isn't really an issue. You can fairly easily discard junk data, so all that really concerns you is whether or not somebody would go to the trouble of constructing fake tracebacks to mess with you, and that's a very unlikely situation.
As for the payload, PyCrash can help you with that.

The web hit is the way to go, but make sure you pick a good URL - your app will be hitting it for years to come.

PyCrash?

Whether you use SMTP or HTTP to send the data, you need to have a username/password in the application to prevent just anyone from sending random data to you.
With that in mind, I suspect it would be easier to use SMTP rather than HTTP to send the data.

Some kind of simple web service would suffice. You would have to consider security so not just anyone could make requests to your service..
On a larger scale we considered a JMS messaging system. Put a serialized object of data containing the traceback/error message into a queue and consume it every x minutes generating reports/alerts from that data.

Related

What's the best way to setup a google smtp server for noreply E-Mails sent from a Python application?

We are currently developing a python program that as part of its functionality sends noreply E-Mails to customers whenever something important happens. For testing we are sending them from a free noreply#gmail.com address using pythons smtplib library and that works without problems so far.
However when going live we want to change the address to a proper noreply#company.com address. We are already using Google workspaces and have user accounts with company E-Mails. But while reading up on how to get that to work I came across multiple guides and articles which were either confusing, outdated or don't really do what I was hoping for. So I have a few questions that I hope you could answer.
Do I have to create a new user account just for the noreply mails? I have read about aliases and groups but I am not sure that this is the right way to do it since the mails shouldn't be sent from a renamed existing user account. I'd rather not set up a user just for sending E-Mails.
How many mails can I send when it is all set up? Free accounts can send 500 daily, workspace users have 2000, up to 10000 with smtp relay (if that's possible)? If the program ever exceeds this limit is there any way to increase it or should I already look for an alternative.
Finally how do I set this up? Most guides are for the old Gsuite. I feel like there should be an easy way to set this up that I am missing. All I'm looking for is creating a generic noreply#company.com address for our project to programmatically send a higher amount of mails.
Thanks for the help.

How to verify client using a python flask API

I'm running python flask and have an end point say /api/secure.
Right now anyone can access it using Basic Auth over HTTPS.
In my case customers will use this to get their specific data.
The problem I have is that I don't know that the client that connects to this api is actually the customer we send the username/psw to.
So I have been googling this for awhile now and havn't found a good solution for it.
Since the client that connects will be a batchprogram (so no real user) then I guess oauth and json web tokens is not what I am after?
My idea could be that the client would supply a certificate in the request and that we on our end can compare this certificate with something we have saved when we setup the account for the customer.
I have been looking at mutual authentication like mutual-tls-with-python-flask-and-werkzeug but I'm not sure if this is the right way.
Is there a best practise how to handle this?

Django: Should sendgrid emails always be sent from Celery?

I'm using django-sendgrid-v5 and I read somewhere that it isn't good to send emails from the main webserver. Should I process emails from Celery? Or is it fine to call from the main app since I'm using an external service like Sendgrid anyways?
I don't know in which context you've read that, but I would guess it has something to do with reliability, spam and security in general.
Short answer: Yes, this should be fully okay as you are using an external email service.
Another option is to set up a Smart host on your webserver and let your main email server deliver it to the final recipients.
Long answer: Nowadays sending emails from a (web)server, which is not fully set up as an email server might be difficult in means of reliably sending emails.
Due to the massive amounts of spam and malware sent, most (or at least a lot) receiving email servers (Mail Exchangers) are trying to check if the emails they should deliver to their users, are legit.
This is done by several settings mostly on the server itself. To name only a few: RDNS, DKIM, Greylisting, etc.
In general a (web) server whos main purpose is not sending emails, does not have all these settings. This might result in difficulties to reach certain email addresses.

Sending from gmail with smtplib

I'm attempting to use smtplib to set up a python script that will email out alert notifications. I don't need anything fancy, so I figured I'd stick with the basics and use SMTP for my messages. Following one of the many available online examples, my attempt to do so begins
server = smtplib.SMTP('smtp.gmail.com:587')
server.starttls()
server.login('username','password')
but at this point fails with an SMTPAuthenticationError 534, telling me to log on via my web browser. When I so, gmail has emailed me saying the sign in failed because it came from "an app that doesn't meet modern security standards."
I've seen some people having similar problems solved by changing their gmail account to accept logon from less secure apps, but did this myself and continued to get the same error message.
So is plain old SMTP not going to cut it and I need to get fancy? What am I doing wrong, or what can I do instead to make this work?
As it turns out, my attempts to set gmail to accept logon from less secure apps had (for whatever reason) not taken the first time I tried. Going to https://myaccount.google.com/security?pli=1 and turning this setting on allowed me to access successfully.
The comments pointing me towards oauth2 and app passwords are most helpful though, and I now that I've accomplished the bare bones I may look into those for more robust long-term approaches. Thank you!

Spotify without Redirect URI?

I'm using Spotipy to get some spotify data from an authorized user but I can't understand how to authorize my account.
Am I correct in thinking that a server is required that hosts something at http://www.myapp.com/callback ? What needs to be returned? Maybe I'm completely missing something here... I'm very confused by the whole required redirect URI thing...
I am trying to make a program, without website, so how should I handle authorization? What exactly should the redirect URI do?
Thanks
Edit:
Using http://localhost:8888/callback as my redirect URI now and that works. I'm not even sure why since nothing is running on that port.
Disclaimer: I know nothing about Spotify's API. But I have worked with similar APIs in the past (or even designed them). What I assume is that they use some kind of OpenID/OAuth authorization mechanism.
The very nature of these APIs is that they work through the browser! The idea is that MyApp doesn't have your actual Spotify credentials, but instead some signed token it can use.
To communicate this token to the MyApp, there are the server-callbacks, outlined in your question. Because all the browser can do is to redirect to a special URL you provide, with some info added.
So there are conceptually two ways to deal with this:
the easy, server-based one: you in fact register a myapp.com. When your app tries to authorize with spotify, it first creates a unique resource (myapp.com/authrequests/HASH-NUMBER), and communicates this as callback. Then it goes through the motions of making spotify authorize it, and once these are finished, there will have been a call to myapp.com/authrequests/HASH-NUMBER/ADDITIONAL-INFO. So while your app is waiting for this to happen, it has to poll (or open a websocket and listen to that) myapp.com. Complicated? Wait, it gets better!
the harder, OS-dependent one: you write an application that registers itself as protocol-provider with your browsers. E.g. my company does that with the protocol "ableton". Thus we can make the browser generate "ableton://AUTHORIZATION-REQUEST-RESULT" URLs which will then be communicated through Browser and OS to the running application, and thus you receive the necessary secret.
HTH

Categories

Resources