smtplib, 'tuple' object has no attribute 'encode' - python-3.x

I am out of ideas how to solve this. I checked most smtplib threads and those about " AttributeError: 'tuple' object has no attribute 'encode'"
I am trying to create message template to send emails from Python3 script. For some reason, when I added message template I cannot fix that in any way.
import smtplib
import additional
import datetime
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
#server commends
server = smtplib.SMTP('smtp.gmail.com', 587)
server.ehlo()
server.starttls()
server.ehlo()
#credentials of sender
FROM = "xxx.gmail.com"
PASSWORD = additional.x #hidden password in other .py file
#logging in
server.login(FROM, PASSWORD)
#template for recievers
TOADDR = ["reciever email"]
CC = ["FIRST CC", "2ND CC"]
SUBJECT = "testing"
TEXT = "Let's check if this works and I joined everything correctly"
#MSG template
FINAL_TO = CC + [TOADDR]
message = MIMEMultipart()
message['From'] = "Michal", FROM
message['To'] = TOADDR
message['Cc'] = ", ".join(CC)
message['Subject'] = SUBJECT
message.attach(MIMEText(TEXT))
MSG = message.as_string()
#Join reciever with CC
FINAL_TO = CC + [TOADDR]
server.sendmail(FROM, FINAL_TO, MSG)
TIME = datetime.datetime.now()
print("Email sent at {}".format(TIME))
As mentioned above, my output is :
Traceback (most recent call last):
File "/home/galander/Desktop/sending email/app.py", line 39, in <module>
MSG = message.as_string()
File "/usr/lib/python3.6/email/message.py", line 158, in as_string
g.flatten(self, unixfrom=unixfrom)
File "/usr/lib/python3.6/email/generator.py", line 116, in flatten
self._write(msg)
File "/usr/lib/python3.6/email/generator.py", line 195, in _write
self._write_headers(msg)
File "/usr/lib/python3.6/email/generator.py", line 222, in _write_headers
self.write(self.policy.fold(h, v))
File "/usr/lib/python3.6/email/_policybase.py", line 326, in fold
return self._fold(name, value, sanitize=True)
File "/usr/lib/python3.6/email/_policybase.py", line 369, in _fold
parts.append(h.encode(linesep=self.linesep, maxlinelen=maxlinelen))
AttributeError: 'tuple' object has no attribute 'encode'

Headers on a mime message must be strings. You have assigned a tuple to From, and a list to To.
Make those strings too:
message['From'] = "Michal <{}>".format(FROM)
message['To'] = ', '.join(TOADDR)

Related

Why do I get this Python websocket Discord error?

I have a small python script that used to connect to Discord and it would print the author and their comment from the channels I am a member of. I now get an error when it tries to connect. Not sure how to find the connection error.
from fileinput import close
from locale import format_string
import websocket
import json
import threading
import time
import csv
import string
def send_json_request(ws, request):
ws.send(json.dumps(request))
def recieve_json_response(ws):
response = ws.recv()
if response:
return json.loads(response)
def heartbeat(interval, ws):
print("Heartbeat Begin")
while True:
time.sleep(interval)
heartbeatJSON = {
"op": 1,
"d": "null"
}
send_json_request(ws, heartbeatJSON)
print("Heartbeat Sent")
ws = websocket.WebSocket()
ws.connect("wss://gateway.discord.gg/?v=6&encording=json")
event = recieve_json_response(ws)
heartbeat_interval = event["d"]["heartbeat_interval"] / 1000
threading._start_new_thread(heartbeat, (heartbeat_interval, ws))
token = "token"
payload = {"op":2,"d": {"token":token, "properties": {"$os":"Linux","$browser":"Discord","$device": "Pi" }}}
send_json_request(ws, payload)
while True:
event = recieve_json_response(ws)
try:
author = event['d']['author']['username']
content = event['d']['content']
rows = [[author, content]]
if author in ["pebbles", "runner", "snapper"] :
print({event['d']['author']['username']}, {event['d']['content']})
with open('file.csv', 'a', newline='', encoding='UTF8') as csvfile:
writer = csv.writer(csvfile)
auth = author.casefold()
writer.writerow(rows)
op_code = event('op')
if op_code == 11:
print ("Heartbeat received")
except:
pass
I get the below when I run it. Hope someone can point me in the right direction.
Traceback (most recent call last):
File "c:\Users\seanj\Documents\Trading\main.py", line 52, in
event = recieve_json_response(ws)
File "c:\Users\seanj\Documents\Trading\main.py", line 17, in recieve_json_response
response = ws.recv()
File "C:\Users\seanj\AppData\Local\Programs\Python\Python310\lib\site-packages\websocket_core.py", line 359, in recv
opcode, data = self.recv_data()
File "C:\Users\seanj\AppData\Local\Programs\Python\Python310\lib\site-packages\websocket_core.py", line 382, in recv_data
opcode, frame = self.recv_data_frame(control_frame)
File "C:\Users\seanj\AppData\Local\Programs\Python\Python310\lib\site-packages\websocket_core.py", line 403, in recv_data_frame
frame = self.recv_frame()
File "C:\Users\seanj\AppData\Local\Programs\Python\Python310\lib\site-packages\websocket_core.py", line 442, in recv_frame
return self.frame_buffer.recv_frame()
File "C:\Users\seanj\AppData\Local\Programs\Python\Python310\lib\site-packages\websocket_abnf.py", line 338, in recv_frame
self.recv_header()
File "C:\Users\seanj\AppData\Local\Programs\Python\Python310\lib\site-packages\websocket_abnf.py", line 294, in recv_header
header = self.recv_strict(2)
File "C:\Users\seanj\AppData\Local\Programs\Python\Python310\lib\site-packages\websocket_abnf.py", line 373, in recv_strict
bytes_ = self.recv(min(16384, shortage))
File "C:\Users\seanj\AppData\Local\Programs\Python\Python310\lib\site-packages\websocket_core.py", line 526, in _recv
return recv(self.sock, bufsize)
File "C:\Users\seanj\AppData\Local\Programs\Python\Python310\lib\site-packages\websocket_socket.py", line 122, in recv
raise WebSocketConnectionClosedException(
websocket._exceptions.WebSocketConnectionClosedException: Connection to remote host was lost.

Python script for Parsing Office 365 HTML email and getting body

This is script to read email and parse body from outlook 365. For me does not work.
I have outlook 365 account without TFA. TFA is not activated
what could be a problem?
#!/usr/bin/python3
from email.message import EmailMessage
import email
import imaplib
import re
import sys
import logging
import base64
import email.parser
import html2text
import requests
import json
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-mpass', '-mailbox_password', dest = 'mailbox_password', help = 'mailbox password.')
args = parser.parse_args()
user = 'someuser#company.com'
mailbox_password ='Email Password' #args.mailbox_password
def get_email_body(body):
if body.is_multipart():
for payload in body.get_payload():
print('To:\t\t', body['To'])
print('From:\t', body['From'])
print('Subject:', body['Subject'])
print('Date:\t',body['Date'])
for part in body.walk():
if (part.get_content_type() == 'text/plain') and (part.get('Content-Disposition') is None):
output = part.get_payload()
else:
print('To:\t\t', body['To'])
print('From:\t', body['From'])
print('Subject:', body['Subject'])
print('Date:\t', body['Date'])
print('Thread-Index:\t', body['Thread-Index'])
text = f"{body.get_payload(decode=True)}"
html = text.replace("b'", "")
h = html2text.HTML2Text()
h.ignore_links = True
output = (h.handle(f'''{html}''').replace("\\r\\n", ""))
output = output.replace("'", "")
# output in one line
#output = output.replace('\n'," ")
output = output.replace('*', "")
return output
def clear_inbox(conn, dest_folder):
output=[]
result = conn.uid('COPY', emailid, dest_folder)
output.append(result)
if result[0] == 'OK':
result = mov, data = conn.uid('STORE',emailid, '+FLAGS', '(\Deleted Items)')
conn.expunge()
conn = imaplib.IMAP4_SSL("outlook.office365.com")
conn.login(user,mailbox_password)
conn.select("Inbox")
try:
resp, items = conn.uid("search",None, 'All')
items = items[0].split()
for emailid in items:
resp, data = conn.uid("fetch",emailid, "(RFC822)")
if resp == 'OK':
email_body = data[0][1].decode('utf-8')
email_message = email.message_from_string(email_body)
subject = email_message["Subject"]
if subject.lower().startswith('Darktrace'.lower()):
output = get_email_body(email_message)
#do some task
# move emails to Processed folder and clear Inbox
clear_inbox(conn, "Processed")
else:
clear_inbox(conn, "backup")
except IndexError:
print("No new email")
conn.close()
conn.logout()
This is error:
Traceback (most recent call last):
File "d:\python\lib\imaplib.py", line 1047, in _command_complete
typ, data = self._get_tagged_response(tag, expect_bye=logout)
File "d:\python\lib\imaplib.py", line 1173, in _get_tagged_response
self._get_response()
File "d:\python\lib\imaplib.py", line 1075, in _get_response
resp = self._get_line()
File "d:\python\lib\imaplib.py", line 1185, in _get_line
raise self.abort('socket error: EOF')
abort: socket error: EOF
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\Dev Codes\ReadOutlookEmail.py", line 74, in
resp, data = conn.uid("fetch", emailid, "(RFC822)")
File "d:\python\lib\imaplib.py", line 890, in uid
typ, dat = self._simple_command(name, command, *args)
File "d:\python\lib\imaplib.py", line 1230, in _simple_command
return self._command_complete(name, self._command(name, *args))
File "d:\python\lib\imaplib.py", line 1049, in _command_complete
raise self.abort('command: %s => %s' % (name, val))
abort: command: UID => socket error: EOF

Reddit and Twitter bot in Python using PRAW

I am a beginner in Python, and trying out making a bot which automatically Tweets anything which is posted on a Subreddit that I have made.
I took help from some of the tutorials online which has the following code
import praw
import json
import requests
import tweepy
import time
access_token = '************************************'
access_token_secret = '************************************'
consumer_key = '************************************'
consumer_secret = '************************************'
def strip_title(title):
if len(title) == 94:
return title
else:
return title[:93] + "..."
def tweet_creator(subreddit_info):
post_dict = {}
post_ids = []
print("[bot] Getting posts from Reddit")
for submission in subreddit_info.get_hot(limit=20):
post_dict[strip_title(submission.title)] = submission.url
post_ids.append(submission.id)
print("[bot] Generating short link using goo.gl")
mini_post_dict = {}
for post in post_dict:
post_title = post
post_link = post_dict[post]
short_link = shorten(post_link)
mini_post_dict[post_title] = short_link
return mini_post_dict, post_ids
def setup_connection_reddit(subreddit):
print("[bot] setting up connection with Reddit")
r = praw.Reddit(' %s' %(subreddit))
subreddit = r.get_subreddit(subreddit)
return subreddit
def shorten(url):
headers = {'content-type': 'application/json'}
payload = {"longUrl": url}
url = "https://www.googleapis.com/urlshortener/v1/url"
r = requests.post(url, data=json.dumps(payload), headers=headers)
link = json.loads(r.text)['id']
return link
def duplicate_check(id):
found = 0
with open('posted_posts.txt', 'r') as file:
for line in file:
if id in line:
found = 1
return found
def add_id_to_file(id):
with open('posted_posts.txt', 'a') as file:
file.write(str(id) + "\n")
def main():
subreddit = setup_connection_reddit('*Name of the subreddit*')
post_dict, post_ids = tweet_creator(subreddit)
tweeter(post_dict, post_ids)
def tweeter(post_dict, post_ids):
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth)
for post, post_id in zip(post_dict, post_ids):
found = duplicate_check(post_id)
if found == 0:
print("[bot] Posting this link on twitter")
print(post + " " + post_dict[post] + " #Python #reddit #bot")
api.update_status(post+" "+post_dict[post]+" #Python #reddit #bot")
add_id_to_file(post_id)
time.sleep(30)
else:
print("[bot] Already posted")
if __name__ == '__main__':
main()
The code seems fine in PyCharm, however I am getting the following error when I try to run it directly from the folder via Terminal using the rolling code, reddit_bot2.py is my file name:
python3 reddit_bot2.py
When I try to run the code I am getting the following error:
mahesh#Maheshs-MacBook-Air Atoms % python3 reddit_bot2.py
[bot] setting up connection with Reddit
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/configparser.py", line 846, in items
d.update(self._sections[section])
KeyError: '**Name of the subreddit to fetch posts from**'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/mahesh/Python_Bot/Atoms/reddit_bot2.py", line 82, in <module>
main()
File "/Users/mahesh/Python_Bot/Atoms/reddit_bot2.py", line 62, in main
subreddit = setup_connection_reddit('Bot167')
File "/Users/mahesh/Python_Bot/Atoms/reddit_bot2.py", line 36, in setup_connection_reddit
r = praw.Reddit(' %s' %(subreddit))
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/praw/reddit.py", line 227, in __init__
self.config = Config(
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/praw/config.py", line 85, in __init__
self.custom = dict(Config.CONFIG.items(site_name), **settings)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/configparser.py", line 849, in items
raise NoSectionError(section)
configparser.NoSectionError: No section: ' Bot167'
You provided the name of a praw.ini configuration which does not exist.
For help with creating a Reddit instance, visit
https://praw.readthedocs.io/en/latest/code_overview/reddit_instance.html
For help on configuring PRAW, visit
https://praw.readthedocs.io/en/latest/getting_started/configuration.html
Any help in this regards would be highly appreciated.
Thanks :)

Python3 SMTP 'Connection unexpectedly closed'

Could somebody please tell me why I am getting a SMTPServerDisconnected("Connection unexpectedly closed") error from the following code?
import smtplib
from string import Template
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
MY_ADDRESS = '---'
PASSWORD = '---'
def get_contacts(filename):
"""
Return two lists names, emails containing names and email
addresses
read from a file specified by filename.
"""
names = []
emails = []
with open(filename, mode='r', encoding='utf-8') as contacts_file:
for a_contact in contacts_file:
names.append(a_contact.split()[0])
emails.append(a_contact.split()[1])
return names, emails
def read_template(filename):
"""
Returns a Template object comprising the contents of the
file specified by filename.
"""
with open(filename, 'r', encoding='utf-8') as template_file:
template_file_content = template_file.read()
return Template(template_file_content)
def main():
names, emails = get_contacts('contacts.txt') # read contacts
message_template = read_template('message.txt')
# set up the SMTP server
s = smtplib.SMTP('smtp.gmail.com', 465)
s.ehlo()
s.starttls()
s.login(MY_ADDRESS, PASSWORD)
# For each contact, send the email:
for name, email in zip(names, emails):
msg = MIMEMultipart() # create a message
# add in the actual person name to the message template
message =
message_template.substitute(PERSON_NAME=name.title())
# Prints out the message body for our sake
print(message)
# setup the parameters of the message
msg['From']=MY_ADDRESS
msg['To']=email
msg['Subject']="This is TEST"
# add in the message body
msg.attach(MIMEText(message, 'plain'))
# send the message via the server set up earlier.
s.send_message(msg)
del msg
# Terminate the SMTP session and close the connection
s.quit()
if __name__ == '__main__':
main()
Obviously when I run the code my address and password is filled in.
The traceback I get from this when running in terminal is:
Traceback (most recent call last):
File "emailAlert2.py", line 71, in
main()
File "emailAlert2.py", line 40, in main
s = smtplib.SMTP('smtp.gmail.com', 465)
File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/smtplib.py", line 251, in init
(code, msg) = self.connect(host, port)
File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/smtplib.py", line 338, in connect
(code, msg) = self.getreply()
File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/smtplib.py", line 394, in getreply
raise SMTPServerDisconnected("Connection unexpectedly closed")
smtplib.SMTPServerDisconnected: Connection unexpectedly closed
Thanks
The Google Gmail server is hanging up on your (dropping your connection attempt).
Provided that you have enabled third party access (link) to your Gmail account, change your code as follows:
s = smtplib.SMTP('smtp.gmail.com', 465)
s.ehlo()
s.starttls()
s.login(MY_ADDRESS, PASSWORD)
Change to this:
s = smtplib.SMTP_SSL('smtp.gmail.com', 465)
s.ehlo()
s.login(MY_ADDRESS, PASSWORD)
The reason for the hang up is that you are creating a connection using an unencrypted method (smtplib.SMTP()). Google is expecting that you are connecting using SMTPS which requires SSL.
Try port number 587 instead of port 465 in s = smtplib.SMTP('smtp.gmail.com', 465)
Probably you may need to come up with App password instead of your default password - Check this out - https://support.google.com/accounts/answer/185833

Is there any way of getting values from keys inside other keys?

(first post sorry if i do this wrong) So I am making a bot (on discord) for me and my friends using discord.py (since python is the easiest code ever) and I've came across this. I need to get values from keys INSIDE OTHER keys. How do I do this?
So I've tried to change res to res.text and res.json and res.content and I could only find the "data" but not "id","name" or "description" which I need.
import discord
from discord.ext.commands import Bot
from discord.ext import commands
import requests, json
import asyncio
Client = discord.Client()
client = commands.Bot(command_prefix='?')
#client.event
async def on_ready():
print('started')
#client.command()
async def findfriends(ctx,userid):
res = requests.get("https://friends.roblox.com/v1/users/"+userid+"/friends")
var = json.loads(res.text)
def a(a):
ID = a['id']
return ID
def b(b):
Name = b['name']
return Name
def c(c):
description = c['description']
return description
data = var['data'] #I can get this working
print(data)
#cv = data['name'] #but this wont work
#id = a(var) #nor this
#name = b(var) #nor this
#desc = c(var) #nor this
#await ctx.send("\nID: " + id + "\nName: " + name + "\nDesc: " + desc) # this is just sending the message
client.run(BOT TOKEN HERE) #yes i did indeed add it but just for the question i removed it
As I said in the code, I can only get "data" working and not id,name or desc. For id name and desc it just throws an error
Ignoring exception in command findfriends:
Traceback (most recent call last):
File "C:\Users\Calculator\PycharmProjects\ryhrthrthrhrebnfbngfbfg\venv\lib\site-packages\discord\ext\commands\core.py", line 79, in wrapped
ret = await coro(*args, **kwargs)
File "C:/Users/Calculator/PycharmProjects/ryhrthrthrhrebnfbngfbfg/a.py", line 277, in findfriends
id = a(var) #nor this
File "C:/Users/Calculator/PycharmProjects/ryhrthrthrhrebnfbngfbfg/a.py", line 266, in a
ID = a['id']
KeyError: 'id'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\Calculator\PycharmProjects\ryhrthrthrhrebnfbngfbfg\venv\lib\site-packages\discord\ext\commands\bot.py", line 863, in invoke
await ctx.command.invoke(ctx)
File "C:\Users\Calculator\PycharmProjects\ryhrthrthrhrebnfbngfbfg\venv\lib\site-packages\discord\ext\commands\core.py", line 728, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "C:\Users\Calculator\PycharmProjects\ryhrthrthrhrebnfbngfbfg\venv\lib\site-packages\discord\ext\commands\core.py", line 88, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: KeyError: 'id'
and
Ignoring exception in command findfriends:
Traceback (most recent call last):
File "C:\Users\Calculator\PycharmProjects\ryhrthrthrhrebnfbngfbfg\venv\lib\site-packages\discord\ext\commands\core.py", line 79, in wrapped
ret = await coro(*args, **kwargs)
File "C:/Users/Calculator/PycharmProjects/ryhrthrthrhrebnfbngfbfg/a.py", line 274, in findfriends
data = var['data']['id'] #I can get this working
TypeError: list indices must be integers or slices, not str
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\Calculator\PycharmProjects\ryhrthrthrhrebnfbngfbfg\venv\lib\site-packages\discord\ext\commands\bot.py", line 863, in invoke
await ctx.command.invoke(ctx)
File "C:\Users\Calculator\PycharmProjects\ryhrthrthrhrebnfbngfbfg\venv\lib\site-packages\discord\ext\commands\core.py", line 728, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "C:\Users\Calculator\PycharmProjects\ryhrthrthrhrebnfbngfbfg\venv\lib\site-packages\discord\ext\commands\core.py", line 88, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: list indices must be integers or slices, not str
The https://friends.roblox.com/v1/users/<userid>/friends endpoint returns a list of all the friends that the user has, which can be of varying size.
With var = json.loads(res.text) you are loading the response text into a json object, which contains the key data, which you access using data = var['data']. The new data variable now contains a list object, which is why cv = data['name'] fails to work as list objects do not take strings as keys, they are accessed using integers.
You need to iterate over the list to get all information on the friends. The below code goes through the list, pulls information for each item in the list and sends a message of the information once it has gone through all items.
import discord
from discord.ext.commands import Bot
from discord.ext import commands
import requests, json
import asyncio
client = commands.Bot(command_prefix='?')
#client.event
async def on_ready():
print('started')
#client.command()
async def findfriends(ctx,userid):
res = requests.get("https://friends.roblox.com/v1/users/"+userid+"/friends")
var = json.loads(res.text)
data = var['data']
print(data)
friends_msg = 'Friends information:'
for friend in data:
id = friend['id']
name = friend['name']
desc = friend['description']
friends_msg = friends_msg + "\nID: " + id + "\nName: " + name + "\nDesc: " + desc
await ctx.send(friends_msg)
client.run(BOT TOKEN HERE)

Resources