How to automatically send personalized emails with a pdf attachment in Python? - python

I am a beginner programmer and I am trying to write a program that automatically sends personalized emails to a list of receivers in a csv file with a pdf attachment.
My current code sends personalized emails but I don't know how to add an attachment. Also, I think it's best practice to write the program in a function but I don't know how to do that either.
It would be greatly appreciated if anyone could help me out. Also, I want to keep it as simple as possible so that I still understand what every line of code does.
import os
import smtplib, ssl
import csv
# Sender credentials (from environment variables)
email_address = os.environ.get("email_user")
email_pass = os.environ.get("email_app_pass")
context = ssl.create_default_context()
with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
server.login(email_address, email_pass) # Log into sender email account
# Email information
subject = "Testing Python Automation"
body = """ Hi {name},\n\n This email was entirely generated in Python. So cool!
"""
msg = f"Subject: {subject}\n\n{body}"
with open("contacts_test.csv") as file:
reader = csv.reader(file)
next(reader) # Skip header row
for name, email in reader:
server.sendmail(email_address, email, msg.format(name=name))
file.close()
server.quit()

This will only work using gmail and make sure you have manually set up
special permissions on your gmail account for the program to be able to send email on behalf of you. The process is described here.
You can use other email address services for that you need to change the smtp server address and the smtp port number in line 32 accordingly and take care of any other additional steps required.
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
body = """
Hi {name},\n\n This email was entirely generated in Python. So cool!
""".format(name="Name")
# details
sender = 'example1#gmail.com' # my email
password = '&*password.$' # my email's password
receiver = 'example2#gmail.com' # receiver's email
msg = MIMEMultipart()
msg['To'] = receiver
msg['From'] = sender
msg['Subject'] = 'Testing Python Automation'
msg.attach(MIMEText(body, 'plain'))
pdfname = "mypdf.pdf" # pdf file name
binary_pdf = open(pdfname, 'rb')
payload = MIMEBase('application', 'octate-stream', Name=pdfname)
payload.set_payload((binary_pdf).read())
encoders.encode_base64(payload)
payload.add_header('Content-Decomposition', 'attachment', filename=pdfname)
msg.attach(payload)
session = smtplib.SMTP('smtp.gmail.com', 587)
session.starttls()
session.login(sender, password)
text = msg.as_string()
session.sendmail(sender, receiver, text)
session.quit()
print('[#] Mail Sent!')

Related

send HTMLbody from file using python

I can send the plain text but unable to send html text in html format.
import email, smtplib, ssl
import os
from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
body = """
this is first mail by using python
"""
port_email = 587
smtp_server = "smtp.gmail.com"
password = "your password"
subject = "An email with attachment from Python"
sender_email = "sender#gmail.example.com"
receiver_email = "receiver#example.net"
# Create a multipart message and set headers
message = MIMEMultipart()
message["From"] = sender_email
message["To"] = receiver_email
message["Subject"] = subject
message["Bcc"] = receiver_email # Recommended for mass emails
# Add body to email
message.attach(MIMEText(body, "plain"))
filename = "file name" # In same directory as script
with open(filename.html, 'r', encoding="utf-8") as attachment:
part1 = attachment.read()
part2 = MIMEText(part1, "html")
message.attach(part2)
text = message.as_string()
context = ssl.create_default_context()
with smtplib.SMTP_SSL(smtp_server, 465 , context=context) as server:
server.login(sender_email, password)
server.sendmail(sender_email, receiver_email, text)
This will send attach file but i want to see the html text in email body.
filename is content html table so code should send the html text which will automatic available in html body with html table.
Why are you passing a bogus body if that's not what you want?
Your code seems to be written for Python 3.5 or earlier. The email library was overhauled in 3.6 and is now quite a bit more versatile and logical. Probably throw away what you have and start over with the examples from the email documentation.
Here's a brief attempt.
from email.message import EmailMessage
...
message = EmailMessage()
message["From"] = sender_email
message["To"] = receiver_email
message["Subject"] = subject
# No point in using Bcc if the recipient is already in To:
with open(filename) as fp:
message.set_content(fp.read(), 'html')
# no need for a context if you are just using the default SSL
with smtplib.SMTP_SSL(smtp_server, 465) as server:
server.login(sender_email, password)
# Prefer the modern send_message method
server.send_message(message)
If you want to send a message in both plain text and HTML, the linked examples show you how to adapt the code to do that, but then really, the text/plain body part should actually contain a useful message, not just a placeholder.
As commented in the code, there is no reason to use Bcc: if you have already specified the recipient in the To: header. If you want to use Bcc: you will have to put something else in the To: header, commonly your own address or an address list like :undisclosed-recipients;
Tangentially, when opening a file, Python (or in fact the operating system) examines the user's current working directory, not the directory from which the Python script was loaded. Perhaps see also What exactly is current working directory?
Mime has a variety of formats. By default MIMEMultipart builds a multipart/mixed message, meaning a simple text body and a bunch of attachments.
When you want an HTML representation of the body, you want a multipart/alternative message:
...
message = MIMEMultipart('alternative')
...
But you are using the old compat32 API. Since Python 3.6 you'd better use email.message.EmailMessage...

Python SMTPLIB Gmail recipient security issues

I am trying to send emails with already made Zip attachments and I am running into errors with gmail's security kicking them back. Originally I was using a gmail account to send the email, but I learned that gmail blocks that. So now I am using an outlook email. It sends the emails, which is an improvement, but my recipient emails (gmail) are returning the emails. How do people get around this? Surely there has to be a way to send zip files to gmail addresses. Here is my code:
UPDATE: I opened the returned email I sent - the attached file is a .bin file, not the .zip file. I may be misunderstanding the code and converting the zip file to binary rather than just attaching it.
def send_mail(zips_folder):
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
sender_email = "senderEmail#outlook.com"
receiver_email ="receiverEmail#gmail.com"
message = MIMEMultipart()
message["From"] = sender_email
message['To'] = receiver_email
message['Subject'] = "subject"
zf = open(r"C:\Users\Full File Path to Zip File\Zip File Name.zip",'rb')
obj = MIMEBase('application', 'octet-stream')
obj.set_payload(zf.read())
encoders.encode_base64(obj)
obj.add_header('Content-Disposition', "attachment; filename= " )
message.attach(obj)
my_message = message.as_string()
email_session = smtplib.SMTP("smtp-mail.outlook.com", 587)
email_session.starttls()
email_session.login(sender_email, 'email password')
email_session.sendmail(sender_email, receiver_email, my_message)
email_session.quit()
print("YOUR MAIL HAS BEEN SENT SUCCESSFULLY")

How to get smtp email log

I want to get a log when I email to the wrong email address.
so, I wrote this command.
mailserver = mymailserver
to_email = emailaddress
from_email = fromaddress
subject = SBJECT
original_message = TEXT
message = MESSAGE
server = smtplib.SMTP(mailserver)
debug = server.set_debuglevel(1)
server.sendmail(from_mail,to_mail, message)
server.quit()
print(debug)
I just want to know connection status log.
wchich code should I edit?
I tried this scripts, but it does not work well.
server = smtplib.SMTP(mailserver)
mail_response = server.sendmail(from_mail,to_mail, message)
server.quit()
print(mail_response)
Thank you for helping me.
Try This and read the docs. Hope it will help you
# Import smtplib for the actual sending function
import smtplib
# Import the email modules we'll need
from email.message import EmailMessage
# Open the plain text file whose name is in textfile for reading.
# Or simply skip this part
with open(textfile) as fp:
# Create a text/plain message
msg = EmailMessage()
msg.set_content(fp.read())
# me == the sender's email address
# you == the recipient's email address
msg['Subject'] = f'The contents of {textfile}'
msg['From'] = me
msg['To'] = you
# Send the message via our own SMTP server.
s = smtplib.SMTP('localhost')
s.send_message(msg)
s.quit()

Python: Sending email with attachment only with the stdlib?

I want to send an email with attachment (for example a text file) with python. Is this possible with the stdlib or do I have to download and install other packages?
I would like to do this with the stdlib.
thx. :)
You can try this:
# Import smtplib for the actual sending function
import smtplib
# Import the email modules we'll need
from email.mime.text import MIMEText
# Open a plain text file for reading. For this example, assume that
# the text file contains only ASCII characters.
fp = open(textfile, 'rb')
# Create a text/plain message
msg = MIMEText(fp.read())
fp.close()
# me == the sender's email address
# you == the recipient's email address
msg['Subject'] = 'The contents of %s' % textfile
msg['From'] = me
msg['To'] = you
# Send the message via our own SMTP server.
s = smtplib.SMTP('localhost')
s.send_message(msg)
s.quit()

How to send Gmail email with multiple CC:'s

I am looking for a quick example on how to send Gmail emails with multiple CC:'s. Could anyone suggest an example snippet?
I've rustled up a bit of code for you that shows how to connect to an SMTP server, construct an email (with a couple of addresses in the Cc field), and send it. Hopefully the liberal application of comments will make it easy to understand.
from smtplib import SMTP_SSL
from email.mime.text import MIMEText
## The SMTP server details
smtp_server = "smtp.gmail.com"
smtp_port = 587
smtp_username = "username"
smtp_password = "password"
## The email details
from_address = "address1#domain.com"
to_address = "address2#domain.com"
cc_addresses = ["address3#domain.com", "address4#domain.com"]
msg_subject = "This is the subject of the email"
msg_body = """
This is some text for the email body.
"""
## Now we make the email
msg = MIMEText(msg_body) # Create a Message object with the body text
# Now add the headers
msg['Subject'] = msg_subject
msg['From'] = from_address
msg['To'] = to_address
msg['Cc'] = ', '.join(cc_addresses) # Comma separate multiple addresses
## Now we can connect to the server and send the email
s = SMTP_SSL(smtp_server, smtp_port) # Set up the connection to the SMTP server
try:
s.set_debuglevel(True) # It's nice to see what's going on
s.ehlo() # identify ourselves, prompting server for supported features
# If we can encrypt this session, do it
if s.has_extn('STARTTLS'):
s.starttls()
s.ehlo() # re-identify ourselves over TLS connection
s.login(smtp_username, smtp_password) # Login
# Send the email. Note we have to give sendmail() the message as a string
# rather than a message object, so we need to do msg.as_string()
s.sendmail(from_address, to_address, msg.as_string())
finally:
s.quit() # Close the connection
Here's the code above on pastie.org for easier reading
Regarding the specific question of multiple Cc addresses, as you can see in the code above, you need to use a comma separated string of email addresses, rather than a list.
If you want names as well as addresses you might as well use the email.utils.formataddr() function to help get them into the right format:
>>> from email.utils import formataddr
>>> addresses = [("John Doe", "john#domain.com"), ("Jane Doe", "jane#domain.com")]
>>> ', '.join([formataddr(address) for address in addresses])
'John Doe <john#domain.com>, Jane Doe <jane#domain.com>'
Hope this helps, let me know if you have any problems.
If you can use a library, I highly suggest http://libgmail.sourceforge.net/, I have used briefly in the past, and it is very easy to use. You must enable IMAP/POP3 in your gmail account in order to use this.
As for a code snippet (I haven't had a chance to try this, I will edit this if I can):
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email import Encoders
import os
#EDIT THE NEXT TWO LINES
gmail_user = "your_email#gmail.com"
gmail_pwd = "your_password"
def mail(to, subject, text, attach, cc):
msg = MIMEMultipart()
msg['From'] = gmail_user
msg['To'] = to
msg['Subject'] = subject
#THIS IS WHERE YOU PUT IN THE CC EMAILS
msg['Cc'] = cc
msg.attach(MIMEText(text))
part = MIMEBase('application', 'octet-stream')
part.set_payload(open(attach, 'rb').read())
Encoders.encode_base64(part)
part.add_header('Content-Disposition',
'attachment; filename="%s"' % os.path.basename(attach))
msg.attach(part)
mailServer = smtplib.SMTP("smtp.gmail.com", 587)
mailServer.ehlo()
mailServer.starttls()
mailServer.ehlo()
mailServer.login(gmail_user, gmail_pwd)
mailServer.sendmail(gmail_user, to, msg.as_string())
# Should be mailServer.quit(), but that crashes...
mailServer.close()
mail("some.person#some.address.com",
"Hello from python!",
"This is a email sent with python")
For the snippet I modified this

Categories