I have this code (below) that shows me all emails in my email account. It also shows the whole email, including all the metadata (which I dont want). Is there a way to just print the To, From, Subject and Message only? This is in Python as well. Thanks.
Code:
import getpass, imaplib
import os
email = raw_input('Email: ')
password = getpass.getpass()
M = imaplib.IMAP4_SSL("imap.gmail.com", 993)
print('Logging in as ' + email + '...')
M.login(email, password)
M.select()
typ, data = M.search(None, 'ALL')
for num in data[0].split():
typ, data = M.fetch(num, '(RFC822)')
print ('Message %s\n%s\n' % (num, data[0][1]))
M.close()
M.logout()
You can use email.parser.Parser() from standard module to parse mail and get headers
from __future__ import print_function
import imaplib
import getpass
import os
from email.parser import Parser
email = raw_input('Email: ')
password = getpass.getpass()
print('Logging in as', email, '...')
M = imaplib.IMAP4_SSL("imap.gmail.com", 993)
M.login(email, password)
M.select()
typ, data = M.search(None, 'ALL')
for num in data[0].split():
typ, data = M.fetch(num, '(RFC822)')
#print ('Message %s\n%s\n' % (num, data[0][1]))
header = Parser().parsestr(data[0][1])
print('From:', header['From'])
print('To:', header['To'])
print('Subject:', header['Subject'])
print('Body:')
for part in header.get_payload():
print(part.as_string()[:150], '.....')
#break # to test only first message
M.close()
M.logout()
For anyone else who wants to know, this is the working code:
from __future__ import print_function
import imaplib
import getpass
import os
from email.parser import Parser
email = raw_input('Email: ')
password = getpass.getpass()
print('Logging in as', email, '...\n')
M = imaplib.IMAP4_SSL("imap.gmail.com", 993)
M.login(email, password)
M.select()
typ, data = M.search(None, 'ALL')
for num in data[0].split():
typ, data = M.fetch(num, '(RFC822)')
## To view whole email, uncomment next line
## print ('Message %s\n%s\n' % (num, data[0][1]))
header = Parser().parsestr(data[0][1])
print('To:', header['Delivered-To'])
print('From:', header['From'])
print('Subject:', header['Subject'])
print('Body:', header.get_payload(), '\n')
M.close()
M.logout()
Hope this helps :) Big thanks to #furas!
Related
I want to create a program in python that receives every new unread email from one of my email accounts to another email account.
So far I got everything set up. Unfortunately I have really big issues with umlauts (ä,ö,ü). For some reason I con not make it to work properly.
Here is my code:
# -*- coding: utf-8 -*-
import os, sys
import imaplib
import email
import smtplib
from email.mime.multipart import MIMEMultipart
servername = 'SERVERNAME'
username='USERNAME'
password='PASSWORD'
mail = imaplib.IMAP4_SSL(servername)
(retcode, capabilities) = mail.login(username,password)
mail.list()
mail.select('inbox')
server_smtp = smtplib.SMTP_SSL('SMTP')
n=0
(retcode, messages) = mail.search(None, '(UNSEEN)')
if retcode == 'OK':
for num in messages[0].split() :
n=n+1
typ, data = mail.fetch(num,'(RFC822)')
for response_part in data:
if isinstance(response_part, tuple):
original = email.message_from_string(response_part[1])
print original['From']
typ, data = mail.store(num,'+FLAGS','\\Seen')
body = ""
if original.is_multipart():
for part in original.walk():
ctype = part.get_content_type()
cdispo = str(part.get('Content-Disposition'))
if ctype == 'text/plain' and 'attachment' not in cdispo:
body = part.get_payload(decode=True) # decode
break
else:
body = original.get_payload(decode=True)
body = body.encode('UTF-8')
body = str(body)
print(body)
body = "Betreff: " + str(original['Subject']) + "\n\n\n" + body.encode('UTF-8')
SUBJECT = original['From']
server_smtp.login(username, password)
msg = 'Subject: {}\n\n{}'.format(SUBJECT, body.decode('UTF-8'))
server_smtp.sendmail(username, 'TARGET', msg)
For example: if I want to send this message: "ÄäÖöÜü&ß" I will receive this: "������������&��
���"
Do you know what I am doing wrong?
I would really appreciate your help!
I wrote the code below for my script:
import sys
import imaplib
import getpass
import email
import email.header
import datetime
EMAIL_ACCOUNT = "notatallawhistleblowerIswear#gmail.com"
EMAIL_FOLDER = "INBOX"
def process_mailbox(M):
rv, data = M.search(None, "ALL")
if rv != 'OK':
print("No messages found!")
return
for num in data[0].split():
rv, data = M.fetch(num, '(RFC822)')
if rv != 'OK':
print("ERROR getting message", num)
return
msg = email.message_from_bytes(data[0][1])
hdr = email.header.make_header(email.header.decode_header(msg['Subject']))
subject = str(hdr)
print('Message %s: %s' % (num, subject))
print('Raw Date:', msg['Date'])
# Now convert to local date-time
date_tuple = email.utils.parsedate_tz(msg['Date'])
if date_tuple:
local_date = datetime.datetime.fromtimestamp(
email.utils.mktime_tz(date_tuple))
print ("Local Date:", \
local_date.strftime("%a, %d %b %Y %H:%M:%S"))
M = imaplib.IMAP4_SSL('imap.gmail.com')
rv, data = M.login(EMAIL_ACCOUNT, getpass.getpass())
print(rv, data)
rv, mailboxes = M.list()
rv, data = M.select(EMAIL_FOLDER)
print("Processing mailbox...\n")
process_mailbox(M)
M.close()
M.logout()
I am not able to fetch a gmail body using IMAP. I am successfully getting the subject name and from the email using IMAP.
How can I read the gmail body text?
Try:
msg = email.message_from_string(data[0][1])
print(msg['From'])
print(msg.get_payload(decode=True))
Also can check out:
Python : How to parse the Body from a raw email , given that raw email does not have a "Body" tag or anything
I have a piece of code to get emails from messages from my inbox (gmail). Getting emails work correct when I print email_from but I would like to do some operation on data split name and email etc. but then code broke after print first loop step and I got the error:
Traceback (most recent call last):
File "C:\Users\loc\Desktop\extract_gmail.py", line 24, in <module>
email_message_raw = email.message_from_bytes(data[0][1])
AttributeError: 'str' object has no attribute 'message_from_bytes'
Can you give me some advice how to solve this problem?
Code:
import imaplib
import email
from email.header import Header, decode_header, make_header
# Connection settings
HOST = 'imap.gmail.com'
USERNAME = '***'
PASSWORD = '***'
m = imaplib.IMAP4_SSL(HOST, 993)
m.login(USERNAME, PASSWORD)
m.select('INBOX')
result, data = m.uid('search', None, "ALL")
if result == 'OK':
for num in data[0].split()[:5]:
result, data = m.uid('fetch', num, '(RFC822)')
if result == 'OK':
# Get raw message
email_message_raw = email.message_from_bytes(data[0][1])
# Decode headers
email_from = str(make_header(decode_header(email_message_raw['From'])))
# Print each name and email
name, email = email_from.split('<')
email.replace(">", "")
print(name + "|" + email)
# When i swap to just print email_from then works
# print(email_from)
# Close server connection
m.close()
m.logout()
In your code you replaced the email variable..
Try this...
import imaplib
import email
from email.header import Header, decode_header, make_header
# Connection settings
HOST = 'imap.gmail.com'
USERNAME = '***'
PASSWORD = '***'
m = imaplib.IMAP4_SSL(HOST, 993)
m.login(USERNAME, PASSWORD)
m.select('INBOX')
result, data = m.uid('search', None, "ALL")
if result == 'OK':
for num in data[0].split()[:5]:
result, data = m.uid('fetch', num, '(RFC822)')
if result == 'OK':
# Get raw message
email_message_raw = email.message_from_bytes(data[0][1])
# Decode headers
email_from = str(make_header(decode_header(email_message_raw['From'])))
# Print each name and email
name, email_addr = email_from.split('<')
email_addr.replace(">", "")
print(name + "|" + email_addr)
# When i swap to just print email_from then works
# print(email_from)
# Close server connection
m.close()
m.logout()
I had the same error [happily solved], my mistake was in the shebang. That should point to python3.
#! /usr/bin/env python3
Here is my code:
conn = imaplib.IMAP4_SSL('imap.gmail.com')
conn.login('username', 'password')
conn.select()
typ, data = conn.search(None, "ALL")
parser1 = HeaderParser()
for num in data[0].split():
typ, data = conn.fetch(num, '(RFC822)')
header_data = str(data[1][0])
msg = email.message_from_string(header_data)
print(msg.keys())
print(msg['Date'])
Why am i getting "[]" for the printout of msg.keys() and "None" for the msg['Date']. No error messages. However, if i comment out the last 4 lines of code, and type print(data), then all the headers get printed? Im using python 3.4
conn.fetch returns tuples of message part envelope and data. For some reason -- I'm not sure why -- it may also return a string, such as ')'. So instead of hard-coding data[1][0], it's better (more robust) to just loop through the tuples in data and parse the message parts:
typ, msg_data = conn.fetch(num, '(RFC822)')
for response_part in msg_data:
if isinstance(response_part, tuple):
msg = email.message_from_string(response_part[1])
For example,
import imaplib
import config
import email
conn = imaplib.IMAP4_SSL("imap.gmail.com", 993)
conn.login(config.GMAIL_USER2, config.GMAIL_PASS2)
try:
conn.select()
typ, data = conn.search(None, "ALL")
print(data)
for num in data[0].split():
typ, msg_data = conn.fetch(num, '(RFC822)')
for response_part in msg_data:
if isinstance(response_part, tuple):
part = response_part[1].decode('utf-8')
msg = email.message_from_string(part)
print(msg.keys())
print(msg['Date'])
finally:
try:
conn.close()
except:
pass
finally:
conn.logout()
Much of this code comes from Doug Hellman's imaplib tutorial.
Update: my code works under python 2.6.5 but not python 3 (I'm using 3.4.1).
I'm unable to search for messages in the "All Mail" or "Sent Mail" folders - I get an exception:
imaplib.error: SELECT command error: BAD [b'Could not parse command']
my code:
import imaplib
m = imaplib.IMAP4_SSL("imap.gmail.com", 993)
m.login("myemail#gmail.com","mypassword")
m.select("[Gmail]/All Mail")
using m.select("[Gmail]/Sent Mail") doesn't work either.
But reading from the inbox works:
import imaplib
m = imaplib.IMAP4_SSL("imap.gmail.com", 993)
m.login("myemail#gmail.com","mypassword")
m.select("inbox")
...
I used the mail.list() command to verify the folder names are correct:
b'(\\HasNoChildren) "/" "INBOX"',
b'(\\Noselect \\HasChildren) "/" "[Gmail]"',
b'(\\HasNoChildren \\All) "/" "[Gmail]/All Mail"',
b'(\\HasNoChildren \\Drafts) "/" "[Gmail]/Drafts"',
b'(\\HasNoChildren \\Important) "/" "[Gmail]/Important"',
b'(\\HasNoChildren \\Sent) "/" "[Gmail]/Sent Mail"',
b'(\\HasNoChildren \\Junk) "/" "[Gmail]/Spam"',
b'(\\HasNoChildren \\Flagged) "/" "[Gmail]/Starred"',
b'(\\HasNoChildren \\Trash) "/" "[Gmail]/Trash"'
I'm following the solutions from these questions, but they don't work for me:
imaplib - What is the correct folder name for Archive/All Mail in Gmail?
I cannot search sent emails in Gmail with Python
Here is a complete sample program that doesn't work on Python 3:
import imaplib
import email
m = imaplib.IMAP4_SSL("imap.gmail.com", 993)
m.login("myemail#gmail.com","mypassword")
m.select("[Gmail]/All Mail")
result, data = m.uid('search', None, "ALL") # search all email and return uids
if result == 'OK':
for num in data[0].split():
result, data = m.uid('fetch', num, '(RFC822)')
if result == 'OK':
email_message = email.message_from_bytes(data[0][1]) # raw email text including headers
print('From:' + email_message['From'])
m.close()
m.logout()
The following exception is thrown:
Traceback (most recent call last):
File "./eport3.py", line 9, in <module>
m.select("[Gmail]/All Mail")
File "/RVM/lib/python3/lib/python3.4/imaplib.py", line 682, in select
typ, dat = self._simple_command(name, mailbox)
File "/RVM/lib/python3/lib/python3.4/imaplib.py", line 1134, in _simple_command
return self._command_complete(name, self._command(name, *args))
File "/RVM/lib/python3/lib/python3.4/imaplib.py", line 965, in _command_complete
raise self.error('%s command error: %s %s' % (name, typ, data))
imaplib.error: SELECT command error: BAD [b'Could not parse command']
Here's the corresponding Python 2 version that works:
import imaplib
import email
m = imaplib.IMAP4_SSL("imap.gmail.com", 993)
m.login("myemail#gmail.com","mypassword")
m.select("[Gmail]/All Mail")
result, data = m.uid('search', None, "ALL") # search all email and return uids
if result == 'OK':
for num in data[0].split():
result, data = m.uid('fetch', num, '(RFC822)')
if result == 'OK':
email_message = email.message_from_string(data[0][1]) # raw email text including headers
print 'From:' + email_message['From']
m.close()
m.logout()
As it's mentioned in this answer:
Try using m.select('"[Gmail]/All Mail"'), so that the double quotes get transmitted.
I suspect imaplib is not properly quoting the string, so the server gets what looks like two arguments: [Gmail]/All, and Mail.
And it works in python v3.4.1
import imaplib
import email
m = imaplib.IMAP4_SSL("imap.gmail.com", 993)
m.login("myemail#gmail.com","mypassword")
m.select('"[Gmail]/All Mail"')
result, data = m.uid('search', None, "ALL") # search all email and return uids
if result == 'OK':
for num in data[0].split():
result, data = m.uid('fetch', num, '(RFC822)')
if result == 'OK':
email_message = email.message_from_bytes(data[0][1]) # raw email text including headers
print('From:' + email_message['From'])
m.close()
m.logout()