win32com.client to send different attachments instead of fixed file path - python

I am able to send email to different recipients on outlook with below script for single attachment, but if I try to send different attachments to each user using for loop, then it fails.
Currently the script is using attachment = r'C:\Users\roy\Royfile.csv'. But I want attachment = file, so that the attachment changes in each for loop for different users. This part is not working.
Different files for different users, example Royfile.csv below. But there are 50 more such files.
Folder FolderOwner EmailAddress AttachmentPath
C:\folder1\ Roy Roy#gmail.com Royfile.csv
D:\folder2\ Roy Roy#gmail.com Royfile.csv
2nd file in same folder Jackfile.csv:
Folder FolderOwner EmailAddress AttachmentPath
C:\folder3\ Jack Jack#gmail.com Jackfile.csv
D:\folder4\ Jack Jack#gmail.com Jackfile.csv
3rd file for example Mandyfile.csv. And same way total 50 files for 50 users in same folder.
Folder FolderOwner EmailAddress AttachmentPath
C:\folder5\ Mandy Mandy#gmail.com Mandyfile.csv
D:\folder6\ Mandy Mandy#gmail.com Mandyfile.csv
Python Script
import glob, as
import win32com.client as win32
import pandas as pd
for file in glob.glob("*file.csv"):
print(file)
email_list = pd.read_csv(file)
names = email_list['FolderOwner']
emails = email_list['EmailAddress']
attachments = email_list['AttachmentPath']
for i in range(len(emails)):
print(file)
name = names[i]
email = emails[i]
attachment = r'{}.csv'.format(attachments)
with open(attachment, 'r') as my_attachment:
myfile = my_attachment.read()
outlook = win32.Dispatch('outlook.application')
mail = outlook.CreateItem(0)
mail.To = email
mail.Subject = 'Message subject'
mail.Body = 'Hello ' + name
mail.Attachments.Add(attachment)
mail.Send()
break
Current output of the script if I remove the attachment part:
Royfile.csv
Royfile.csv
Jackfile.csv
Jackfile.csv
Mandyfile.csv
Mandyfile.csv
...
..
.
Struggling now with what needs to be for attachment = ???. So that each file gets sent to 50 users.

I don't know how your files named how they are distributed in different folders, try to put their all names along with paths in excel sheet in one column and iterate through them the way you are doing for names and mails
attachment = r'{}.csv'.format(filepaths from excel sheet)
with open(attachment, 'r') as my_attachment:
myfile = my_attachment.read()

Found answer for my question finally, below is full code.
The error was coming, as there was PATH missing.
win32com lib need full path even if the script is running in same folder as the attachments.
works perfectly now. :)
import glob, as
import win32com.client as win32
import pandas as pd
for file in glob.glob("*file.csv"):
print(file)
email_list = pd.read_csv(file)
names = email_list['FolderOwner']
emails = email_list['EmailAddress']
attachments = email_list['AttachmentPath']
PATH = "C:\\Users\\roy\\myfolder\\"
for i in range(len(emails)):
print("Sending email with " + file)
name = names[i]
email = emails[i]
attachment = attachments[i]
attachment1 = PATH + attachment
with open(attachment1, 'r') as my_attachment:
myfile = my_attachment.read()
outlook = win32.Dispatch('outlook.application')
mail = outlook.CreateItem(0)
mail.To = email
mail.Subject = 'Message subject'
mail.Body = 'Hello ' + name
mail.Attachments.Add(attachment1)
mail.Send()
break

Related

How to Rename Attachments from outlook msg (.msg files) with the msg file name it self (string before .msg) with Python

I have a folder that has nearly 12k (.msg) files each has a csv attachment.
I managed to get a code to extract the attachment from each .msg file. but due to attachment and subjects are similar the attachment keeps getting over written! I tried to rename with msg.subject but the subject of the msg is similar
import win32com.client
import os
inputFolder = r'directory with my msg' ## Change here the input folder
outputFolder = r'directiry for attachments' ## Change here the attachments output folder
for file in os.listdir(inputFolder):
if file.endswith(".msg"):
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
filePath = inputFolder + '\\' + file
msg = outlook.OpenSharedItem(filePath)
att = msg.Attachments
for i in att:
i.SaveAsFile(os.path.join(outputFolder, str(msg.subject + ".csv")))
#Saves the file with the attachment name
You need to find an algorithm which allows identifying attachments uniquely - try to combine the attachment file name with email data such as ReceivedTime and etc.
Don't forget to exclude forbidden symbols from the result file name before trying to save the attachment.

Sending attachments with python tkinter [duplicate]

I am able to send email to different recipients on outlook with below script for single attachment, but if I try to send different attachments to each user using for loop, then it fails.
Currently the script is using attachment = r'C:\Users\roy\Royfile.csv'. But I want attachment = file, so that the attachment changes in each for loop for different users. This part is not working.
Different files for different users, example Royfile.csv below. But there are 50 more such files.
Folder FolderOwner EmailAddress AttachmentPath
C:\folder1\ Roy Roy#gmail.com Royfile.csv
D:\folder2\ Roy Roy#gmail.com Royfile.csv
2nd file in same folder Jackfile.csv:
Folder FolderOwner EmailAddress AttachmentPath
C:\folder3\ Jack Jack#gmail.com Jackfile.csv
D:\folder4\ Jack Jack#gmail.com Jackfile.csv
3rd file for example Mandyfile.csv. And same way total 50 files for 50 users in same folder.
Folder FolderOwner EmailAddress AttachmentPath
C:\folder5\ Mandy Mandy#gmail.com Mandyfile.csv
D:\folder6\ Mandy Mandy#gmail.com Mandyfile.csv
Python Script
import glob, as
import win32com.client as win32
import pandas as pd
for file in glob.glob("*file.csv"):
print(file)
email_list = pd.read_csv(file)
names = email_list['FolderOwner']
emails = email_list['EmailAddress']
attachments = email_list['AttachmentPath']
for i in range(len(emails)):
print(file)
name = names[i]
email = emails[i]
attachment = r'{}.csv'.format(attachments)
with open(attachment, 'r') as my_attachment:
myfile = my_attachment.read()
outlook = win32.Dispatch('outlook.application')
mail = outlook.CreateItem(0)
mail.To = email
mail.Subject = 'Message subject'
mail.Body = 'Hello ' + name
mail.Attachments.Add(attachment)
mail.Send()
break
Current output of the script if I remove the attachment part:
Royfile.csv
Royfile.csv
Jackfile.csv
Jackfile.csv
Mandyfile.csv
Mandyfile.csv
...
..
.
Struggling now with what needs to be for attachment = ???. So that each file gets sent to 50 users.
I don't know how your files named how they are distributed in different folders, try to put their all names along with paths in excel sheet in one column and iterate through them the way you are doing for names and mails
attachment = r'{}.csv'.format(filepaths from excel sheet)
with open(attachment, 'r') as my_attachment:
myfile = my_attachment.read()
Found answer for my question finally, below is full code.
The error was coming, as there was PATH missing.
win32com lib need full path even if the script is running in same folder as the attachments.
works perfectly now. :)
import glob, as
import win32com.client as win32
import pandas as pd
for file in glob.glob("*file.csv"):
print(file)
email_list = pd.read_csv(file)
names = email_list['FolderOwner']
emails = email_list['EmailAddress']
attachments = email_list['AttachmentPath']
PATH = "C:\\Users\\roy\\myfolder\\"
for i in range(len(emails)):
print("Sending email with " + file)
name = names[i]
email = emails[i]
attachment = attachments[i]
attachment1 = PATH + attachment
with open(attachment1, 'r') as my_attachment:
myfile = my_attachment.read()
outlook = win32.Dispatch('outlook.application')
mail = outlook.CreateItem(0)
mail.To = email
mail.Subject = 'Message subject'
mail.Body = 'Hello ' + name
mail.Attachments.Add(attachment1)
mail.Send()
break

python forward email to specific outlook folder win32com

I want to forward an Outlook email to a specific folder (not Inbox) using python. I'm using win32com.
When I Forward then Move, my email does appear in the specific folder, but when I look in my Outlook the Datetime and From are not showing.
How do I get the Datetime and From onto the forward/moved email?
import win32com.client
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
root_folder = outlook.Folders.Item(1)
sub_folder1 = root.Folders['Project1']
next_level = sub_folder1.Folders['ProjectA']
msg = next_level.Items
msgs = msg.GetLast()
dest = sub_folder1.Folders['ProjectB']
NewMsg = msgs.Forward()
NewMsg.Move(dest)
This is because you're making a draft of the original received email.
To simply move the email remove the NewMsg = msgs.Forward() line and replace NewMsg.Move(dest) with msgs.Move(dest).
import win32com.client
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
root_folder = outlook.Folders.Item(1)
sub_folder1 = root_folder.Folders['Project1']
next_level = sub_folder1.Folders['ProjectA']
msg = next_level.Items
msgs = msg.GetLast()
dest = sub_folder1.Folders['ProjectB']
msgs.Move(dest)
If you wish to make an actual copy and move the new item to the second folder, replace your ending code with
msgcopy = msgs.Copy()
dest = sub_folder1.Folders['ProjectB']
msgcopy.Move(dest)

How to save xls attachment as xlsx from outlook - pywin32

I receive a batch email containing a xls file, I have a script that searches my Outlook inbox for that email and extracts the attachment. I would like to save the file as an xlsx instead of it's current format xls.
I have tried to amend the file name in the SaveAsFile attachment method to include x at the end - attachment.SaveAsFile(os.path.join(file_home_path, new_file_name)+"x") - this did save the file as an xlsx but the file got corrupted and I couldn't open it.
Are there any other attachment methods that allow the file extension to be amended at source?
import win32com.client
import os
import datetime
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
now = datetime.datetime.now().strftime("%Y %m %d")
inbox = outlook.GetDefaultFolder(6)
messages = inbox.Items
file_home_path = "C:/Desktop"
for message in messages:
if message.Subject == 'subject_to_search_for':
attachments = message.Attachments
for attachment in attachments:
new_file_name = 'required_file_{}.xls'.format(now)
attachment.SaveAsFile(os.path.join(file_home_path, new_file_name))
break
message.Delete()
My work around is below.
os.chdir(file_home_path)
excel = win32com.client.gencache.EnsureDispatch('Excel.Application')
wb = excel.Workbooks.Open(new_file_name)
wb.SaveAs(new_file_name+"x", FileFormat = 51) #FileFormat = 51 is for .xlsx extension
wb.Close()
excel.Application.Quit()

How to Add File as Attachment to Outlook Item in Python

I have just created a few files and zipped them up, then begun an email to send it. I'ts probably simple, but I haven't been able to figure out how to specify a file by path to attach. Feeding the filepath alone doesn't seem to work?
ZipName = 'Order'+OrderNumber+'.zip'
zip = zipfile.ZipFile(ZipName, 'a', 8)
for file in os.listdir(filepath_out):
if file.endswith(".epw"):
zip.write(file)
zip.close()
outlook = win32.Dispatch('outlook.application')
mail = outlook.CreateItem(0)
#mail.From = 'sales#c1.com'
mail.To = 'support#c2.com'
mail.Subject = 'Files for Order ' + OrderNumber
mail.HtmlBody = ""
mail.Attachments.Add(ZipName)
mail.Display(True)
It's off topic but related; is there an easy way to specify a non-default "from" email address? "From" doesn't seem to be a property and "Sender" doesn't change anything.
Attachments.Add takes a fully qualified file name (e.g. c:\temp\order1.zip), not just a file name.

Categories