I am trying to download attachments from Outlook using Python, as of now am able to download the attachments by subject line but in my case I want to download multiple attachments from multiple emails where subject line starts with some string, For Ex:
Subjects are: Query 123654, Query 56975, Query 5698 like this and I want to download all of them where subject name starts with "Query".
My current code is below:
from win32com.client import Dispatch
outlook = Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox = outlook.GetDefaultFolder("6")
all_inbox = inbox.Items
val_date = datetime.date.today()
sub_today = 'Query 123654'
att_today = ''
for msg in all_inbox:
if msg.Subject == sub_today and msg.Senton.date() == val_date:
break
for att in msg.Attachments:
if att.FileName == att_today:
break
try:
att.SaveAsFile('C:\\Offline Feeds\\Attachments' + '\\'+ att.FileName)
messagebox.showinfo("SUCCESSFUL","Attachments Downloaded")
except:
messagebox.showerror("ERROR","Attachment Download Failed")
You could use find() to search specific data.
sub_today = 'Query'
if msg.Subject.find(sub_today) != -1 break
If subject not include “Query”, it will return “-1”.
This is the complete code:
from win32com.client import Dispatch
outlook = Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox = outlook.GetDefaultFolder("6")
all_inbox = inbox.Items
val_date = datetime.date.today()
sub_today = 'Query'
att_today = ''
for msg in all_inbox:
if msg.Subject.find(sub_today) != -1 and msg.Senton.date() == val_date:
break
for att in msg.Attachments:
if att.FileName == att_today:
break
try:
att.SaveAsFile('C:\\Offline Feeds\\Attachments' + '\\'+ att.FileName)
messagebox.showinfo("SUCCESSFUL","Attachments Downloaded")
except:
messagebox.showerror("ERROR","Attachment Download Failed")
For more information, please refer to this link:
Python String find() Method
Related
I have the below code, which downloads a Gmail email and its attachments. It returns its attachments.
def gmailAPIDownloadAttachments(self, messageID, userID="me"):
try:
service = self.gmailAPIService
self.GLogger.info("Attempting to download attachments from messageID (" +str(messageID)+ ")")
message = self.gmailAPIGetFullMessage(messageID, userID=userID)
if message is False:
self.GLogger.error("Failed to extract message (" +str(messageID)+ ") for downloading attachments")
return False
attachmentList = list()
payload = message['payload']
if 'parts' in payload:
parts = payload['parts']
for part in parts:
if part['filename']:
if 'data' in part['body']:
data = part['body']['data']
else:
att_id = part['body']['attachmentId']
att = service.users().messages().attachments().get(userId=userID, messageId=messageID, id=att_id).execute()
data = att['data']
file_data = base64.urlsafe_b64decode(data.encode('UTF-8'))
filename = part['filename']
extSearch = filename.find('.')
if extSearch == -1:
ext = ""
partFileName = filename[0:extSearch]
else:
ext = filename[extSearch+1:]
partFileName = filename[0:extSearch]
theAttachment = Attachment(filename,partFileName, ext, file_data)
attachmentList.append(theAttachment)
self.GLogger.info("Successfully downloaded attachments from messageID (" +str(messageID)+ ")")
return(attachmentList)
except:
self.GLogger.error("Encountered an error while attempting to download email attacments from messageID (" +str(messageID)+ ")")
tb = traceback.format_exc()
self.GLogger.exception(tb)
return False
I understand how to convert fetching messages into batching. For example, this is how one could batch-fetch messages:
from apiclient.http import BatchHttpRequest
import json
batch = BatchHttpRequest()
#assume we got messages from Gmail query API
for message in messages:
batch.add(service.users().messages().get(userId='me', id=message['id'],
format='raw'))
batch.execute()
for request_id in batch._order:
resp, content = batch._responses[request_id]
message = json.loads(content)
#handle your message here, like a regular email object
However, the attachments aspect seem to have logic and other possible fetches such as in this part:
att_id = part['body']['attachmentId']
att = service.users().messages().attachments().get(userId=userID, messageId=messageID, id=att_id).execute()
data = att['data']
How can I effectively batch both fetching the message and its attachments? I would like to be able to quickly fetch many emails at once.
I am new to python. I am trying to save all the attachment from the email without specifying the attachment name from the outlook.
We need to download the attachment with the subject name.
because attachment can come in any name and also i need to download the attachment only for past 2 days.
Could anyone help me. Below is my code
from win32com.client import Dispatch
import time
import datetime
import re
outlook = Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox = outlook.GetDefaultFolder("6")
all_inbox = inbox.Items
val_date = datetime.date.today()
sub_today = 'test4'
att_today = '20201018_2.xlsx'
#att_today = re.match(regex_, )
for msg in all_inbox:
if msg.Subject.find(sub_today) != -1 and msg.SentOn.date() == val_date:
break
for att in msg.Attachments:
if att.FileName == att_today:
print(att_today)
break
try:
print(att.FileName)
#att.SaveAsFile("C:/Users/Shwettha/Downloads/attachment/"+ att.FileName)
att.SaveAsFile(os.path.join("D:\Script\Monitoring",att.FileName))
print("SUCCESSFUL","Attachments Downloaded")
except:
print("ERROR","Attachment Download Failed")
In my outlook, I have 2 accounts(account 1 and account 2). Account 1 is the default account.
I am trying to read the email from the account 2 from the python code. I tried different approach, but it did not work.
Am posting a my code where it reads from my default account. Could you please help me to read the emails from the account 2(which is not default)
from win32com.client import Dispatch
import time
import datetime
import re
outlook = Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox = outlook.GetDefaultFolder("6")
all_inbox = inbox.Items
val_date = datetime.date.today()
sub_today = 'test4'
att_today = '20201018_2.xlsx'
#att_today = re.match(regex_, )
for msg in all_inbox:
if msg.Subject.find(sub_today) != -1 and msg.SentOn.date() == val_date:
break
for att in msg.Attachments:
if att.FileName == att_today:
print(att_today)
break
try:
print(att.FileName)
#att.SaveAsFile("C:/Users/Shwettha/Downloads/attachment/"+ att.FileName)
att.SaveAsFile(os.path.join("D:\Script\Monitoring",att.FileName))
print("SUCCESSFUL","Attachments Downloaded")
except:
print("ERROR","Attachment Download Failed")
Try setting your inbox like the following
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox = outlook.Folders["0m3r#Email.com"].Folders["Inbox"]
Or use GetSharedDefaultFolder method (Outlook)
import win32com.client
Outlook = win32com.client.Dispatch("Outlook.Application")
olNs = Outlook.GetNamespace("MAPI")
Recip = olNs.CreateRecipient("0m3r#Email.com")
Recip.Resolve()
shared_inbox = olNs.GetSharedDefaultFolder(Recip, "6")
for Item in shared_inbox.Items:
print(Item.Subject)
I have gotten some of the features I want but need help with 2 others.
I would like to flag the message "Mark as Done" (it's one of the Flag statuses). I have not found how to do this.
If I wanted to do this same thing for 4 other emails how would I do it, with 4 other save paths?
import win32com.client
import os
Outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
inboxfolder = Outlook.GetDefaultFolder(6) # "6" refers to the index of a folder - in this case the inbox. You can change that number to reference
inbox = inboxfolder.Items
message = inbox.GetFirst()
subject = message.Subject
sender = message.SenderEmailAddress
for m in inbox:
if m.Class == 43: # this is to make sure it is an email item and not something else.
if m.SenderEmailAddress == 'John#email.com' and m.Unread == True:
path = 'C:\\User\\Path\\Data\\John'
print ('Subject as: ' and message)
for attached in message.Attachments:
attached.SaveASFile(os.path.join(path,attached.FileName)) #Saves attachment to current folder
print (attached)
message.Unread = False
print (message.FlagStatus)
message.FlagStatus = 1 # This is to "mark as Done" but it doesn't work
message = inbox.GetNext()
elif m.SenderEmailAddress == 'Jane#email.com' and m.Unread == True:
path = 'C:\\User\\Path\\Data\\Jane'
# ... How would you add 4 more?
message = inbox.GetNext()
else:
message = inbox.GetNext()
You have to save it message.Save(), Example
import win32com.client
Outlook = win32com.client.Dispatch("Outlook.Application")
olNs = Outlook.GetNamespace("MAPI")
Inbox = olNs.GetDefaultFolder(win32com.client.constants.olFolderInbox)
for Item in Inbox.Items:
if Item.Class == 43:
Item.FlagStatus = 1
Item.Save()
For multiple emails & path use dictionary, Example
emails_with_path = {
"email#one.com": "path_one",
"email#two.com": "path_two",
"email#three.com": "path_three"
}
for m in inbox:
if m.Class == 43:
for email, path in emails_with_path.items():
if m.SenderEmailAddress == email and m.UnRead:
print(email)
print(path)
I want to fetch all the emails from gmail of a particular label called important. I am using imaplib and python 2.
Below is my code,
import email, getpass, imaplib, os
detach_dir = '.'
user = raw_input("Enter your GMail username:")
pwd = getpass.getpass("Enter your password: ")
# connecting to the gmail imap server
m = imaplib.IMAP4_SSL("imap.gmail.com")
m.login(user,pwd)
m.select("important")
resp, items = m.search(None, "ALL")
items = items[0].split()
print len(items)
for emailid in items:
resp, data = m.fetch(emailid, "(RFC822)")
email_body = data[0][1]
mail = email.message_from_string(email_body)
if mail.get_content_maintype() != 'multipart':
continue
print "["+mail["From"]+"] :" + mail["Subject"]
for part in mail.walk():
if part.get_content_maintype() == 'multipart':
continue
if part.get('Content-Disposition') is None:
continue
filename = mail["From"] + "_hw1answer"
att_path = os.path.join(detach_dir, filename)
if not os.path.isfile(att_path) :
fp = open(att_path, 'wb')
fp.write(part.get_payload(decode=True))
fp.close()
The error is showing,
imaplib.error: command SEARCH illegal in state AUTH, only allowed in states SELECTED
But, if I use INBOX then it is working.
Working when m.select("inbox")
What is the recommended way to achieve it ?
m.select("important") failed.
If you want the special starred folder, it is probably named "[Gmail]/Important". Use the list() command to find the names used by the server.