I'm trying to create a Python code that reads data from an email, saves it onto a temporary txt. file. There will be another permanent txt. file, where the temporary txt. files contents will be written in a form that skips the first 6 lines. During this loop the temporary file gets flushed, so the same data will not be written multiple times.
Here is the code I have worked with:
for part in email_message.walk():
if part.get_content_type() == 'text/plain':
body = part.get_payload(decode=True)
save_string = str('C:/Email/file.txt')
myfile = open(save_string, 'a')
myfile.write(str(body)) ## Write to file 2 and then flush this
open ('C:/Email/file.txt','w+') as f:
lines = f.readlines()
open ('C:/Email/newfile.txt','a') as g:
g.writelines(lines[6:])
f.close()
g.close()
myfile.close()# Clear first file
else:
continue
Currently the issue is that it writes the email to the first txt. file, but does not update the second txt. file. However, when I run the code again, the previous data gets written to the second txt. This is something I don't quite understand why it happens, since the order should be correct. Thanks in advance!
More of the code here:
@view_config(route_name='update-data')
def update_view(request):
m = imaplib.IMAP4_SSL('imap.gmail.com')
m.login('gmail@gmail.com', 'password')
m.list()
m.select('inbox')
result, data = m.uid('search', None, 'UNSEEN') # Only unseen mail
i = len(data[0].split()) #space separate string
if i == 0:
return Response('<h3> Data cannot be updated </h3><h4>No new emails</h4><a href="localhost:8888"> Return to the main page </a> ')
for x in range(i):
latest_email_uid = data[0].split()[x]
result, email_data = m.uid('fetch', latest_email_uid, '(RFC822)')
raw_email = 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_type() == 'text/plain':
body = part.get_payload(decode=True)
save_string = str('C:/Email/file.txt')
myfile = open(save_string, 'a')
myfile.write(str(body)) ## Write to file 2 and then flush this
open ('C:/Email/file.txt','w+') as f:
lines = f.readlines()
open ('C:/Email/newfile.txt','a') as g:
g.writelines(lines[6:])
f.close()
g.close()
myfile.close()# Clear first file
else:
continue
return Response('<h3>Data update successful</h3>')
EDIT
Got it working the way I want with this:
for part in email_message.walk():
if part.get_content_type() == 'text/plain':
body = part.get_payload(decode=True)
with open('C:/Email/file.txt', 'a') as myfile: # Opens file.txt and writes the email body
myfile.write(str(body))
with open('C:/Email/file.txt', 'r+') as f: # Opens file.txt again in read mode and reads lines
lines = f.readlines()
with open ('C:/Email/newfile.txt','a') as g: # Writes file.txt contents to newfile.txt, starting from line 6, deletes contents of the first file
g.writelines(lines[6:])
f.truncate(0)
else:
continue
You need to close myfile
before trying to reopen it and you should reopen it in read
mode. Try something like this
for part in email_message.walk():
if part.get_content_type() == 'text/plain':
body = part.get_payload(decode=True)
save_string = str('C:/Email/file.txt')
myfile = open(save_string, 'a')
myfile.write(str(body)) ## Write to file 2 and then flush this
myfile.close()
open ('C:/Email/file.txt','r') as f:
lines = f.readlines()
open ('C:/Email/newfile.txt','a') as g:
g.writelines(lines[6:])
f.close()
g.close()
But it would be better to use with
context manager to open your files, in which case you dont have to worry about closing files
for part in email_message.walk():
if part.get_content_type() == 'text/plain':
body = part.get_payload(decode=True)
with open('C:/Email/file.txt', 'a') as myfile:
myfile.write(str(body))
with open('C:/Email/file.txt', 'r') as f:
lines = f.readlines()
with open ('C:/Email/newfile.txt','a') as g:
g.writelines(lines[6:])