Reading outlook and writing to excel using Python - python

i need to read all email from a particular address and get "some content" into excel
i have had some success in reading emails but i am stuck to get the content of these emails in to excel
import win32com.client
import xlsxwriter
import pandas
wb = xlsxwriter.Workbook('Planned_power_outage.xlsx')
ws = wb.add_worksheet()
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI").Folders
folder = outlook(1)
inbox = folder.Folders("Inbox")
messages = inbox.Items
for message in messages:
if (message.SenderEmailAddress) == 'addess here':
sent_date = message.senton.date()
sender = message.Sender
subject = message.Subject
content = message.body
possible_node = subject.split(" ")[1]
print(sender,subject,content)
i expect to see the output as below in a excel file
SENDER SUBJECT CONTENT
alpha this is subject0 blahbalahblahablah
alpha this is subject1 blahbalahblahablah
alpha this is subject2 blahbalahblahablah

Related

How to convert dataframe to csv on AWS Lambda and sendmail with csv attached using SES

I have to sendmail at the end of my code with csv attached containing a dataframe.
Im doing it at AWS Lambda using boto3 to call SES as it follows.
def sendMail1(value, df):
subject = "Comission"
client = boto3.client("ses")
body = f"""
Comission value is {value}.
"""
message = {"Subject": {"Data": subject}, "Body": {"Html": {"Data": body}}}
attachment = df.to_csv(f"Comission.csv", index=False)
response = client.send_email(Source = "myemail#gmail.com", Destination = {"ToAddresses": ["youremail#gmail.com"]}, Message = message, Attachment = attachment)
I had no ideia how to do it, I tried df.to_csv method and include it as attachment. Did not work.
The rest of the code works without the attachment parts, but I need to attach my df to the e-mail.
Do you guys have any idea how to do it?
df.to_csv(f"Comission.csv", index=False)
to_emails = [target_email1, target_email2]
ses = boto3.client('ses')
msg = MIMEMultipart()
msg['Subject'] = 'weekly report'
msg['From'] = from_email
msg['To'] = to_emails[0]
# what a recipient sees if they don't use an email reader
msg.preamble = 'Multipart message.\n'
# the message body
part = MIMEText('Howdy -- here is the data from last week.')
msg.attach(part)
# the attachment
part = MIMEApplication(open('Comission.csv', 'rb').read())
part.add_header('Content-Disposition', 'attachment', filename='Comission.csv')
msg.attach(part)
result = ses.send_raw_email(
Source=msg['From'],
Destinations=to_emails,
RawMessage={'Data': msg.as_string()})
# and send the message
print result

How do I send emails to multiple people with different body?

I want to group recipients by reason and sent out tailored emails for each reason. The data looks like this.
Email reason
0 one#outlook.com Address
1 two#outlook.com Address
2 three#outlook.com Phone Number
3 one#outlook.com Postcode
import Pandas as pd
data = { 'Email': ['one#outlook.com','two#outlook.com','three#outlook.com','one#outlook.com'],
'reason': ['Address','Address', 'Phone Number','Postcode']}
df = pd.DataFrame(data)
df
This is how I started.
for e in df['reason'].unique():
print(f"Reason: {e}")
print(df[df['reason'] == e]['Email'].to_list())
print('\n')
Reason: Address
['one#outlook.com', 'two#outlook.com']
Reason: Phone Number
['three#outlook.com']
Reason: Postcode
['one#outlook.com']
Not sure how to use this list below.
message = "Update"
email_subject = "Test"
recipients = e
# sending email function
def send_mail(text, subject, recipients):
o = win32com.client.Dispatch("Outlook.Application")
Msg = o.CreateItem(0)
Msg.to = ''
Msg.BCC = "; ".join(recipients)
Msg.Subject = subject
Msg.HTMLBody = text
Msg.Send()
# sending email
send_mail(message,email_subject,recipients)
How to set 3(or more) different email body's and loop around the grouped list to sent separate emails for each reason?
You need to repeat the following code in the loop:
Msg = o.CreateItem(0)
Msg.to = recipient;
Msg.Subject = subject
Msg.HTMLBody = text
Msg.Send()
where recipient is an email address of a single recipient.
You may find the Using Visual Basic for Applications in Outlook article helpful.

Is there a way of concatenating emails to multiple recipients via SMTPLib in a Pandas dataframe in Python? [duplicate]

This question already has answers here:
How to send email to multiple recipients using python smtplib?
(18 answers)
Closed 1 year ago.
I have the below code to send out emails specific to certain addresses all in a pandas dataframe. The type says pandas.series. How can I be able to send each list with multiple addresses? Some have upto 8 email addresses separated by a semi-colon(;). Only possibility of sending out is to a single address. From the below dataframe, I'm able to send emails specific to the IDs to TestEmail values. Nothing works for Emails. I get the below error :
SMTPRecipientsRefused: {'': (421, b'4.7.0 Too many protocol errors (6) on this connection, closing transmission channel.')}
Dataframe df
IDs CompanyNames Emails TestEmail
2003 XXX xx#gmail.com;yy#ryt.com;dd#xx.com;ii#dd.com kk#kk.com
2004 XXXYY xx#gmail.com;yy#ryt.com;dd#xx.com kk#kk.com
2005 XXTTNN xx#gmail.com;yy#ryt.com;dd#xx.com;ii#dd.com kk#kk.com
2006 BBOOLL xx#gmail.com;yy#ryt.com kk#kk.com
The code is below. To the single address, I'm able to send attachments with names matching df['IDs'] values to the corresponding email address.
import smtplib, ssl
from email.message import EmailMessage
import getpass
ids = df['IDs']
emails_to = df['Emails'] #Pandas column with email addresses split by semi-colon(;)
namesofcompanies = df["CompanyNames"]
sendfrom = df["SenderList"]
date_7days = (datetime.now() + timedelta(days=7)).strftime('%d/%m/%Y')
date_14days = (datetime.now() + timedelta(days=13)).strftime('%d/%m/%Y')
email_pass = input() #Office 365 password
context=ssl.create_default_context()
for i in range(len(emails_to)): # iterate through the records
# for every record get the name and the email addresses
ID = str(ids[i])
Emaitstosendto = emails_to[i]
companynames = namesofcompanies[i]
tosendfrom = sendfrom[i]
if my_files_dict.get(ID): #Looks for attachments in the same folder with same name as the corresponding record
smtp_ssl_host = 'smtp.office365.com'
smtp_ssl_port = 587
email_login = "xxx#xxx.com" #Office 365 email
email_from = tosendfrom
email_to = Emaitstosendto
msg = MIMEMultipart()
msg['Subject'] = "Received Emails between "+date_7days+" - "+date_14days
msg['From'] = email_from
msg['To'] = email_to
msg['X-Priority'] = '2'
text = ("XXXX,\n"
f"xxxxxx\n\n")
msg.attach(MIMEText(text))
filename = my_files_dict.get(ID)#Files in the folder matching the ID
fo = open(filename,'rb')
s2 = smtplib.SMTP(smtp_ssl_host, smtp_ssl_port)
s2.starttls(context=context)
s2.login(email_login, email_pass)
attachment = email.mime.application.MIMEApplication(fo.read(),_subtype="xlsx")
fo.close()
attachment.add_header('Content-Disposition','attachment',filename=filename)
msg.attach(attachment)
s2.send_message(msg)
s2.quit()
Taken from this answer: How to send email to multiple recipients using python smtplib?
This is the line you have to change:
First split the email_to into a list of different emails and then join using ", "
msg['To'] = ", ".join(email_to.split(";"))

Python send emails with corresponding attachments

I have a desktop folder with 3 XLSX files: ID1.xlsx, ID2.xlsx, ID3.xlsx
I can use the following code to loop through a list of 3 email addresses and send individual emails to each address, but it attaches all XLSX files in the folder.
Expected Result: I want to attach ID1.xlsx to the first email and send, ID2.xlsx to the 2nd email and send, and finally ID3.xlsx to the 3rd email and send.
email_addresses = ['test1#test.com', 'test2#test.com', 'test3#test.com']
class EmailsSender:
def __init__(self):
self.outlook = win32.Dispatch('outlook.application')
def send_email(self, to_email_address, attachment_path):
mail = self.outlook.CreateItem(0)
mail.To = to_email_address
mail.Subject = 'Report'
mail.Body = """Report is attached."""
if attachment_path:
mail.Attachments.Add(Source=attachment_path, Type=olByValue)
mail.Send()
def send_emails(self, email_addresses, attachment_path=None):
for email in email_addresses:
self.send_email(email, attachment_path)
attachment_path = r'C:\Users\Desktop\Test\*.xlsx'
email_sender = EmailsSender()
email_sender.send_emails(email_addresses, attachment_path)
You will need to reference the file name with email so switch to Dictionaries.
Example
email_addresses = {'test1#test.com': 'ID1.xlsx',
'test2#test.com': 'ID2.xlsx',
'test3#test.com': 'ID3.xlsx'
}
attachment_path = r'C:\Users\Desktop\Test'
for email, file in email_addresses.items():
print(email, attachment_path + file)

Use python to download email attachments only based on Subject

The following code uses imap to find emails by subject line and returns all parts of the email and downloads the attachments. However i am ONLY needing it to download the attachments of the email not the entire body also. I understand this has to do with the for part in email_message.walk(): that is iterating the entire email. Could someone please help me have this code download only the attachment of the email? Im sure this is a simple code change but im just not sure how to make it!
import imaplib
import email.header
import os
import sys
import csv
# Your IMAP Settings
host = 'imap.gmail.com'
user = 'User email'
password = 'User password'
# Connect to the server
print('Connecting to ' + host)
mailBox = imaplib.IMAP4_SSL(host)
# Login to our account
mailBox.login(user, password)
boxList = mailBox.list()
# print(boxList)
mailBox.select()
searchQuery = '(SUBJECT "CDR Schedule output from schedule: This is a test to see how it works")'
result, data = mailBox.uid('search', None, searchQuery)
ids = data[0]
# list of uids
id_list = ids.split()
i = len(id_list)
for x in range(i):
latest_email_uid = id_list[x]
# fetch the email body (RFC822) for the given ID
result, email_data = mailBox.uid('fetch', latest_email_uid, '(RFC822)')
# I think I am fetching a bit too much here...
raw_email = email_data[0][1]
# converts byte literal to string removing b''
raw_email_string = raw_email.decode('utf-8')
email_message = email.message_from_string(raw_email_string)
# downloading attachments
for part in email_message.walk():
if part.get_content_maintype() == 'multipart':
continue
if part.get('Content-Disposition') is None:
continue
fileName = part.get_filename()
if bool(fileName):
filePath = os.path.join('C:/install files/', fileName)
if not os.path.isfile(filePath) :
fp = open(filePath, 'wb')
fp.write(part.get_payload(decode=True))
fp.close()
subject = str(email_message).split("Subject: ", 1)[1].split("\nTo:", 1)[0]
print('Downloaded "{file}" from email titled "{subject}" with UID {uid}.'.format(file=fileName, subject=subject, uid=latest_email_uid.decode('utf-8')))
mailBox.close()
mailBox.logout()

Categories

Resources