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)])')
Related
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.
I'd like to delete email from specific sender with python.
Here is my codes to delete all emails from my email account.
Question 1) How can I delete specific emails from specific sender? (ex: anyspamsender#gmail.com)
Question 2) How can I delete specific emails of which email title contains specific text ? (title : Delivery Status Notification (Failure))
import imaplib
box = imaplib.IMAP4_SSL('imap.gmail.com', 993)
box.login("emailid","password")
box.select('Inbox')
typ, data = box.search(None, 'ALL')
for num in data[0].split():
box.store(num, '+FLAGS', '\\Deleted')
box.expunge()
box.close()
box.logout()
I got it
typ, data = box.search(None, 'from','mailer-daemon#googlemail.com')
I am sending marketing emails through sendgrid smtp api via python EmailMultiAlternatives. I want to know how can I handle bounces directly from there to mark particular emails as undeliverable.
The code snippet is:
def send1():
text_content = 'Hi this is the text version'
connection = get_connection(host=EMAIL_HOST,
port=EMAIL_PORT,
username=EMAIL_HOST_USER,
password=EMAIL_HOST_PASSWORD,
use_tls=EMAIL_USE_TLS)
connection.open()
subject = 'Inviting {0} to join the Business Network of SMEs'.format('surya')
html_content = template.format('Surya')
from_email = 'sp#abc.com'
to = 'abc#gmail.com'
msg = EmailMultiAlternatives(subject, text_content, from_email, [to], connection=connection)
msg.attach_alternative(html_content, "text/html")
msg.send()
connection.close()
Is it possible to get the response here only after msg.send() or is there some other way.
The best way to respond to events like blocks and bounces is to implement the event webhook.
You can also poll for the data via the bounces endpoint.
So, For those who might be looking for a solution:
I am using imaplib python package to scrape the inbox (of the mail id through which i am sending the emails) everyday for bounced emails and complaints to get those unwanted emails.
def bounce():
M = imaplib.IMAP4_SSL('imap.zoho.com')
M.login('email#emailcom', password)
M.select()
line = '(HEADER Subject "Bounce")'
typ, data = M.uid('search', line)
if typ != 'OK':
return
print(len(data[0].split()))
for i in data[0].split():
result, data = M.uid('fetch', i, '(RFC822)')
raw_email = data[0][1].decode('utf-8', 'ignore')
emg = email.message_from_string(raw_email)
w = get_first_text_block(emg)
emails = re.findall(r"[a-z0-9\.\-+_]+#[a-z0-9\.\-+_]+\.[a-z]+", str(w), re.I)
So Executing the code everyday or every hour will help you.
You can also use sendgrid. The below was written using version 6.4.1.
import sendgrid
sg = sendgrid.SendGridAPIClient(api_key="<your_key>")
payload = {
"limit": 100,
"offset": 0,
}
response = sg.client.suppression.bounces.get(query_params=payload)
query_params can be omitted to accept the defaults, there's also start_time and end_time available (need to be integer Unix times).
I've been writing automated tests for a web application and it involves sending emails not just for account creation and password resets, but as the premise for the actual product it sends emails with virtual documents.
As part of my tests I obviously need to check that these emails contain certain elements eg. link to sign up, link to documents etc.
I have written some python code (for the gmail atom feed) that would just find and print the title of each email and if their is a link print that too but it cannot find the link.
import urllib2
import untangle
FEED_URL = 'https://mail.google.com/mail/feed/atom'
def get_unread_msgs(user, passwd):
auth_handler = urllib2.HTTPBasicAuthHandler()
auth_handler.add_password(
realm='New mail feed',
uri='https://mail.google.com',
user='{user}#gmail.com'.format(user=user),
passwd=passwd
)
opener = urllib2.build_opener(auth_handler)
urllib2.install_opener(opener)
feed = urllib2.urlopen(FEED_URL)
return feed.read()
if __name__ == "__main__":
import getpass
user = raw_input('Username: ')
passwd = getpass.getpass('Password: ')
xml = get_unread_msgs(user, passwd)
o = untangle.parse(xml)
try:
for item in o.feed.entry:
title = item.title.cdata
print title
link = item.link.cdata
if link:
print "Link"
print ' ', link
except IndexError:
pass # no new mail
Edit: I've just realised that the atom feed doesn't actually give the message data..
Could anyone please suggest an alternative method of achieving my goal?
You could access the messages via imaplib instead:
import imaplib
def get_unread_msgs(user, passwd):
M = imaplib.IMAP4_SSL('imap.gmail.com')
M.login(user, passwd)
try:
M.select()
try:
type, data = M.search(None, '(UNSEEN)')
for num in data[0].split():
yield M.fetch(num, '(RFC822)')
finally:
M.close()
finally:
M.logout()
You will need to enable IMAP in your gmail settings if you haven't already:
Get started with IMAP and POP3
If you are looking for a (gmail specific) solution without polling the server for updates, you can look into the Gmail Notifications API.
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()