Decoding message headers and bodies in python - python

I'm trying to program a simple mail client in Python which can both send and read messages from inbox in gmail. The sending part works well, but the reading part keeps giving me a bad result.
Here is the python code:
import imaplib
import base64
email_user = '<gmail_address>'
email_pass = '<password>'
M = imaplib.IMAP4_SSL('imap.gmail.com', 993)
M.login(email_user, email_pass)
M.select('inbox')
typ, message_numbers = M.search(None, 'ALL') # change variable name, and use new name in for loop
typ, data = M.fetch(b'1', '(RFC822)')
data1 = base64.b64decode(data[0][1])
print('Message \n%s' %data1)
M.close()
M.logout()
and the result is:
Message
b'\r\xe9b\xbd\xea\xdeu:1\xcaf\xa2\x97M;\x82f\xa2\x95\xca&E\xe7\x1e\x8a\xf7\x9do-\xb4\xd3f\xb5\xef\xdd\x1a\xd7Nt\xd3M4\xc2+aH\xc4\xcf\x89\xdc\xb5\xea\xfe\x9c\xb2\x9d\xb8\xd3\xae\xbd\xf2\x98\xdd2\x89\xf5\xd4W\x9b\xdbM}\xd3nv\xd7\x9d<\xd3C\xd2Mt^q\xe8\xafy\xd6\xf2\xdbM6i\xd7\xfc\xdbgp\x8a\xd8R13\xe2w\x8d\xa6\xaf^\xbb\xefo{\xf3\n\xdb\xeb}y\xe3\xdf<\xdb}\xf9\xdfM\x8c\xa2}u\x15\xe6\xf6\xd3_t\xdb\x9d\xb5\xe7O4\xd0\xf4\x93\x01\x10\x92y\xa9b\xd5\xaa\xecj\xc8Z\xdb\x9e\xad\xd7\x9e=\xf3\xcd\xb7\xdf\x97/\x9e\x89\xdev\n(\x82W\x9c\xa2k'
I appreciate any modified code and hint. Also I'm new to python so please keep your descriptions as simple as possible...

The message you receive in data[0][1] is not base64.
You want to do something like
from email import message_from_bytes
...
msg = message_from_bytes(data[0][1])
and then manipulate msg.

Related

Python imaplib fetching iCloud mail RFC822 not working

I'm unable to fetch email from iCloud Mail using imaplib.
Below is the code I am trying to run:
import imaplib
imap_host = 'imap.mail.me.com'
imap_user = 'user#icloud.com'
imap_pass = 'password'
M = imaplib.IMAP4_SSL(imap_host)
M.login(imap_user, imap_pass)
# Select folder named Google
M.select('Google')
typ, data = M.search(None, 'ALL')
for num in data[0].split():
typ, data = M.fetch(num, "(RFC822)")
print('Message %s: %s' % (num, data))
M.close()
M.logout()
This results in the following output:
Message b'1': [b'1 ()']
Message b'2': [b'2 ()']
Message b'3': [b'3 ()']
Message b'4': [b'4 ()']
In the print line if I change data to data[0][1], the number 32 gets printed out 4 times, whereas I should be getting the message bodies.
Interestingly, if I change (RFC822) to ((BODY.PEEK[HEADER.FIELDS (SUBJECT)])), I do get all the subjects of the messages printed out.
I've tried just about everything at this point and I have no idea what the problem is.
I'm expecting RFC822 to give me the whole message, but it is giving me absolutely nothing.
Any help or insight would be appreciated.

Reading Gmail Email in Python

I am attempting to create a simple script to check my Gmail for emails with a certain title. When I run this program on Python 3.7.3 I receive this data: ('OK', [b'17']).
I need to access the body of the email within python. I am just not sure what to do with the data that I have.
Here is my current code:
import imaplib
import credentials
imap_ssl_host = 'imap.gmail.com'
imap_ssl_port = 993
username = credentials.email
password = credentials.passwd
server = imaplib.IMAP4_SSL(imap_ssl_host, imap_ssl_port)
server.login(username, password)
server.select('INBOX')
data = server.uid('search',None, '(SUBJECT "MY QUERY HERE!")')
print(data)
The result from running the code:
('OK', [b'17'])
I know it is a little rough, but I am still learning, so any advice you have to help me improve would be greatly appreciated!
You need to first list the contents of the selected mailbox and fetch one of the items. You could do something like this (also check the link suggested by #asynts)
imap.select('Inbox')
status, data = imap.search(None, 'ALL')
for num in data[0].split():
status, data = imap.fetch(num, '(RFC822)')
email_msg = data[0][1]
If you only want specific fields in the body, instead of parsing the RFC you could filter fields like:
status, data = imap.fetch(num, '(BODY[HEADER.FIELDS (SUBJECT DATE FROM TO)])')

I'm trying to get emails from server using imaplib in Python, but it didn't print anything

I'm trying to get and print all emails from server using imaplib in Python, but it didn't print anything. I have gone through I want to grab all emails from an inbox using the Python IMAPLIB module... how can I do this? and the imaplib documentation. But the code didn't print the mails.
mail = imaplib.IMAP4_SSL(imap_host)
## login
mail.login(imap_user, imap_pass)
status, messages = mail.select('INBOX')
print(status)
if status != "OK":
exit("Incorrect mail box")
print(messages)
typ, data = mail.search(None, 'ALL')
for num in data[0].split():
typ, data = mail.fetch(num, '(RFC822)')
print('Message %s\n%s\n' % (num, data[0][1]))
mail.close()
mail.logout()
Here, the print(status) prints 'OK' but print(messages) prints [b'0']. Several answers from stackoverflow i have analyzed. I'm stuck in this, any suggestions. I want to print all the emails in the particular mailid.

Receive replies from Gmail with smtplib - Python

Ok, I am working on a type of system so that I can start operations on my computer with sms messages. I can get it to send the initial message:
import smtplib
fromAdd = 'GmailFrom'
toAdd = 'SMSTo'
msg = 'Options \nH - Help \nT - Terminal'
username = 'GMail'
password = 'Pass'
server = smtplib.SMTP('smtp.gmail.com:587')
server.starttls()
server.login(username , password)
server.sendmail(fromAdd , toAdd , msg)
server.quit()
I just need to know how to wait for the reply or pull the reply from Gmail itself, then store it in a variable for later functions.
Instead of SMTP which is used for sending emails, you should use either POP3 or IMAP (the latter is preferable).
Example of using SMTP (the code is not mine, see the url below for more info):
import imaplib
mail = imaplib.IMAP4_SSL('imap.gmail.com')
mail.login('myusername#gmail.com', 'mypassword')
mail.list()
# Out: list of "folders" aka labels in gmail.
mail.select("inbox") # connect to inbox.
result, data = mail.search(None, "ALL")
ids = data[0] # data is a list.
id_list = ids.split() # ids is a space separated string
latest_email_id = id_list[-1] # get the latest
result, data = mail.fetch(latest_email_id, "(RFC822)") # fetch the email body (RFC822) for the given ID
raw_email = data[0][1] # here's the body, which is raw text of the whole email
# including headers and alternate payloads
Shamelessly stolen from here
Uku's answer looks reasonable. However, as a pragmatist, I'm going to answer a question you didn't ask, and suggest a nicer IMAP and SMTP library.
I haven't used these myself in anything other then side projects so you'll need to do your own evaluation, but both are much nicer to use.
IMAP
https://github.com/martinrusev/imbox
SMTP:
http://tomekwojcik.github.io/envelopes/
I can suggest you to use this new lib https://github.com/charlierguo/gmail
A Pythonic interface to Google's GMail, with all the tools you'll
need. Search, read and send multipart emails, archive, mark as
read/unread, delete emails, and manage labels.
Usage
from gmail import Gmail
g = Gmail()
g.login(username, password)
#get all emails
mails = g.inbox().mail()
# or if you just want your unread mails
mails = g.inbox().mail(unread=True, from="youradress#gmail.com")
g.logout()

python email.parser: extract header from email

import sys, imaplib
from email.parser import HeaderParser
mail = imaplib.IMAP4_SSL(SERVER, PORT)
status, data = mail.search(None, 'ALL')
for msg_id in data[0].split():
status, message = mail.fetch(msg_id, '(RFC822)')
print message[0][1]
mail.close()
mail.logout()
I am trying to fetch emails from gmail via imap. All works fine, except that I am not able to extract header (subject, sender, date) from the message. In the above code, message[0][1] contains my email.
The only way I am able to get the header is to ask the imap server again, specifically for header:
status, message = mail.fetch(msg_id, '(BODY[HEADER.FIELDS (SUBJECT FROM)])')
parser = HeaderParser()
header = parser.parsestr(message[0][1])
print header
could somebody please advise how to do it?
I assume you've got the full email, not only the message body.
raw_message = """From: Santa Claus <santa#aintreal.no>
To: Some Dude <some#du.de>
Subject: I have lost your presents.
Dude, i am so sorry.
"""
import email
msg = email.message_from_string(raw_message)
print(msg['Subject']) # "I have lost your presents."
msg is a email.message.Message object.

Categories

Resources