Win32com locating time of email after restricting timeframe - python

I would like to capture the date/time when a message was sent so that I can store the info in dataframe. I have connected to my inbox and can extract the email and I have restricted the time so that I can only get emails from the last 7 days.
Here's my code:
import win32com.client as wc
import pandas as pd
import datetime as dt
last_week = dt.date.today()- dt.timedelta(days = 7)
last_week = last_week.strftime('%m/%d/%Y %H:%M %p')
#Search through my inbox
outlook = wc.Dispatch("Outlook.Application")
mapi = outlook.GetNamespace("MAPI")
root_folder = mapi.Folders['username'].Folders['Inbox'].Folders['folder']
print(root_folder.Name)
#restrict inbox to 7 days
messages = root_folder.Items
messages = messages.Restrict("[ReceivedTime] >= '" + last_week + "'")
messages.Sort("[ReceivedTime]", True)
#grab message and convert to pandas DF. Expected 7 messages
counter = 0
for message in messages:
if message.Subject == 'Message_1':
print(counter, message.Subject)
print(messages.SentOn) ### I Get my Attributes Error here :(
html_str = message.HTMLBody
get_table = pd.read_html(html_str)[0]
counter += 1
When I added the SentOn Method I am getting an AttributeError saying "Restrict.SentOn" I am assuming that this is because I have restricted my time period.
How do I get the actual date/time of the individual message?

I needed to use the individual object as the item to get the .SentOn info from

Related

How can I add the authentication step in my script?

I have a script below which I would like to schedule to run it everyday through SQL Server and store the calendar events to database but the problem is I would need to have my outlook open in order to run this script, how can I add my credential in the script so I don't have to open outlook and have the script run without keeping my outlook opened? Thank you
import win32com.client, datetime
from datetime import date
from dateutil.parser import *
import calendar
import pandas as pd
import pyodbc
Outlook = win32com.client.Dispatch("Outlook.Application")
ns = Outlook.GetNamespace("MAPI")
Item = Outlook.CreateItem ( 1 )
Recip = Item.Recipients.Add ( 'Corporate Master Calendar' )
appts = ns.GetSharedDefaultFolder(Recip,9).Items
appts.Sort("[Start]")
appts.IncludeRecurrences = "False"
eoy=date(date.today().year, 12, 31)
eoy=eoy.strftime("%m/%d/%Y")
begin = date.today()
begin = begin.strftime("%m/%d/%Y")
appts = appts.Restrict("[Start] >= '" +begin+ "' AND [Start] <= '" +eoy+ "'")
apptDict = {}
item = 0
for indx, a in enumerate(appts):
organizer = str(a.Organizer)
start = a.Start
end = a.End
subject = str(a.Subject)
location = str(a.Location)
categories = str(a.Categories)
body=str(a.Body)
itemid=str(a.GlobalAppointmentId)
lmt=str(a.LastModificationTime)
apptDict[item] = {"GlobalAppointmentId": itemid, "Organizer": organizer, "Subject": subject, "Location": location, "Start": start, "End": end, "Body": body,"Categories": categories, "LMT":lmt}
item = item + 1
You can't - with MFA, even storing the credentials in the keyring (which only deals with basic credentials) won't do anything.

Alert for Old Access Keys in AWS

I didn't get an answer to my original question, but I've tweaked my code and I'm leaving this here in case anyone is trying to figure this out in the future. I'm new to Python, but this worked. This is a Python script I created for a Lambda function that checks the users in your AWS account and publishes a notification to an SNS topic. I've scheduled a CloudWatch rule with a cron expression to run it every day.
import boto3, json, time, datetime, sys, re
iam_client = boto3.client('iam')
sns_client = boto3.client('sns')
users = iam_client.list_users()
user_list = []
for key in users['Users']:
user_list = key['UserName']
accesskeys = iam_client.list_access_keys(UserName=key['UserName'])
for items in user_list.split('\n'):
for key in accesskeys['AccessKeyMetadata']:
accesskeydate = accesskeys['AccessKeyMetadata'][0]['CreateDate']
accesskeydate = accesskeydate.strftime("%Y-%m-%d %H:%M:%S")
currentdate = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
accesskeyd = time.mktime(datetime.datetime.strptime(accesskeydate, "%Y-%m-%d %H:%M:%S").timetuple())
currentd = time.mktime(datetime.datetime.strptime(currentdate, "%Y-%m-%d %H:%M:%S").timetuple())
active_days = (currentd - accesskeyd)/60/60/24
message = (key['UserName'],int(round(active_days))),
message = re.sub(r'[^a-zA-Z0-9 ]', "", str(message))
message = re.sub(r' ', ' is ', str(message))
if active_days >= 90:
sns_client.publish(
TopicArn='arn:aws:sns:us-west-2:xxxxxxxxxxxxx:topic-name',
Subject='User with Old Access Key Detected',
Message="The access key for " + str(message) + " days old. This user access key should be replaced ASAP.",
)

update categories in emails using python

I am trying to update categories of emails available in one of the data frame using below code.
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox = outlook.GetDefaultFolder(6)
messages = inbox.Items
i = 0
for message in messages:
try:
message.Categories = output.iat[i,2]
except:
message.Categories = 'No Category'
i = i + 1
Below script used to move updated emails from inbox to another folder and then remove to inbox
donebox = outlook.GetDefaultFolder(6).Folders[20]
def delay(time):
for j in range(time):
j=j+1
i = 0
while (messages.Count > 0):
print(i,messages.Count)
message = messages.GetLast()
message.Move(donebox)
delay(1000000)
i = i + 1
messages = donebox.Items
i = 0
while (messages.Count > 0):
print(i,messages.Count)
message = messages.GetLast()
message.Move(inbox)
delay(1000000)
i = i + 1
In outlook updated Categories from output dataframe for emails are able visible only once email selected. Is there any option which can refresh outlook and categories will be updated automatically. Please advice.
For everyone who cant save changing of non-selected mail Categories property by Python:
mail.Categories='Red category'
mail.Save()
It worked for me!
import win32com.client
from win32com.client import Dispatch
outlook=win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
folder = outlook.Folders.Item("Inbox")
messages = folder.Items
for i in range(messages.Count):
messages[i].GetInspector()
messages[i].Categories = 'Purple Category'
messages[i].Save()
If only one category needs to be assigned to each email, dmitrii.kotenko has provided the solution.
If you need to append more than one category, pass the categories as a string separated by commas
mail.Categories = "category1, category2, category3"
mail.Save()

Send an email only if # isn't in csv

I have two CSV files, one with IOC hits and a second that is a watchfile. The watchfile adds an # to the file along with the IOC domain and last seen date. I'm trying to send one email when an IOC hit for that day, but I can't seem to get my loop right. Currently it emails every time, even though the # is present in the watchfile.csv. I've printed the values for val and emailed and they show up in the correct format, but it still emails every time the script is ran.
finIOChit.csv
last: 2017-01-17 query: rabbitons.pw,
watchfile.csv
last: 2017-01-17 query: # rabbitons.pw,
import smtplib
import csv
import os
import re
from datetime import *
today = date.today()
today = datetime.combine(today, datetime.min.time())
# Setup email alerting
sender = 'server#company.com'
receivers = ['user#company.com']
patn = re.compile('20\d{2}-\d{2}-\d{2}')
watchfile = open('watchfile.csv', 'r+w')
alreadyemailed = re.compile('#')
with open('finalIOChit.csv') as finalhit:
for hit in finalhit:
for line in watchfile:
emailed = alreadyemailed.findall(line)
for match in patn.findall(hit):
val = datetime.strptime(match, '%Y-%m-%d')
if val == today and emailed != '#':
hit = re.sub('query: ','query: # ',hit)
watchfile.write(hit)
message = """From:server <server#comapny.com>
To: user <user#company.com>
Subject: Passive DNS hit
"""
subject = ' ' + str(hit)
messagefull = message + subject
try:
smtpObj = smtplib.SMTP('emailserver')
smtpObj.sendmail(sender, receivers, messagefull)
except SMTPException:
print "Error: unable to send email"

Python - Outlook Response (Accept, Reject, etc.) Date/Time

I am working on a project that involves pulling a lot of appointment/meeting data from Outlook from multiple people. One piece of information that I am trying to find is the response for each attendee and, if possible, the date and time that the response happened. For example, if Person X sends me a meeting request on 4/21/2015 12:31:00 PM and I accepted the meeting request at 4/21/2015 1:30:00 PM, how would I get the latter of those two times? I have been browsing the Microsoft docs for this (Link) but have had no luck so far.
Here is a quick summary in Python:
import win32com.client
outlook = win32com.client.Dispatch('Outlook.Application')
namespace = outlook.GetNamespace('MAPI')
recipient = namespace.createRecipient('Other Person')
resolved = recipient.Resolve()
sharedCalendar = namespace.GetSharedDefaultFolder(recipient, 9)
appointments = sharedCalendar.Items
for i in range(0,1):
print appointments[i]
print appointments[i].start
print appointments[i].end
print appointments[i].organizer
print appointments[i].location
print appointments[i].duration
for j in range(0,len(appointments[i].recipients)):
print 'recip, status: ' + str(appointments[i].recipients[j]) + ', ' + str(appointments[i].recipients[j].TrackingStatusTime)
AppointmentItem.ReplyTime and AppointmentItem.ResponseStatus
here is another way
import win32com.client
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox = outlook.GetDefaultFolder(6)
messages = inbox.Items
messages.Sort("[ReceivedTime]", True)
for i, msg in enumerate(messages):
print(msg.MessageClass) # use this in condition
if msg.MessageClass=='IPM.Note':
print('This a Meeting')
elif msg.MessageClass =='IPM.Schedule.Meeting.Request':
print('This is a meeting Meeting')
elif msg.MessageClass =='IPM.Schedule.Meeting.Resp.Pos':
print('Accepted Response , POS = Positive')
elif msg.MessageClass =='IPM.Schedule.Meeting.Resp.Tent':
print('Accepted as Tentative ')
elif msg.MessageClass == 'IPM.Schedule.Meeting.Resp.Neg':
print('Declined Meeting , Neg = Negative')
# Check only first 10 items, change the number as per requirement
if i > 10:
break
https://learn.microsoft.com/en-us/office/vba/outlook/Concepts/Forms/item-types-and-message-classes

Categories