How do I identify Outlook "message id" over imap/pop3 in Python? - python

Problem
I am using a "logic app" in Azure to create a queue of incoming mails. The way the emails are registered are using a "message id", which is described as "a unique identifier for a message". I would like to be able to fetch emails over imap using this id - is this possible?
Logic app "message id"
Example of "message id":
AQMkADAwATM3ZmYAZS0yNTYwLWNkZAAzLTAwAi0wMAoARgAAA-U4TGbG56lEtdoXy_23gW0HAKhWKDtf5AJErHyhh_b9NYQAAAIBDAAAAKhWKDtf5AJErHyhh_b9NYQAAAIFfgAAAA==
Example of logic app:
What I have tried
I have tried just to download all emails as eml, and then to read them into notepad++ to see if the "message id" even exists in the eml-files, but they don't.
# Library for downloading emails
import imaplib
# Logging in
mail = imaplib.IMAP4_SSL("outlook.office365.com",993)
mail.login(email_user, email_pass)
# Downloading emails to eml
mail.select('Inbox')
typ, data = mail.search(None, 'ALL')
for num in data[0].split():
typ, data = mail.fetch(num, '(RFC822)')
f = open('%s/%s.eml' %("/my/path/", num), 'wb')
f.write(data[0][1])
mail.close()
mail.logout()

May i know why are you trying to fetch email over IMAP . As you can fetch fetch email using message id from outlook api too. Here is the api which you can use:
GET https://outlook.office.com/api/v2.0/me/messages/{message_id}
You can find more details here:
https://learn.microsoft.com/en-us/previous-versions/office/office-365-api/api/version-2.0/mail-rest-operations#GetMessages
Also just to update , in outlook you wont' find the message id in .eml or in body, it's available in internet header. Most clients utilities download the headers (including the Message-ID) of all messages, store them, and then post-process them. For outlook you can find it in internet header like below:
Reference: https://www.codetwo.com/kb/messageid/
Still if you want to access email using IMAP, try below thread and see if it helps:
https://www.go4expert.com/articles/accessing-email-using-imap-python-t28838/
https://social.msdn.microsoft.com/Forums/en-US/29f44441-feda-4f81-a04c-40d53b3dfdc5/how-to-access-an-email-using-messageid-in-outlook?forum=outlookdev
Hope it helps.

Related

receiving emails with python api O365

I am just starting out in Python and I am trying to accomplish a manual task I have heard is on the simpler side to accomplish with python. My company uses Office 365 for their emails and I want to retrieve an email attachment and store it locally so I can save time . So far have established how to send a simple email, call the names of the folders in my account but I cannot figure out how to read any specific email .
my idea goes a little like this ,
from O365 import Account, message,mailbox
credentials = ('username', 'given password')
account = Account(credentials)
mailbox = account.mailbox()
mail_folder = mailbox.inbox_folder()
mail_folder = mailbox.get_folder(folder_name='Inbox')
print(mail_folder)
#_init__(*,parent= Inbox, con=None,**kwargs)
Message_body = message.body()
message.get_subject('email subject here!')
print(Message.body)
right now I am lost and trying anything within the O365 documentation page but the message module does not have the attribute subject according to how I am using it . Any guidance would be much appreciated
From your example - it's not clear if you are authenticated or not...
If you are then you will be able to list the mailbox folders. In the case below - you can access the inbox and then list the sub-folders:
from O365 import Account, Connection, MSGraphProtocol, Message, MailBox, oauth_authentication_flow
scopes=['basic', 'message_all']
credentials=(<secret>, <another secret>)
account = Account(credentials = credentials)
if not account.is_authenticated: # will check if there is a token and has not expired
account.authenticate(scopes=scopes)
account.connection.refresh_token()mailbox = account.mailbox()
inbox = mailbox.get_folder(folder_name='Inbox')
child_folders = inbox.get_folders(25)
for folder in child_folders:
print(folder.name, folder.parent_id)
This part will allow you to list folders (and also messages).
If I look at your code - it looks as though you are trying to do both?
Try doing something like the following to get the hang of paging through your inbox:
for message in inbox.get_messages(5):
if message.subject == 'test':
print(message.body)
Note that I'm looping through the first 5 messages in the inbox looking for a message with subject 'test'. If it finds the message - then it prints the body.
Hopefully this will shed a little light.

How to attach a calendar invite to SES send_raw_email?

I use send_raw_email to send emails with HTML content and file attachments. How do I insert an ical/ics invite to the email?
I use icalendar to generate ics content.
This is what I came up with so far, but it shows in Gmail as a file attachment.
if calendar_reminder_date:
cal = Calendar()
cal.add('prodid', '-//My calendar product//mxm.dk//')
cal.add('version', '2.0')
cal.add('calscale', 'GREGORIAN')
cal.add('method', 'REQUEST')
event = Event()
event['dtstart'] = calendar_reminder_date.strftime("%Y%m%dT%H%M%SZ")
event['dtstamp'] = calendar_reminder_date.strftime("%Y%m%dT%H%M%SZ")
event['summary'] = 'Python meeting about calendaring'
cal.add_component(event)
attachment_part = MIMEText(cal.to_ical())
print repr(cal.to_ical())
del attachment_part['Content-Type']
attachment_part.add_header('Content-Type', 'text/calendar', name='invite.ics')
attachment_part.add_header('Content-Disposition', 'attachment', filename='invite.ics')
msg.attach(attachment_part)
Hard to tell without seeing the actual full MIME message as received on the Google side but there are definitely several things missing here:
a calendar REQUEST must have an ORGANIZER property, as well as at least one ATTENDEE property with a value corresponding to the email address of the gmail user (prefixed with a mailto:).
your content-type is missing a METHOD=REQUEST parameter and you probably do not want to set any content-disposition.
See also Multipart email with text and calendar: Outlook doesn't recognize ics

How to send myself an email notification when a suds job is done?

I'm learning to use suds in a python script to send SQL queries to a database. I'd like to able to send myself an email when the query job is finished (it has a job ID so I'm able to check its status). How do I do that?
This is how you send an email via python just fill in the blanks and input it to your code:
import smtplib
content = ("Content to send")
mail = smtplib.SMTP('smtp.gmail.com',587)
mail.ehlo()
mail.starttls()
mail.login('your_email#gmail.com','123your_password')
mail.sendmail('your_email#gmail.com','destination_email#gmail.com',content)
mail.close()
print("Sent")
(you dont have to use gmail as most addresses will still work through the gmail smtp)
If email is not required, you can also send chat messages to yourself.
Two projects achieving this :
Nimrod, for Facebook Messenger : https://www.nimrod-messenger.io/
Telegram Middleman, for Telegram : https://github.com/n1try/telegram-middleman-bot
I just wrote a Python decorator for this purpose. You can realize it in one line.
https://github.com/Wenzhi-Ding/py_reminder
from py_reminder import monitor
#monitor('SQL Query of xxx')
def query(sql):
...send your query...
query()
Once this function finishes / or is caught an error, you will get an email notification with some brief information.

Check unread count of Gmail messages with Python

How can I check the number of unread Gmail message in my inbox with a short Python script? Bonus points for retrieving the password from a file.
import imaplib
obj = imaplib.IMAP4_SSL('imap.gmail.com','993')
obj.login('username','password')
obj.select()
obj.search(None,'UnSeen')
Well, I'm going to go ahead and spell out an imaplib solution as Cletus suggested. I don't see why people feel the need to use gmail.py or Atom for this. This kind of thing is what IMAP was designed for. Gmail.py is particularly egregious as it actually parses Gmail's HTML. That may be necessary for some things, but not to get a message count!
import imaplib, re
conn = imaplib.IMAP4_SSL("imap.gmail.com", 993)
conn.login(username, password)
unreadCount = re.search("UNSEEN (\d+)", conn.status("INBOX", "(UNSEEN)")[1][0]).group(1)
Pre-compiling the regex may improve performance slightly.
I advise you to use Gmail atom feed
It is as simple as this:
import urllib
url = 'https://mail.google.com/mail/feed/atom/'
opener = urllib.FancyURLopener()
f = opener.open(url)
feed = f.read()
You can then use the feed parse function in this nice article: Check Gmail the pythonic way
For a complete implementation of reading the value from the atom feed:
import urllib2
import base64
from xml.dom.minidom import parse
def gmail_unread_count(user, password):
"""
Takes a Gmail user name and password and returns the unread
messages count as an integer.
"""
# Build the authentication string
b64auth = base64.encodestring("%s:%s" % (user, password))
auth = "Basic " + b64auth
# Build the request
req = urllib2.Request("https://mail.google.com/mail/feed/atom/")
req.add_header("Authorization", auth)
handle = urllib2.urlopen(req)
# Build an XML dom tree of the feed
dom = parse(handle)
handle.close()
# Get the "fullcount" xml object
count_obj = dom.getElementsByTagName("fullcount")[0]
# get its text and convert it to an integer
return int(count_obj.firstChild.wholeText)
Well it isn't a code snippet but I imagine using imaplib and the Gmail IMAP instructions get you most of the way there.
Once you are logged in (do this manually or with gmail.py) you should use the feed.
It is located here:
http://mail.google.com/mail/feed/atom
It is the way Google does it. Here is a link to their js chrome extension:
http://dev.chromium.org/developers/design-documents/extensions/samples/gmail.zip
You will then be able to parse xml that looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#">
<title>Gmail - Inbox for yourmail#gmail.com</title>
<tagline>New messages in your Gmail Inbox</tagline>
<fullcount>142</fullcount>
I didn't like the existing solutions so I decided to make a sister library for my email sender called Red Box.
It has a pre-configured gmail instance:
from redbox import gmail
# Configure Gmail
gmail.username = "example#gmail.com"
gmail.password = "<PASSWORD>"
# Select inbox folder
inbox = gmail.inbox
# Get unread emails
msgs_unread = inbox.search(seen=False)
# Print unread count
print(len(msgs_unread))
Red Box fetches the email contents only when needed. The above does not do that as we didn't access the contents of these messages. You can also easily access various parts of the messages if you need.
I also wrote how to configure Gmail's app password here:
To install:
pip install redbox
Links:
Source code
Documentation
Use Gmail.py
file = open("filename","r")
usr = file.readline()
pwd = file.readline()
gmail = GmailClient()
gmail.login(usr, pwd)
unreadMail = gmail.get_inbox_conversations(is_unread=True)
print unreadMail
Gets login information from a text file assuming the login name and password are on separate lines.

Select mails from inbox alone via poplib

I need to download emails from the gmail inbox only using poplib.Unfortunately I do not see any option to select Inbox alone, and poplib gives me emails from sent items too.
How do I select emails only from inbox?
I dont want to use any gmail specific libraries.
POP3 has no concept of 'folders'. If gmail is showing you both 'sent' as well as 'received' mail, then you really don't have any option but to receive all that email.
Perhaps you would be better off using IMAP4 instead of POP3. Python has libraries that will work with gmail's IMAP4 server.
I assume you have enabled POP3/IMAP access to your GMail account.
This is sample code:
import imaplib
conn= imaplib.IMAP4_SSL('imap.googlemail.com')
conn.login('yourusername', 'yourpassword')
code, dummy= conn.select('INBOX')
if code != 'OK':
raise RuntimeError, "Failed to select inbox"
code, data= self.conn.search(None, ALL)
if code == 'OK':
msgid_list= data[0].split()
else:
raise RuntimeError, "Failed to get message IDs"
for msgid in msgid_list:
code, data= conn.fetch(msgid, '(RFC822)')
# you can also use '(RFC822.HEADER)' only for headers
if code == 'OK':
pass # your code here
else:
raise RuntimeError, "could not retrieve msgid %r" % msgid
conn.close()
conn.logout()
or something like this.
This Java code would suggest that you can select a particular "folder" to download, even when using POP3. Again, this is using Java, not Python so YMMV.
How to download message from GMail using Java (blog post discusses pushing content into a Lucene search engine locally)

Categories

Resources