I want to do a "simple" task in Outlook, with a Python script, but I'm usually in PHP and it's a little bit difficult for me.
Here is the task:
Open Outlook (it's ok for that)
Check a specific account, example: test#test.com
Open the last mail
I want to open the "real" message windows at screen, not just to access to the content.
Is it possible?
For your second requirement, could the account be a shared inbox?
Here is the code for the rest:
import win32com.client
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox = outlook.GetDefaultFolder(6)
messages = inbox.Items
message = messages.GetLast()
message.display()
Here is another example with exchangelib in python:
https://medium.com/#theamazingexposure/accessing-shared-mailbox-using-exchangelib-python-f020e71a96ab
Here is the snippet to get the last email. I did it using a combination of order by and picking the first one or the last one depending on how you order by:
from exchangelib import Credentials, Account, FileAttachment
credentials = Credentials('FirstName.LastName#Some_Domain.com', 'Your_Password_Here')
account = Account('FirstName.LastName#Some_Domain.com', credentials=credentials, autodiscover=True)
filtered_items = account.inbox.filter(subject__contains='Your Search String Here')
print("Getting latest email for given search string...")
for item in account.inbox.filter(subject__contains='Your Search String Here').order_by('-datetime_received')[:1]: #here is the order by clause:: you may use order_by('datetime_received')[:-1]
print(item.subject, item.text_body.encode('UTF-8'), item.sender, item.datetime_received) #item.text_body.encode('UTF-8') gives you the content of email
while trying to open the real message might be a bit of a challenge but I will update this section once I have a solution. If I may ask:: are you looking at a python only solution ?
Related
I am using Pywin32 and win32com to programmatically create and save Outlook MSG files. (These are emails that will only ever be saved and never be sent across smtp.) I am able to create and save the emails, but it only works when the display() method is used. This is problematic because it creates and opens the actual Outlook email in the GUI.
When I comment out the display() method, the email message save method just runs forever and yields zero in the debug console and the email is neither created or saved.
The appearance of the Outlook emails in the GUI is not desirable as I will later programmatically create thousands of messages and cannot have them all opening in the GUI. (and having to close them!)
edit: I've done some research here display method and here .net mail class but have not found a way to suppress the GUI display of the email.
How can I create the emails to disk as msg files without them appearing in the Windows GUI as Outlook emails? Code as follows. Thank you.
import sys
import win32com.client as client
MSG_FOLDER_PATH = "d:\\Emails_Msg\\"
html_body = """
<div>
Test email 123
</div><br>
"""
recipient = "johndoe#foo.com"
cc = "janedoe#foo.com"
outlook = client.Dispatch("outlook.application")
message = outlook.CreateItem(0)
message.To = recipient
message.CC = cc
message.Subject = "foo1"
message.HTMLBody = html_body
# message display method
message.Display()
# save the message, only works if message.Display() runs
message_name = MSG_FOLDER_PATH + "foo.msg"
message.SaveAs(message_name)
The problem was that Outlook was not opened in the Windows Server. (The simple things at times!) Once it is opened, the display method is no longer needed and emails are written directly to disk.
My Python code below runs but doesn't delete selected emails that I'm expecting to be deleted from my test gamil\inbox. I'm not sure what am I doing wrong here. I will really appreciate any help.
import imaplib
import datetime
m = imaplib.IMAP4_SSL("imap.gmail.com") # server to connect to
print("{0} Connecting to mailbox via IMAP...".format(datetime.datetime.today().strftime("%Y-%m-%d %H:%M:%S")))
m.login('bb_xxxxx#gmail.com', 'gmail_pass')
print("{0} Searching Inbox by sender...".format(datetime.datetime.today().strftime("%Y-%m-%d %H:%M:%S")))
m.select('Inbox') #select folder to search
status, messages = m.search(None, 'FROM "location-history-noreply#google.com"') # search for specific mails by sender
print("{0} Flagging selected mail as deleted...".format(datetime.datetime.today().strftime("%Y-%m-%d %H:%M:%S")))
for mail in messages[0].split():
m.store(mail, "+FLAGS", "\\Deleted")
m.expunge()
print("{0} Done. Closing connection & logging out.".format(datetime.datetime.today().strftime("%Y-%m-%d %H:%M:%S")))
m.close()
m.logout()
Do not run expunge until you are out of the for loop. expunge renumbers the message ids, so the numbers you have from your search do not correspond anymore.
So:
for mail in messages[0].split():
m.store(mail, "+FLAGS", "\\Deleted")
m.expunge()
This is one of the reasons why it is a separate operation. Or use UIDs everywhere.
Also, on gmail, deleting does not actually delete messages. It only marks it as removed from that Label (inbox). If you want to actually delete it, you need to move it to the Trash folder, then delete it from there.
Thanks a lot Max! Your answer helped me fixing my problem. However, if I use "\Deleted" then I see messages are removed from the inbox but still available in "All Mail" folder. Does this mean they are permanently deleted? So I tried using as below with moving to "Trash" now messages are removed from the inbox but moved to "Trash".
for mail in messages[0].split():
#m.store(mail, "+FLAGS", "\\Deleted")
m.store(mail, '+X-GM-LABELS', '\\Trash')
m.expunge()
I'm trying to get date related info from messages that Python retrieves from Outlook but for some weird reason I cannot.
It is strange because I can obtain all info about sender, email body, subject, cc, bc, attachment etc. but when it comes to properties like SentOn, CreationTime or LastModificationTime IDLE just restarts (without any warnings, errors and exceptions).
Here is sample code:
import win32com.client
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox = outlook.GetDefaultFolder(6) # "6" refers to the index of a folder - in this case,
# the inbox. You can change that number to reference
# any other folder
messages = inbox.Items
message = messages.GetLast()
rec_time = message.CreationTime
body_content = message.body
subj_line = message.subject
print(rec_time, body_content, subj_line)
Output:
>>>
================= RESTART: C:/Users/XXXXX/Desktop/email.py =================
=============================== RESTART: Shell ===============================
>>>
And here outpoot when CreationTime is commented out:
Hi,
I really think that it is weird that win32 cannot read date info
Your sincerely,
Myself
Andrew
Python ver 3.7, Outlook 2016
Just tried your code and it worked with no issues. Assuming you have taken some general troubleshooting steps, i.e., restart your computer, etc. I would recommend the following steps:
Close all instances of outlook
Run Outlook in safe mode by pressing Windows Key + R and this dialog appears
input outlook /safe just as its shown in the image (above). Attempt to run your script (opening outlook in safe mode ensures no Outlook add-ins/configurations interfere)
If this doesn't work, I would recommend using a debugger (VSCode for example) and running line by line to see where your script is terminating. You shared a sample code, but if you have additional code that you didn't share - only assumptions can be made from my end, but you may have something causing this issue in your script.
I have a instrument at work that emails me a file containing raw data, I can go into my email and download them easily enough but when I have multiple files (which it sends as multiple emails) it gets a bit tedious.
I'm looking at using python and imaplib to login to my email account, search for emails from a known email address within the past day or so and then download any attachments to a directory. So I thought a script might help here.
I've setup a gmail account and altered the settings so that I can connect using imap from a shell, however I'm lost as to where to go from here.
Could someone point me in the right direction as to what I need to do to make this happen.
Here is a repository that is forked off imaplib (made compatible with Python3.6, did not test other versions)
https://github.com/christianwengert/mail
The following snippet checks all unseen messages, then returns their attachments:
server = IMAPClient(imap, use_uid=True, ssl=993)
server.login(username, password)
server.select_folder('INBOX')
message_ids = server.search([b'NOT', b'SEEN']) # UNSEEN
messages = server.fetch(message_ids, data=['ENVELOPE', 'BODYSTRUCTURE', 'RFC822.SIZE'])
for mid, content in messages.items():
bodystructure = content[b'BODYSTRUCTURE']
text, attachments = walk_parts(bodystructure, msgid=mid, server=server)
HTH
I am trying to access the Chat Folder using imaplib but am not able to do so. The code mail.select("Chats") doesn't work since "chats" is not actually a label.
How do I access the emails in the Chats folder?
any folder you want to access by imap. it should be allowed by mail server.
e.g : for gmail, check below image for, how to set access of imap.
here, "Show in IMAP" should be checked for "Chats" folder.
then after, try below code snippets:
sock = imaplib.IMAP4_SSL("imap.gmail.com", 993)
sock.login("your Email Id", "Password")
lb_list = sock.list() # print
#search for "Chats" folder and its signature
#here, it is "[Gmail]/Chats"
sock.select("[Gmail]/Chats", True)
sock.search(None, '(ALL)')
resp, data = sock.fetch('1:*', '(RFC822)')
Hope, it will be helpful.