Parse “math340-05 =?UTF-8?B?4oCTIEF1ZmdhYmUgNS4x?=” - python

I want to extract the subject from an email which is stored in an .eml file using Python 3:
The subject line from the file is the following:
Subject: math340-05 =?UTF-8?B?4oCTIEF1ZmdhYmUgNS4x?=
I try to parse the name using the email module, but it returns the string as is:
with open(filename, "r") as f:
m = email.message_from_file(f)
print(m["Subject"])
How can I decode that?

One way of doing it would be to us the email.header module:
import email, email.header
m = email.message_from_string("Subject: math340-05 =?UTF-8?B?4oCTIEF1ZmdhYmUgNS4x?=")
raw_header = email.header.decode_header(m["Subject"])
header = email.header.make_header(raw_header)
print(str(header))
# or for py2: print(unicode(header))
will give you:
math340-05 – Aufgabe 5.1

Related

How do you grab data from a text file, then use the extracted data in the Python file?

I have a text file with my email and password address,
Text file:
email: email#address.com
password: password123
I'd like to extract the data from the text file, using the variables "email" and input it into my code, using Selenium.
For example:
search = driver.find_element_by_name("emailAddress")
search.send_keys(EmailFromTextFile)
How?
Try this:
with open("file/location.txt","r") as f:
txt = f.read()
email = txt.split("password")[0].split(":")[1].strip()
password = txt.split(":")[2].strip()
Here's a way using a regular expression:
import re
# There would be other code here to set up Selenium and
# define the variable `driver`
with open('/tmp/data.txt') as f:
buf = f.read()
expr = re.compile(r"email:\s*([^\s]+)\s+password: (.*)")
m = expr.match(buf)
if m:
email = m.group(1)
password = m.group(2)
search = driver.find_element_by_name("emailAddress")
search.send_keys(email)
Use:
myfile = open("text.txt","r") # text.txt is the file name, r means read file.
contents = myfile.read()
print(contents)
myfile.close()
You can get more information about Python file handling in Python File Open.

String Formatting in Python/Thunderbird

Noob, trying to use Thunderbird (rather than SMTP) to send personalized emails to a few dozen people. I am basically looking to have the message display in Thunderbird as follows:
Dear Bob,
It was nice to meet you the other day.
However, I instead end up with:
Dear Bob (comma missing, and rest of body missing)
I have tried the following:
import subprocess
import os
def send_email(name, email_address):
#print(name, email_address)
os.system("thunderbird -compose to= 'to',subject='subject',body='body'")
tbirdPath = r'c:\Program Files (x86)\Mozilla Thunderbird\thunderbird.exe'
to = email_address
subject = 'Test Subject LIne'
#body = "Dear %s, \n\n This is the body." %(name)
body = 'html><body>Dear %s, This is the body <br></body></html>'%(name)
composeCommand = 'format=html,to={},subject={},body={}'.format(to, subject, body)
subprocess.Popen([tbirdPath, '-compose', composeCommand])
As always, simple answers I can implement are preferred to complex ones I cannot. I suspect I'm missing something stupid about string formatting, but am unsure as to exactly what. Thanks in advance for your help.
From this example, you may need to surround the arguments with single and double quotes.
Like this:
composeCommand = '"format=html,to=\'{}\',subject=\'{}\',body=\'{}\'"'.format(to, subject, body)
By the way, if you are using python 3.6+, using f-strings makes str more readable:
body = f'<html><body>Dear {name}, This is the body <br></body></html>'
composeCommand = f'"format=html,to=\'{to}\',subject=\'{subject}\',body=\'{body}\'"'
So here is a simple program to read in names and email addresses from a CSV file, and to automate drafting emails from your Thunderbird client (you will still need to hit send on each), using Python on a Windows machine.
import csv
import subprocess
import os
# a list that will contain OrderedDict ('Name', 'Bob'), ('email', bob#yahoo.com)
each_persons_info = []
def load_email_info(data_file):
"""
Load data from CSV files into memory.
"""
# Load people
with open(f"email_list.csv", encoding="utf-8") as f:
reader = csv.DictReader(f)
# using DictReader, starts reading at row 2, with row 1 forming your labels, append to each_persons_info list (differs from csv reader in that respect)
for row in reader:
each_persons_info.append(row)
def send_email(name, email_address):
"""
Launches Thunderbird and drafts personalized emails to people on your list, using content you supply in subject and body fields below.
"""
subject = 'Test Subject LIne'
body = "Dear {}".format(name) + '\n' + '\n' + "This is the body." + '\n' + '\n' + "The End." + '\n'
to = email_address
os.system("thunderbird -compose to= 'to',subject='subject',body='body'")
tbirdPath = r'c:\Program Files (x86)\Mozilla Thunderbird\thunderbird.exe'
composeCommand = "format=html,to={},subject={},body='{}'".format(to, subject, body)
subprocess.Popen([tbirdPath, '-compose', composeCommand])
def main():
load_email_info("email_list.csv")
# walk each person through the send email function
for item in each_persons_info:
send_email(name, email_address)
if __name__ == "__main__":
main()

PYTHON/OUTLOOK Sending e-mails through PYTHON with DOCX

I have to send mails through python. It works. It is almost done. The only problem is that I have to keep the formatting too. So either I have to send e mail as HTML (and then rewrite template with html instead of .docx) OR copy .docx file with extension
Anybody has any ideas how to do this? Thanks guys.
import win32com.client as win32
import fileinput as fi
from docx import Document
outlook = win32.Dispatch('outlook.application')
path_in = 'maillist.csv'
input_file = open(path_in, 'r')
document = Document('template.docx')
document_html = open('template.html', 'r')
print(temp)
def filecount(fname):
for line in fi.input(fname):
pass
return fi.lineno()
print("Total mails %s" % (filecount(path_in)))
count = 0
for line in input_file:
if (count>16):
name = line.split(";")[0]
mail_adress = line.split(";")[1]
subject = line.split(";")[2]
print ("%s:%s:%s:" % (name, mail_adress, subject))
mail = outlook.CreateItem(0)
mail.To = mail_adress
mail.Subject = subject
mail.body = temp.replace("XXXNAMEXXX", name)
mail.send
else:
count+=1
Try adding the .RTFBody and/or .HTMLBody methods to the document objects :
document = Document('template.docx').RTFBody
document_html = open('template.html', 'r').HTMLBody
Also, I'm not sure if it makes much of a difference but, for convention's sake, I like to capitalize the first letter of the method for the mailItem object.
Let me know if that works.

How to get decode attachment filename with python email?

I use the following code to extract filename of the attachment:
import email.utils
msg = email.message_from_string(self.request.body) # http://docs.python.org/2/library/email.parser.html
for part in msg.walk():
ctype = part.get_content_type()
if ctype in ['image/jpeg', 'image/png']:
image_file = part.get_payload(decode=True)
image_file_name = part.get_filename()
It works well in many cases, but sometime as image_file_name I get values like =?KOI8-R?B?xsHTLTk2Mi5qcGc=?= or =?UTF-8?B?REkyeTFXMFNMNzAuanBn?=.
How should I handle such cases?
You can use decode_header function like this:
from email.header import decode_header
filename = part.get_filename()
if decode_header(filename)[0][1] is not None:
filename = str(decode_header(filename)[0][0]).decode(decode_header(filename)[0][1])
With Python 3:
from email.message import EmailMessage
from email.header import decode_header
def get_part_filename(msg: EmailMessage):
filename = msg.get_filename()
if decode_header(filename)[0][1] is not None:
filename = decode_header(filename)[0][0].decode(decode_header(filename)[0][1])
return filename
You should look at the three parts separated by '?', and use the first two as instructions for how to treat the third:
The first bit is the character-encoding (KO18-R and UTF-8 in your examples), and the second bit is a 'B' to indicate base64 encoding - Q in it's place would indicate quoted-printable, so you should prepare your code for that as well.
Elaborating on #Nikon's response:
from email.header import decode_header
filename = part.get_filename()
fname, charset = decode_header(filename)
if charset:
filename = fname.decode(charset)

Simple encryption and decryption of strings by using bz2 in Python

I am trying to create a file with encrypted username, password and computer name when the user logs in. And the same data I want to use again to authenticate the data but by decrypting them first. I am trying to use something that is built in python and simple.
import os
import bz2
os.chdir("D:/test")
encrypted_username = bz2.compress('username')
encrypted_password = bz2.compress('password')
computer_name = os.environ['COMPUTERNAME']
encrypted_computer_name = bz2.compress(computer_name)
f = open("Session.dat", "w")
f.write(encrypted_username + '\n')
f.write(encrypted_password + '\n')
f.write(encrypted_computer_name)
f.close()
f = open("Session.dat", "r")
data = f.read()
d_data = bz2.decompress(data)
f.close()
print(d_data)
But when I decrypt the data in the file and print it. I get the answer as below. Why am I not getting the password and computer name?? Thank you.
username
The code compressed the strings separately. You should read all lines and decompress them line by line as alecxe commented. But that is not practical because compressed data could contians newline(s).
Instead combine strings (In the following code, I used NULL byte \0 as separator), then compress the combined string.
Decompress: After decompress, split combined strings using the same separator.
import os
import bz2
#os.chdir("D:/test")
username = 'username'
password = 'password'
computer_name = os.environ['COMPUTERNAME']
compressed = bz2.compress(username + '\0' + password + '\0' + computer_name)
with open("Session.dat", "wb") as f:
f.write(compressed)
with open("Session.dat", "rb") as f:
d_data = bz2.decompress(f.read())
print(d_data.split('\0'))
BTW, you should use binary mode to read/write compressed data.

Categories