Sending an email with python using csv data for the body - python

I am using the csv library to pull data to into an email body. I am pulling certain columns from the csv for the body. I am using a junk gmail account to test. I'm just confused on how to use the for loop. If I'm correct, you need a for loop to read the rows then a for loop to email out. I did read Reading and Writing CSV Files but was uncertain how to implement it with smtplib.
import csv, smtplib, ssl
message = """Subject: Your Title
{supervisor} {title} {start}"""
from_address = "test#gmail.com"
password = input("Type your password and press enter: ")
context = ssl.create_default_context()
with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
server.login(from_address, password)
with open('test.csv','rb') as file:
reader = csv.reader(file, delimiter=',')
next(reader)
#start = []
#title = []
#supervisor = []
for row in reader:
title = row[3]
start = row[0]
supervisor = row[4]
for supervisor, title, start in reader:
server.sendmail(
from_address,
Email,
message.format(supervisor=supervisor, start=start, title=title)
)
print('Emails were sent successfully!')
CSV File:
StartDate,Employee Name,PC,Title,Supervisor Name,email
12/9/2019,Katti M. Ricke,289,Recruiter,Courtney Clark,test#gmail.com

Probably if you use pandas for to handle the csv could be more easy ..for install pandas just pip install pandas
import pandas as pd
import io
import smtplib, ssl
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
# read csv using pandas and then convert the csv to html string ....this code later will add into body
str_io = io.StringIO()
df = pd.read_csv('test.csv')
df.to_html(buf=str_io)
table_html = str_io.getvalue()
print(table_html)
sender_email = "mymail#gmail.com"
receiver_email = "anothermail#gmail.com"
password = "mypass"
message = MIMEMultipart("alternative")
message["Subject"] = "Subject: Your Title"
message["From"] = sender_email
message["To"] = receiver_email
text = """\
Subject: Your Title"""
html = """\
<html>
<body>
<p>{table_html}</p>
</body>
</html>
""".format(table_html=table_html)
part1 = MIMEText(text, "plain")
part2 = MIMEText(html, "html")
message.attach(part1)
message.attach(part2)
# Send email
context = ssl.create_default_context()
with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
server.login(sender_email, password)
server.sendmail(
sender_email, receiver_email, message.as_string()
)

Related

'smtplib.SMTPServerDisconnected' after many iterations

I am automating the sending of emails by iterating over a DataFrame but after many iterations have this error 'smtplib.SMTPServerDisconnected', I don't know what I can do to solve this problem.
My code is:
import pandas as pd
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
filename="my_excel.xlsx"
df=pd.read_excel(filename, sheet_name='Sheet1')
user = 'my_mail'
app_password = 'password'
host = 'smtp.gmail.com'
port = 465
subject = 'Proof'
attachment = "attachment.pdf"
while i<=len(df):
if df['Status'][i]=='vencido':
text='my_text'
to = df['email'][i]
message = MIMEMultipart()
message['From'] = Header(user)
message['To'] = Header(to)
message['Subject'] = Header(subject)
content_txt= text
message.attach(MIMEText(content_txt, 'plain', 'utf-8'))
att_name = os.path.basename(attachment)
att1 = MIMEText(open(attachment, 'rb').read(), 'base64', 'utf-8')
att1['Content-Type'] = 'application/octet-stream'
att1['Content-Disposition'] = 'attachment; filename=' + att_name
message.attach(att1)
server = smtplib.SMTP_SSL(host, port)
server.login(user, app_password)
server.sendmail(user, to, message.as_string())
server.quit()

date error and styling issue in python code while reading an excel file and emailing

I have a code which reads an excel file and generates an image from the data frame which is added to the body of the email everything works fine except I am facing an issue where i am unable to style the 2nd 3rd and 4th column as center align , also the date format seems to be with the timestamp which i am unable to get rid of. Below is the code
import pandas as pd
import plotly.figure_factory as ff
import plotly.graph_objects as go
# import SMTP
pd.options.display.float_format = '{:.4f}'.format
df = pd.read_excel('C:\\Users\Automation\\Droom Technology Dropbox\\Analytics and
Planning\\Analytics\\13. Trackers\\decision science automation\\Nikhil\\Daily Marketplace
Tracker.xlsx',sheet_name='Sheet1')
# pd.options.display.max_columns = 500000
#df['date'] = pd.to_datetime(df['date']).dt.date
# df.columns = range(df.shape[1])
lastCloumnsRange = df.shape[1] - 3
df.drop(df.iloc[:, 1:lastCloumnsRange], inplace=True, axis=1)
print(df)
df.dropna(inplace = True)
fig = ff.create_table(df)
fig.update_layout(
autosize=True,
width=500,
height=400,
)
for i in range(len(fig.layout.annotations)):
fig.layout.annotations[i].font.size = 6
# fig.update_traces(cells_font=dict(size = 15))
fig.write_image("table_plotly.png", scale=2)
########## Mailing Code ###############
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
from email import encoders
fromaddr = "Shrikant.ravi#xyz.in"
toaddr = ['nikhil.khandelwal#xyz.in']
# instance of MIMEMultipart
msg = MIMEMultipart()
# storing the senders email address
msg['From'] = fromaddr
# storing the receivers email address
msg['To'] = ", ".join(toaddr)
# storing the subject
msg['Subject'] = "Daily marketplace tracker"
# string to store the body of the mail
body = "Please find attached the graphs for your reference"
# %%
# In[4]:
text = MIMEText('Hello Everyone,\n \nPlease find below the daily Marketplace tracker for your
reference. \n \n \n')
msg.attach(text)
# In[5]:
text1 = MIMEText('<img src="cid:image1">', 'html')
msg.attach(text1)
image = MIMEImage(open('C:\\Users\\Automation\\Desktop\\table_plotly.png', 'rb').read())
# Define the image's ID as referenced in the HTML body above
image.add_header('Content-ID', '<image1>')
msg.attach(image)
filename = "Daily Marketplace Tracker.xlsx"
attachment = open('C:\\Users\Automation\\Droom Technology Dropbox\\Analytics and
Planning\\Analytics\\13. Trackers\\decision science automation\\Nikhil\\Daily Marketplace
Tracker.xlsx', "rb")
# instance of MIMEBase and named as p
p = MIMEBase('application', 'octet-stream')
# To change the payload into encoded form
p.set_payload((attachment).read())
# encode into base64
encoders.encode_base64(p)
p.add_header('Content-Disposition', "attachment; filename= %s" % filename)
# attach the instance 'p' to instance 'msg'
msg.attach(p)
# creates SMTP session
s = smtplib.SMTP('smtp.gmail.com', 587)
# start TLS for security
s.starttls()
# Authentication
s.login(fromaddr, "xxxx")
# Converts the Multipart msg into a string
text = msg.as_string()
# sending the mail
s.sendmail(fromaddr, toaddr, text)
# terminating the session
s.quit()
# In[ ]:
excel reference link

Python how to remove header when sending an email?

I am trying to remove the header section, currently the received email looks like this:
.
I don't want it to be displayed when the receiver gets the email, I am not sure how to hide it.
I tried to just delete it but received an error. That code is included but commented out below.
import donator
import csv
import os
import smtplib
from email.message import EmailMessage
from email.mime.text import MIMEText
def ReadEmailTemplate():
oFile = open('EmailTemplate.txt', 'r')
Subject = oFile.readline()
Body = oFile.read()
return [Subject, Body]
def ReadCSVFile():
with open('ExampleData.csv', 'r') as csv_file:
csv_reader = csv.reader(csv_file)
allDonators = []
for line in csv_reader:
Number = line[0]
Name = line[1]
Amount = line[2]
Date = line[3]
Mode = line[4]
Email = line[5]
allDonators.append(donator.Donator(Number, Name, Amount, Date, Mode, Email))
return allDonators
txt = ReadEmailTemplate()
Subject = txt[0]
Body = txt[1]
# READ VALUES FROM CSV FILE AND RUN THROUGH THEM
allDonators = ReadCSVFile()
# CREATE EMAIL WITH THOSE VALUES
for donator in allDonators:
print(f'Sending email to: {donator.Name} at {donator.Email}...')
msg = EmailMessage()
Body = MIMEText(
Body.replace('REPLACE_DATE', donator.Date).replace('DONATION_AMOUNT', donator.Amount).replace('DONATION_DATE',
donator.Date))
msg.set_content(Body)
msg['From'] = os.environ['PERS_EMAIL']
msg['To'] = donator.Email
msg['Subject'] = Subject.replace('CUSTOMER_NAME', donator.Name)
print(msg.get('Content-Type'))
print(msg.get('Content-Transfer-Encoding'))
print(msg.get('MIME-Version'))
#for hdr in ['Content-Type', 'Content-Transfer-Encoding', 'MIME-Version']:
# del msg[hdr]
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:
smtp.login(os.environ['PERS_EMAIL'], os.environ['PERS_EMAILPW'])
smtp.sendmail(os.environ['PERS_EMAIL'], donator.Email, msg.as_string())
smtplib.SMTP_SSL('smtp.gmail.com', 465).quit()
In ReadEmailTemplate, you have Subject = oFile.readline(). file.readline() leaves the newline '\n' in the line. So, your subject line is followed by a blank line, which terminates the headers, and the rest of the headers are seen as message. Just do
Subject = oFile.readline().strip()
Note that you don't have to split out the fields of your CSV:
for line in csv_reader:
allDonators.append(donator.Donator(*line))

Send gmail with multiple recipients

I am trying to create a bulk email sender. I am struggling to add multiple recipients. I want the script to open contacts.csv that contains multiple email addresses, and send the email to them.
Simply, I need help creating a script that opens the csv file, reads the emails and sends the email to those addresses.
I have tried this but it did not work:
with smtplib.SMTP("smtp.gmail.com:587") as server:
with open("contacts.csv") as file:
reader = csv.reader(file)
next(reader) # Skip header row
for name, email in reader:
server.sendmail(
sender_email,
email,text
#message.format(name=name),
)
my contacts.csv file:
name, email
john, test1#gmail.com
jake, test2#gmail.com
my emailsender.py file:
import smtplib
from email import encoders
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
fromaddr = "myemail#gmail.com"
toaddr = "emails#gmail.com"
msg = MIMEMultipart()
msg['From'] = fromaddr
msg['To'] = toaddr
msg['Subject'] = "test"
body = "testing"
msg.attach(MIMEText(body, 'plain'))
s = smtplib.SMTP('smtp.gmail.com', 587)
s.starttls()
s.login(fromaddr, "password")
text = msg.as_string()
s.sendmail(fromaddr, toaddr, text)
print("Email sent!")
s.quit()
send()
I have tested this code and it works fine:
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import csv
emails = []
with open('test.csv', 'r') as file: #open csv file
reader = csv.reader(file) #init the csv reader
for row in reader: #iterate through all rows in the csv file
emails.append(row[1]) #add the second element of every row (the email column) to the list "emails"
emails.pop(0) #remove the first email which is just the text "email" in the csv file that we don't want
print(emails) #remove if you wish
def sender(recipients, from_email, password, body, subj): #create a sender function. partially adapted from https://stackoverflow.com/a/51931160/8402369
msg = MIMEMultipart()
msg['Subject'] = subj
msg['From'] = from_email
msg['To'] = (', ').join(recipients)
msg.attach(MIMEText(body,'plain'))
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(from_email, password)
server.send_message(msg)
server.quit()
sender(emails, 'youremail#gmail.com', 'your_password', 'Message body', 'Subject') #send all emails
Run and edit the code online
EDIT:
Here's a version with the ability to change the email content based on the csv data:
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import csv
csvdata = []
with open('test.csv', 'r') as file: #open csv file
reader = csv.reader(file) #init the csv reader
for row in reader: #iterate through all rows in the csv file
csvdata.append(
row #instead of adding the email to the array, add the whole row to the array
) #add the second element of every row (the email column) to the list "emails"
csvdata.pop(0)
def sender(
recipient, name_to_display, from_email, password, body, subj
): #create a sender function. partially adapted from https://stackoverflow.com/a/51931160/8402369
msg = MIMEMultipart()
msg['Subject'] = subj
msg['From'] = f'{name_to_display} <{from_email}>'
msg['To'] = recipient
msg.attach(MIMEText(body, 'plain'))
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(from_email, password)
server.send_message(msg)
server.quit()
your_email = "email#gmail.com"
your_password = "password"
name_to_display = "The name of the sender that displays in the inbox (your name or whatever you want)"
for item in csvdata:
name = item[0] #the first column of the csv file is the name
email = item[1] #the second is the email. if you have more columns get them here like so: item[2] (change the index accordingly)
print(f'Sending email to {email}')
body = "Hi " + name + ", The rest of the content goes here"
subject = "Subject"
sender(email, name_to_display, your_email, your_password, body, subject)
Run and edit this code online
Notes:
The sender function is partially adapted from here

send email to recipient from .txt in python 3.3

I am trying to send an email with smtp in python 3.3 to a recipient listed in a text file.
The error I receive is:
session.sendmail(sender, recipient, msg.as_string())
smtplib.SMTPRecipientsRefused: {}
Where is the error in sendmail? Thanks!
Full code below:
#!/usr/bin/python
import os, re
import sys
import smtplib
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
mails = open('/path/emails.txt','r+')
mailList = mails.read()
mailList = [i.strip() for i in mails.readlines()]
directory = "/path/Desktop/"
SMTP_SERVER = 'smtp.gmail.com'
SMTP_PORT = 587
sender = 'Sender#gmail.com'
password = "Sender'sPassword"
recipient = [i.strip() for i in mails.readlines()]
subject = 'Python (-++-) Test'
message = 'Images attached.'
def main():
msg = MIMEMultipart()
msg['Subject'] = 'Python (-++-) Test'
msg['To'] = recipient
msg['From'] = sender
files = os.listdir(directory)
pngsearch = re.compile(".png", re.IGNORECASE)
files = filter(pngsearch.search, files)
for filename in files:
path = os.path.join(directory, filename)
if not os.path.isfile(path):
continue
img = MIMEImage(open(path, 'rb').read(), _subtype="png")
img.add_header('Content-Disposition', 'attachment', filename=filename)
msg.attach(img)
part = MIMEText('text', "plain")
part.set_payload(message)
msg.attach(part)
session = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
session.ehlo()
session.starttls()
session.ehlo
session.login(sender, password)
session.sendmail(sender, recipient, msg.as_string())
session.quit()
if __name__ == '__main__':
main()
You want to double-check your recipients code. It looks like you're trying to consume the contents of the file more than once, which won't work--the file objects should be understood as a stream, not a block of data, so once you've done f.read() or [i.strip() for i in mails.readlines()] one time, that stream is empty, so doing it a second time is going to produce an empty list. You should check this yourself by printing recipient
then try this:
mails = open('/path/emails.txt','r+')
#mailList = mails.read()
#mailList = [i.strip() for i in mails.readlines()]
directory = "/path/Desktop/"
SMTP_SERVER = 'smtp.gmail.com'
SMTP_PORT = 587
sender = 'Sender#gmail.com'
password = "Sender'sPassword"
recipient = [i.strip() for i in mails.readlines()]
print(recipient)
subject = 'Python (-++-) Test'
message = 'Images attached.'
Now you should have the a populated recipient list, and on to the next issue!

Categories