If statement not working comparing Outlook sender with existing dataframe entry - python

I am new to Python. I am scanning Outlook inbox looking for a specific subject (YES). If I find that subject, get the sender email and check if that sender is in my emailing list, if not, add them to my emailing list.
I am stuck with the IF statement comparing the sender with what I have in my dataframe. EmailList.xlsx has 1 column "Name" and 8 entries "LastName, FirstName I"
import win32com.client
import os
import pandas as pd
get_path = os.getcwd()
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox = outlook.GetDefaultFolder(6)
messages = inbox.Items
EmailList = (pd.read_excel("EmailList.xlsx", sheet_name='ABC', index_col=0))
EmailList.info() #<<-- I can see my dataframe, column name and number of entries.
a=len(messages)
if a > 0:
for messages2 in messages:
subject = messages2.Subject
if "YES" in subject:
sender = messages2.Sender
print(subject) #<<-- Works fine, I see the subject
print(sender) #<<-- Works fine, I see the sender
if EmailList ['Name'] == sender: <<-- does not work
if EmailList ['Name'].str.contains(sender).any(): <<-- does not work
print("Your are already subscribed")
else:
print("append DF")
Any ideas? I am guessing there is something with the "sender" string, but I cannot figure it out.

SOLVED!!
sender = messages2.SenderName
&
if EmailList['Name'].str.contains(sender).any():

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)

Make name variable print the corrent name with an automated email

I've been trying to make a python script to send a happy birthday email on a given date, that notifies me who it sent an email to via text message.
I have 3 files.
First I have a brithdays.csv file which I enter all the birthday data that is going to use.
Here's an example of what's inside the file:
name,email,year,month,day
Ivy,Testemail#mail.com,1,3,25
Rose,Testemail#mail.com,1,3,28
Kimberly,Testemail#mail.com,1,4,10
Then I have a letter template which the script reads and replaces [NAME] with the name in the CSV file :
Greetings,
Im wishing [NAME] a very happy birthday! [NAME], &#128522 I hope you enjoy your day and wishing you more life.
Thank you,
And then I have my actual code
############## IMPORTS ##############
import smtplib
import datetime as dtime
import pandas as pd
import random
from time import strftime
from email.mime.text import MIMEText
############## Reading Data and Check Current Day & Month ##############
# READ CSV BIRTHDAY FILE
df = pd.read_csv("birthdays.csv")
# PRINT CURRENT DAY
current_day = dtime.datetime.now().day
current_month = dtime.datetime.now().month
##################ENTER LOGIN HERE#############################
LOGIN = "EMAIL"
PASS = "PASSWORD"
############## LOGIC ##############
# save the rows that has the current day in new variable
new_df = df.loc[df['day'] == current_day]
# check the length of new_df of the current month so if the result is larger than 1
# so there is birthdays on this day
if len(new_df.loc[new_df['month'] == current_month]) > 0:
# check the length of people having birthday in this day
for i in range(len(new_df.loc[new_df['month'] == current_month])):
# OPEN BIRTHDAY TEMPLATE
with open(f"./letter_1.txt") as letter_file:
# READING FILE
letter_contents = letter_file.read()
#CREATE NAME VARIABLE
name = df["name"][i]
# replace [NAME] with actual name on the data
if len(new_df["name"]) > 1:
the_letter = letter_contents.replace("[NAME]", new_df["name"][i])
the_email = new_df["email"][i]
else:
the_letter = letter_contents.replace("[NAME]", new_df["name"].item())
the_email = new_df["email"].item()
# SMTPLIB LOGIN TO SEND EMAIL
# CONNECTION
with smtplib.SMTP("smtp.outlook.com") as con:
# START
con.starttls()
# LOGIN
con.login(user=LOGIN, password=PASS)
# create the msg
msg = MIMEText(the_letter, 'html')
msg["From"] = LOGIN
msg["To"] = the_email
msg["Subject"] = "Happy Birthday " + name + "!!!"
msg["Cc"] = "CC EMAILS"
# SEND EMAIL
con.send_message(msg)
#SENDS TEXT MESSAGE CONFIRMATION
msg = MIMEText ("Sent Happy Birthday Email to " + name + " on " + str(text.strftime('%Y-%m-%d %H:%M:%S %p')))
msg["From"] = LOGIN
msg["To"] = "VERIZONPHONENUMBER#vtext.com"
# SEND TEXT
con.send_message(msg)
# LOGS OUT OF EMAIL
con.quit()
I think the issue lies in Line 45 where I create the name variable.
My issue is that every time it sends an email, the name in the Subject of the email and in the text message I receive it's the first name of the list.
For example if I run the script, the email would look something like this
Happy Birthday Ivy!!!
Greetings,
Im wishing Rose a very happy birthday! Rose, &#128522 I hope you enjoy your day and wishing you more life.
I'm trying to make the name that appears on the subject match with the name that appears on the body of text.
msg = MIMEText ("Sent Happy Birthday Email to " + name + " on " + str(text.strftime('%Y-%m-%d %H:%M:%S %p')))
Here you are using the name variable when generating the body but earlier in your code you have:
name = df["name"][i]
Which grabs the name from the unfiltered DataFrame but you use the filtered DataFrame to generate the subject line here:
# replace [NAME] with actual name on the data
if len(new_df["name"]) > 1:
the_letter = letter_contents.replace("[NAME]", new_df["name"][i])
the_email = new_df["email"][i]
else:
the_letter = letter_contents.replace("[NAME]", new_df["name"].item())
the_email = new_df["email"].item()
The i-th element in the filtered DataFrame might not be the i-th element in your original DataFrame so you need to declare name as follows:
name = new_df["name"][i]

Search outlook body for text, then create a variable for the line the text is on

Every morning I get spot data on FX volumes via an email, I'd like to build a process to search two pieces of data within the body of the email and save them as a new variable which I can then refer to later.
I've got the process to search my emails, order them according to date and check whether the entered data exists within the emails, but because the data is contained within a format between two commas, I am unsure how to take that data out and assign it to a new variable.
Format for example is this:
BWP/USD,0
CHF/AMD T,0
This is what I've achieved thus far:
import win32com.client
import os
import time
import re
# change the ticker to the one you're looking for
FX_volume1 = "BWP/USD"
FX_volume2 = "CHF/AMD"
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox = outlook.GetDefaultFolder(6)
messages = inbox.Items
messages.Sort("[ReceivedTime]", True)
# find spot data
for message in messages:
if message.subject.startswith("FX SPOT FIGURES"):
if FX_volume1 and FX_volume2 in message.body:
data = message.body
print(data)
else:
print('No data for', FX_volume1, 'or', FX_volume2, 'was found')
break
Any idea how to take this forward?
Thanks for any assistance/pointers
import win32com.client
import os
import time
import re
# change the ticker to the one you're looking for
FX_volume1 = "BWP/USD"
FX_volume2 = "CHF/AMD"
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox = outlook.GetDefaultFolder(6)
messages = inbox.Items
messages.Sort("[ReceivedTime]", True)
# find spot data
for message in messages:
if message.subject.startswith("FX SPOT FIGURES"):
case1 = re.match(FX_volume1 + ",(\d*)", message.body)
case2 = re.match(FX_volume2 + ",(\d*)", message.body)
case (1 and 2) will be match objects if a match is found, else they will be None. To retrieve your values just do val = case1.group(1). Hence:
EDIT:
if case1 not None:
FX_vol1_val = case1.group(1)
if case2 not None:
FX_vol2_val = case1.group(1)
For more info on match objects:
https://docs.python.org/3/library/re.html#match-objects
If you are expecting floats, see the following link:
Regular expression for floating point numbers
EDIT 2:
Hi, so as you couldn't get it working I gave it a quick try and it worked for me with the following example. Just to add to regex notation, anything that you put in brackets (), if the pattern matches, the contents between the brackets will be stored.
import re
my_text = "BWP/USD,1"
FX_pattern = "BWP/USD," # added the comma here for my convinience
my_match = re.match(FX_pattern, "(\d*)")
print("Group 0:", my_match.group(0))
print("Group 1:", my_match.group(1))
Printout:
Group 0: BWP/USD,1
Group 1: 1

Reading Emails From Outlook with Python & Specifying a Date Range

I am trying to read emails from Outlook using a specific date range as well as other criteria - sender, subject etc. However, I am unsure as to how to specify a date range within which Python can search for the emails. This is what I have so far which generates the type error below:
if subject in message.subject and date in message.senton.date():
TypeError: argument of type 'datetime.date' is not iterable
import win32com.client
import datetime
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox = outlook.GetDefaultFolder(18).Folders.Item("xxxxx")
messages = inbox.Items
date = datetime.date.today()
subject = "xxxxxxx"
for message in messages:
if subject in message.subject and date in message.senton.date():
print(message.senton.time())
I would like to search for emails within a specific date range, as well as be able to use more than one criteria to search. E.g specify the subject as well as sender etc. But I am not sure how, I am new to Python so please help!
Try this
if subject in message.subject and date == message.senton.date():
print(message.senton.time())
print(message.sender)
Edit:
if you want date range you can use datetime to define the date range
start = message.senton.date() - timedelta(days=10)
end = message.senton.date() + datetime.timedelta(days=10) # 20 days date range
if subject in message.subject and date > start and date < end:
print(message.senton.time())
print(message.sender)
instead of looping through every message, outlook provides an api to query the exact subject:
import win32com.client
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox=outlook.Folders.Item(3).Folders['Inbox'].Folders['My Folder']
filt = "#SQL=""http://schemas.microsoft.com/mapi/proptag/0x0037001f"" = '{0}'".format(subject)
messages=inbox.Items.Restrict(filt)

How to Handle single and Multiple Email ID fetched from Database in Python

I have a scenario where I have Extract Emails from Database and send mails to the respective Users.
The values fetched from the database can be of Single Email Id or Multiple Email Id.
I have written the following code and its throwing me an error when it encounters multiple email id seperated by comma.
for index, row in df1.iterrows():
myVar1 = row["abc"]
#myVar2 = row["Email"]
if row["Email"].count('#') > 1:
myVar2 = ','.join(row["Email"])
else:
myVar2 = row["Email"]
msg = email.message.Message()
msg['From'] = 'do.not.reply#xyz.com'
msg['To'] = myVar2
msg['Subject'] = "abc to be read - {0}".format(myVar1)
msg.add_header('Content-Type', 'text')
msg.set_payload("Hello Users,\n\n ABC - {0} has reached its limit.".format(myVar1))
smtp_obj = smtplib.SMTP("outlook.xyz.com")
smtp_obj.sendmail(msg['From'],msg['To'], msg.as_string())
smtp_obj.quit()
if it a single email id then the mail is trigerring properly but if multiple email is passed then each alphabet is seperated by comma
input 'abc#xyz.com,asd#xyz.com'
error message : a,b,c,#,x,y,z,.,c,o,m,,,a,s,d,#,x,y,z,.,c,o,m
Please help me in this concern.
Thanks

Categories