download base64 email attachment - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: General Coding Help (https://python-forum.io/forum-8.html) +--- Thread: download base64 email attachment (/thread-24624.html) |
download base64 email attachment - cferguson - Feb-23-2020 Hey, New to coding. New to python. I have been using home assistant to do some automation stuff at my place. But my lorex NVR is not natively supported. It does send a email notification on motion detection. I have been able to decode the email body with a python script ran inside the home assistant api (gmail is supported in home assistant.) But now i would like to download the attached email picture. I have been able to piece together a bit of code that can download attachments from non-base64 emails. But I haven't found anything that works for the encoded ones. Here is what I have so far. import imaplib import email import os svdir = 'c:/save/temp' mail = imaplib.IMAP4_SSL('imap.gmail.com', 993) mail.login("hidden","hidden") mail.select("Inbox") typ, data = mail.search(None, 'SEEN') for num in data[0].split(): mail.store(num, '+FLAGS', '\\deleted') mail.expunge() typ, msgs = mail.search(None, 'ALL') msgs = msgs[0].split() for emailid in msgs: resp, data = mail.fetch(emailid, "(RFC822)") email_body = data[0][1] m = email.message_from_bytes(email_body) if m.get_content_maintype() != 'multipart': continue for part in m.walk(): if part.get_content_maintype() == 'multipart': continue if part.get('Content-Disposition') is None: continue filename = part.get_filename() if filename is not None: sv_path = os.path.join(svdir, filename) if not os.path.isfile(sv_path): print(sv_path) fp = open(sv_path, 'wb') fp.write(part.get_payload(decode=True)) fp.close() mail.close() mail.logout()It also only leaves one email in the account by design. Can anyone help me so I can get this to download any and all email attachments regardless of the encoding? the svdir in the above code is what I am using in spyder for testing. But the version I run in home assistant works the same the correctly defined dir. Thanks. I have been able to run this code and identify the attachment. import imaplib mail = imaplib.IMAP4_SSL('imap.gmail.com', 993) mail.login("hidden","hidden") mail.select('inbox') result, data = mail.uid('search', None, 'ALL') uids=data[0].split() result, data = mail.uid('fetch', uids[-1], 'BODYSTRUCTURE') print(data)it returns
RE: download base64 email attachment - cferguson - Feb-23-2020 Woo I got a result! not I just gotta figure out how to decode it and turn it into a proper picture! import imaplib import email import base64 import os svdir = 'c:/save/temp' mail = imaplib.IMAP4_SSL('imap.gmail.com', 993) mail.login("","") mail.select("Inbox") #typ, data = mail.search(None, 'SEEN') #for num in data[0].split(): # mail.store(num, '+FLAGS', '\\deleted') #mail.expunge() typ, msgs = mail.search(None, 'ALL') msgs = msgs[0].split() for emailid in msgs: resp, data = mail.fetch(emailid, "(RFC822)") email_body = data[0][1] m = email.message_from_bytes(email_body) print((data)[0][1]) #added this and the output was a raw base64 string I #was able to repair and decode on a website. Returned #the actual image! Now I just need to decode it and #save it as a file I guess. if m.get_content_maintype() != 'multipart': continue for part in m.walk(): if part.get_content_maintype() == 'multipart': continue if part.get('Content-Disposition') is None: continue filename = part.get_filename() if filename is not None: sv_path = os.path.join(svdir, filename) if not os.path.isfile(sv_path): print(sv_path) fp = open(sv_path, 'wb') fp.write(part.get_payload(decode=True)) fp.close() mail.close() mail.logout() RE: download base64 email attachment - cferguson - Feb-24-2020 still struggling with this. for part in m.walk(): if part.get_content_maintype() == 'multipart': continue if part.get('Content-Transfer-Encoding') is None: continue filename = part.get_filename() filename = str(filename.strip('=?utf-8?b?)') filename = base64.b64decode(filename).decode('utf-8')I tried this but I can't seem to figure out how to decode the output (Feb-24-2020, 05:40 PM)cferguson Wrote: still struggling with this. *correction RE: download base64 email attachment - cferguson - Feb-25-2020 I DID IT. WOO. import imaplib import email import base64 import os svdir = 'c:/save/temp' def sender_decode(sender): parsed_string = sender.split("?") decoded = base64.b64decode(parsed_string[3]).decode(parsed_string[1], "ignore") return decoded mail = imaplib.IMAP4_SSL('imap.gmail.com', 993) mail.login("HIDDEN","HIDDEN") mail.select("Inbox") typ, data = mail.search(None, 'SEEN') for num in data[0].split(): mail.store(num, '+FLAGS', '\\deleted') mail.expunge() typ, msgs = mail.search(None, 'UNSEEN') msgs = msgs[0].split() for emailid in msgs: resp, data = mail.fetch(emailid, "(RFC822)") email_body = data[0][1] m = email.message_from_bytes(email_body) if m.get_content_maintype() != 'multipart': continue for part in m.walk(): if part.get_content_maintype() == 'multipart': continue if part.get('Content-Transfer-Encoding') is None: continue filename: str = part.get_filename() if filename is None: continue try: filename = sender_decode(filename) except IndexError: filename = part.get_filename() if filename is not None: sv_path = os.path.join(svdir, filename) if not os.path.isfile(sv_path): fp = open(sv_path, 'wb') fp.write(part.get_payload(decode=True)) fp.close() mail.close() mail.logout() |