Python script for Parsing Office 365 HTML email and getting body - python-3.x

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

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.

Traceback (most recent call last): File "main.py", line 135, in <module> run_bot(auth['bot_token'], vk_session) help error code python download music

code error
Traceback (most recent call last):
File "main.py", line 135, in <module>
run_bot(auth['bot_token'], vk_session)
File "main.py", line 112, in run_bot
bot.polling()
File "/usr/local/lib/python3.8/dist-packages/telebot/__init__.py", line 514, i n polling
self.__threaded_polling(none_stop, interval, timeout, long_polling_timeout)
File "/usr/local/lib/python3.8/dist-packages/telebot/__init__.py", line 573, i n __threaded_polling
raise e
File "/usr/local/lib/python3.8/dist-packages/telebot/__init__.py", line 536, i n __threaded_polling
self.worker_pool.raise_exceptions()
File "/usr/local/lib/python3.8/dist-packages/telebot/util.py", line 117, in ra ise_exceptions
raise self.exception_info
File "/usr/local/lib/python3.8/dist-packages/telebot/util.py", line 69, in run
task(*args, **kwargs)
File "main.py", line 37, in send_text
if users_data[message.chat.id]['mode'] == 'search':
KeyError: 1413951044
code
import itertools
import requests
import configparser
import telebot
import vk_api
from vk_api.audio import VkAudio
import logging
def run_bot(token, vk_session):
users_data = {}
bot = telebot.TeleBot(token)
vk_audio = VkAudio(vk_session)
#bot.message_handler(commands=['search', 'get'])
def start_message(message):
users_data[message.chat.id] = {}
command = message.text.split()[0][1:]
if command == 'search':
users_data[message.chat.id]['mode'] = 'search'
bot.send_message(message.chat.id, "how to search?")
elif command == 'get':
users_data[message.chat.id]['mode'] = 'get'
try:
users_data[message.chat.id]['user_id'] = message.text.split()[1]
users_data[message.chat.id]['page'] = 0
get(message)
except:
bot.send_message(message.chat.id, "error id (how - /get id)")
#bot.message_handler(content_types=['text'])
def send_text(message):
if users_data[message.chat.id]['mode'] == 'search':
search(message)
#bot.callback_query_handler(func=lambda call: True)
def callback_worker(call):
if users_data[call.message.chat.id]['mode'] == 'search':
download(call)
elif users_data[call.message.chat.id]['mode'] == 'get':
if call.data == 'back':
users_data[call.message.chat.id]['page'] -= 5
get(call.message, call.message.message_id)
elif call.data == 'forward':
users_data[call.message.chat.id]['page'] += 5
get(call.message, call.message.message_id)
else:
download(call)
def download(call):
data = users_data[call.message.chat.id][call.data]
try:
print("loading")
bot.send_message(call.message.chat.id, "loading")
open('tmp.mp3', 'wb').write(requests.get(data['url'], allow_redirects=True, verify=False).content)
audio = open('tmp.mp3', "rb")
bot.send_message(call.message.chat.id, "sending")
print("sending")
bot.send_audio(call.message.chat.id, audio, performer=data['artist'], title=data['title'])
except Exception as exc:
print("error")
bot.send_message(call.message.chat.id, exc)
def get_audio_name(audio):
m, s = divmod(audio["duration"], 60)
track_name = "{} - {} ({}:{:0<2})".format(audio["artist"], audio["title"], m, s)
return track_name
def search(message):
print("Message received:", message.text)
items = [it for it in vk_audio.search(message.text, 5)]
if len(items) != 0:
print("On request found", len(items))
keyboard = telebot.types.InlineKeyboardMarkup()
for item in items:
users_data[message.chat.id][str(items.index(item))] = {'artist': item["artist"], 'title': item["title"],
'url': item["url"]}
key = telebot.types.InlineKeyboardButton(text=get_audio_name(item),
callback_data=str(items.index(item)))
keyboard.add(key)
bot.send_message(message.chat.id, text="What are we going to download?", reply_markup=keyboard)
else:
print("Nothing was found on the request")
bot.send_message(message.chat.id, "Nothing was found on the request")
print("Конец")
def get(message, id_msg_to_edit=None):
try:
it = vk_audio.get_iter(users_data[message.chat.id]['user_id'])
itt = itertools.islice(it, users_data[message.chat.id]['page'], users_data[message.chat.id]['page'] + 5)
keyboard = telebot.types.InlineKeyboardMarkup()
costil = 0
for i in itt:
users_data[message.chat.id][str(costil)] = i
keyboard.add(telebot.types.InlineKeyboardButton(text=get_audio_name(i), callback_data=str(costil)))
costil += 1
if users_data[message.chat.id]['page'] != 0:
keyboard.add(telebot.types.InlineKeyboardButton(text="Back", callback_data="back"))
if costil != 4:
keyboard.add(telebot.types.InlineKeyboardButton(text="Forward", callback_data="forward"))
if id_msg_to_edit is None:
bot.send_message(message.chat.id, text='What will we download?', reply_markup=keyboard)
else:
bot.edit_message_reply_markup(message.chat.id, id_msg_to_edit, reply_markup=keyboard)
except Exception as exc:
bot.send_message(message.chat.id, text=exc)
bot.polling()
What could be the problem here?
message.chat.id at line 37 is resolved to value 1413951044 and this key is not present in users_data dictionary, hence KeyError is raised.
If you just want to get rid of this error, enclose line 37 in a try/except block like below:
try:
if users_data[message.chat.id]['mode'] == 'search':
except KeyError:
pass

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 doesn't recognise my folder path even though it matches what the terminal shows

I'm running ubuntu 18.04 within a google vm. This is my first time working with python so apologies if this is really basic. When I run my code below I get an error message that my folder path wasn't found even though from what I understand it should be correct. Can someone confirm if there is something different I am meant to do when stating a folder path in python3 vs what I have done below?
test.py
#!/usr/bin/env python3
import imaplib
import base64
import os
import email
username = 'gmail_user'
password = 'app_password'
mail = imaplib.IMAP4_SSL("imap.gmail.com")
rv, data = mail.login(username, password)
print(rv,data)
mail.select("blah")
type, data = mail.search(None, "All")
print(data[0])
id_list = data[0].split()
for num in id_list:
typ, data = mail.fetch(num, '(RFC822)')
raw_email = data[0][1]
raw_email_string = raw_email.decode('utf-8')
email_message = email.message_from_string(raw_email_string)
for part in email_message.walk():
if part.get_content_maintype() == 'multipart':
continue
if part.get('Content-Disposition') is None:
continue
fileName = part.get_filename()
if bool(fileName):
filePath = os.path.join('~/workshop/email-downloader/', fileName)
if not os.path.isfile(filePath):
fp = open(filePath, 'wb')
fp.write(part.get_payload(decode=True))
fp.close()
subject = str(email_message).split("Subject: ", 1)[1].split("\nTo:", 1)[0]
print('Downloaded "{file}" from email titled "{subject}" with UID.'.format(file=fileName, subject=subject))
Error Message
user#server:~/workshop/email-downloader$ python3 test.py
OK [b'gmail_user authenticated (Success)']
b'1'
Traceback (most recent call last):
File "test.py", line 35, in <module>
fp = open(filePath, 'wb')
FileNotFoundError: [Errno 2] No such file or directory: '~/workshop/email-downloader/dasd.txt'
Where my script is being called from ~/workshop/email-downloader/
old path that doesn't work
filePath = os.path.join('~/workshop/email-downloader/', fileName)
new path that works
filePath = os.path.join('test/', fileName)

smtplib, 'tuple' object has no attribute 'encode'

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)

Resources