Add appointments from one outlook calendar to another using win32com - python

I can get all appointments from my main calendar, like this:
def getCalendarEntries():
Outlook = win32com.client.Dispatch("Outlook.Application")
ns = Outlook.GetNamespace("MAPI")
appointments = ns.GetDefaultFolder(9).Items
appointments.Sort("[Start]")
appointments.IncludeRecurrences = "True"
begin = datetime.date.today()
end = begin + datetime.timedelta(days = 100);
restriction = "[Start] >= '" + begin.strftime("%m/%d/%Y") + "' AND [End] <= '" +end.strftime("%m/%d/%Y") + "'"
restrictedItems = appointments.Restrict(restriction)
events={'Start':[],'End':[],'Organizer':[],'Subject':[],'Duration':[]}
for a in restrictedItems:
events['Start'].append(a.Start)
events['End'].append(a.End)
events['Organizer'].append(a.Organizer)
events['Subject'].append(a.Subject)
events['Duration'].append(a.Duration)
return events
And I can save events into my main calendar, like this:
def addevent(start, subject, duration):
Outlook = win32com.client.Dispatch("Outlook.Application")
appointment = Outlook.CreateItem(1) # 1=outlook appointment item
appointment.Start = start
appointment.Subject = subject
appointment.Duration = duration
appointment.Save()
My issue is that I don't know how to connect to another calendar folder. I don't want the "DefaultFolder" but a specific one. I would be really greatful if someone could help me.

Found the answer myself. One has to replace
appointments = ns.GetDefaultFolder(9).Items
with
recipient = ns.createRecipient("foo#outlook.com")
resolved = recipient.Resolve()
appointments = ns.GetSharedDefaultFolder(recipient, 9).Items

another way of read Items in another calender with subfolders i.e. \abc#outlook.com\Calendar\Work_Exchange
could be:
privateol = ns.Folders('abc#outlook.com')
privatecal = privateol.Folders('Calendar')
privatesubfolder = privatecal.Folders('Work_Exchange')
What i don't know is, how to write in this specific Subfolder, so if anyone wants to provide...
lg
Edit:
to write to the specific subfolder, one has to replace appointment.Save() with appointment.Move(privatesubfolder)
maybe it's not the best solution, but it works

Had exact the same issue but got brilliant help: use the Items.Add() Method and it perfectly works in whatever folder you are in. See here: Create Outlook appointment in subfolder/subcalendar with python

Related

Python generated *.msg file

I'm Jan and it's my first post here and the following code is also my first python code. So please don't judge me, if the code is not well shaped :) and don't wonder I had to reduce my mail body.
With the following code I try to generate several msg file depending on a user list called "customer_names". The idea is to iterate through this list and to adjust the email body espacially the placeholder for "Customer". The rest of the body content is not so important. Everything works good except the iteration through the list. I have a suggestion that I may need to increment the index for the list in the loop. Do you have any ideas.
import win32com.client as win32
import datetime
import random
# List of customer names
customer_names = ['Name1','Name2','Name3']
current_customer_index = 0
# List of email providers
email_providers = ['provider1', 'provider2', 'provider3']
# set up the Outlook application
outlook = win32.Dispatch('outlook.application')
# create a new email
mail = outlook.CreateItem(0)
# set the subject and recipients
mail.Subject = "Request for Customer Information"
mail.To = "user#emailprovider.net"
# Message body for the email
message = f"Dear User,\n\nThe information we require from [Customer] is as follows:\n\n- Email Address: [Email Address] \n\nWe kindly request that you send the requested information to us within [number of days] days. \n\n Kind regards."
# set the number of days for the customer to respond
num_days = 7
# set the importance of the email to normal
mail.Importance = 1 # 0=Low, 1=Normal, 2=High
# set the sensitivity of the email to normal
mail.Sensitivity = 0 # 0=Normal, 1=Personal, 2=Private, 3=Confidential
# set the read receipt option to true
mail.ReadReceiptRequested = True
# add a reminder for the sender to follow up in 3 days
mail.FlagRequest = "Follow up"
mail.FlagDueBy = (datetime.date.today() + datetime.timedelta(days=3)).strftime('%m/%d/%Y')
# Generate a random email
for i in range(len(customer_names)):
customer = customer_names[i]
message_with_data = message.replace("[Customer]", customer)
message_with_data = message_with_data.replace("[number of days]", str(num_days))
mail.Body = message_with_data
file_name = "Request_" + customer + ".msg"
file_path = "C:/Users/user/Desktop/Email/" + file_name
mail.SaveAs(file_path)

How do I format Outlook restrict to search for a variable?

I am trying to use the restrict method to search for emails where the subject equals a certain string, however, this string changes slightly everyday since the sender adds the current date. I am trying to use a variable which would contain the current date and insert it into the restrict method.
I keep getting an invalid syntax error message specifically with regards to the Restrict line.
from datetime import datetime, timedelta
received_dt = datetime.now()
received_dt = received_dt.strftime('%Y-%m-%d')
subject_search_string = "Daily Statement" + recevied_dt
msg = msg.Restrict("[Subject] = " subject_search_string)
The subject value must be single-quoted:
msg = msg.Restrict("[Subject] = '" subject_search_string "'")

Problem with read Outlook shared calendar via python

I try to make an application to read events from Outlook shared calendar. I use Python 3.8.0 on win10. Here is my function to do this.
def getSharedCalendarEntries(TS_name, days=1000): #TS_name is name of shared calendar
MailboxToAccess = 'owner#gmail.com'
Outlook = win32com.client.Dispatch("Outlook.Application")
namespace = Outlook.GetNamespace("MAPI")
recipient = namespace.createRecipient(MailboxToAccess)
resolved = recipient.Resolve()
sharedCalendar = namespace.GetSharedDefaultFolder(recipient, 9).Folders(TS_name).Items
sharedCalendar.Sort("[Start]")
sharedCalendar.IncludeRecurrences = 'True'
today = datetime.datetime(2019,1,1)
begin = today.date().strftime('%d/%m/%Y')
tomorrow = datetime.timedelta(days=days)+today
end = tomorrow.date().strftime('%d/%m/%Y')
sharedCalendar = sharedCalendar.Restrict("[Start] >= '" +begin+ "' AND [END] <= '" +end+ "'")
events = {'Start':[],'End':[],'Subject':[],'Duration':[]}
mEv = []
for app in sharedCalendar: #petla po rezerwacjach
adate = datetime.datetime(app.Start.year, app.Start.month, app.Start.day).date()
events['Start'].append(adate)
aend = datetime.datetime(app.End.year, app.End.month, app.End.day).date()
events['End'].append(aend)
events['Duration'].append(int(app.Duration/1440))
events['Subject'].append(app.Subject)
mEvent = Event(adate, aend, int(app.Duration/1440), app.Subject)
mEv.append(mEvent)
return mEv
Everything was working and I was able to read events, but suddenly something happened (I didn't change anything in code) and I have such error:
File "C:\Users\user_catalog\Desktop\outread.py", line 60, in
getSharedCalendarEntries
sharedCalendar = namespace.GetSharedDefaultFolder(recipient, 9).Folders(TS_name).Items
File
"C:\Users\user_catalog\AppData\Local\Programs\Python\Python38\lib\site-packages\win32com\client\dynamic.py",
line 197, in call
return self._get_good_object_(self.oleobj.Invoke(*allArgs),self.olerepr.defaultDispatchName,None)
pywintypes.com_error: (-2147352567, 'Exception occurred.', (4096,
'Microsoft Outlook', ' An attempt to perform the operation failed.
Could not find the object.', None, 0, -2147221233), None)
I had read-only access to shared calendars. Owner of shared calendars said that she logged-out of network, and time of logged out was the same time my application stopped working.
Have any of you had such problem or have some tips for me?
Thank you in advance!
Pio
Would you mind trying the code below? It will get you a dataframe with subject, occurence of the meeting, start time and end time.
import win32com.client, datetime
import pandas as pd
from datetime import time, timedelta
#connect to outlook
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
appointments = outlook.GetDefaultFolder(9).Items #Calendário
#use these 2 lines to short the list
appointments.Sort('[Start]')
#Recurrent events only show the first start date, use the following to get the REAL occurrence of the event.
appointments.IncludeRecurrences = 'True'
#Beginning of the week(monday) to end of week(friday)
today = datetime.date.today()
start = today - timedelta(days=today.weekday())
end = start + timedelta(days=5)
#String of restriction time that will be used to filter dates on outlook
restriction = "[Start] >= '" + start.strftime("%d/%m/%Y") + "' AND [End] < '" +end.strftime("%d/%m/%Y") + "'"
print(restriction)
restrictedItems = appointments.Restrict(restriction)
#create empty data frame with columns to be fetched
i = 0
calendario = pd.DataFrame(columns=['Subject', 'When', 'Start Time','End Time'])
#Loop on items to fill the dataframe
for appointmentItem in restrictedItems:
calendario.loc[i] = [appointmentItem.Subject,appointmentItem.Start.strftime("%m/%d/%Y"),appointmentItem.Start.strftime("%H:%M"),appointmentItem.End.strftime("%H:%M")]
i = i + 1
#display dataframe
calendario

Use python to create rule in Outlook from sender Email address

I am trying to create rules to move emails from a long list of senders to specific folders. For example, if I receive an email from john#email.com, I want it to be moved from "Inbox" to "workstuff\John" (john is a subfolder of workstuff).
I'm using comtypes.clients and python to do this because I found a similar post ( Setting a property using win32com ), in which one of the answers uses comtypes.clients in python.
I am also using https://learn.microsoft.com/en-us/office/vba/outlook/how-to/rules/create-a-rule-to-move-specific-e-mails-to-a-folder as a guideline.
import comtypes.client
o = comtypes.client.CreateObject("Outlook.Application")
rules = o.Session.DefaultStore.GetRules()
rule = rules.Create("Test", 0)
condition = rule.Conditions
condition.From.Recipients.Add(str("fabracht"))
condition.From.Recipients.ResolveAll
#.From.Recipients("fabracht#gmail.com")
condition.Enabled = True
root_folder = o.GetNamespace('MAPI').Folders.Item(1)
dest_folder = root_folder.Folders["Evergreen1"].Folders["Chemistry"]
move = rule.Actions.MoveToFolder
move.__MoveOrCopyRuleAction__com__set_Enabled(True)
move.__MoveOrCopyRuleAction__com__set_Folder(dest_folder)
rules.Save()
I've been able to create the rule, which shows up in outlook. But the rule is missing the "from" part. Basically it says:
" Apply this rule after the message arrives
Move it to the john folder "
I expected the rule to be:
" Apply this rule after the message arrives
From john#email.com
Move it to the john folder "
The article mentioned in your post contains the following code for dealing with the From part:
'Specify the condition in a ToOrFromRuleCondition object
'Condition is if the message is from "Eugene Astafiev"
Set oFromCondition = oRule.Conditions.From
With oFromCondition
.Enabled = True
.Recipients.Add ("Eugene Astafiev")
.Recipients.ResolveAll
End With
The code should look like the following:
import comtypes.client
o = comtypes.client.CreateObject("Outlook.Application")
rules = o.Session.DefaultStore.GetRules()
rule = rules.Create("Test", 0)
condition = rule.Conditions
condition.From.Recipients.Add(str("fabracht"))
condition.From.Recipients.ResolveAll
oFromCondition = oRule.Conditions.From
oFromCondition.Enabled = True
oFromCondition.Recipients.Add("john#email.com")
oFromCondition.Recipients.ResolveAll
#.From.Recipients("fabracht#gmail.com")
condition.Enabled = True
root_folder = o.GetNamespace('MAPI').Folders.Item(1)
dest_folder = root_folder.Folders["Evergreen1"].Folders["Chemistry"]
move = rule.Actions.MoveToFolder
move.__MoveOrCopyRuleAction__com__set_Enabled(True)
move.__MoveOrCopyRuleAction__com__set_Folder(dest_folder)
rules.Save()

Include recurring appointments

I am trying to get all appointments from client outlook with python and win32com. client, I just want to get all appointments from 2019 so that I could restrict the appointment Items, but when I restrict them I don't get the recurring appointments.
I already tried to enable recurring items with appointments.IncludeRecurrences = "True", but that didn't help.
import win32com.client
import time
import datetime
import os
f=open("mem.txt", "w")
counter=0
outlook= win32com.client.Dispatch("Outlook.Application")
namespace=outlook.GetNamespace("MAPI")
recipient = namespace.createRecipient("Some Calender")
resolved = recipient.Resolve()
sharedCalendar = namespace.GetSharedDefaultFolder(recipient, 9)
appointments = sharedCalendar.Items
# Restrict items
begin = datetime.date(2019, 1, 1)
end = datetime.date(2019, 12, 30)
restriction = "[Start] >= '" + begin.strftime("%m/%d/%Y") + "' AND [End] <= '" +end.strftime("%m/%d/%Y") + "'"
restrictedItems = appointments.Restrict(restriction)
appointments.IncludeRecurrences = "True"
# Iterate through restricted AppointmentItems
for appointmentItem in restrictedItems:
month= appointmentItem.Start
month=str(month)[5:-18] #just trim the month out of the date
if month=='08': #need appointments from specific
#mystuff
#the code works but I want the recurring appointments too
print(counter)
f.close()
Did you try setting IncludeRecurrences to True before Restricting your items ?
Basically switching those two lines :
restrictedItems = appointments.Restrict(restriction)
appointments.IncludeRecurrences = "True"
Firstly, to retrieve all Outlook appointment items from the folder that meets the predefined condition, you need to sort the items in ascending order and set the IncludeRecurrences to true. You will not catch recurrent appointments if you don’t do this before using the Restrict method!
folderItems = folder.Items;
folderItems.IncludeRecurrences = true;
folderItems.Sort("[Start]");
resultItems = folderItems.Restrict(restrictCriteria);
You may find the following articles helpful:
How To: Use Restrict method in Outlook to get calendar items
How To: Retrieve Outlook calendar items using Find and FindNext methods

Categories