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()
Related
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!')
Using the email and smtp libraries, I have developed a script that automatically sends mail via outlook's smtp server.
I enter the content of the mail and after the content is written I want to send the picture at the bottom.
But it sends the picture not at the bottom as I want it, but at the top of the mail content.
Example mail ( This is only image ) : https://ibb.co/d5HFwRG
My code:
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
def send_mail(gender, messages, subject):
global msg
try:
msg = MIMEMultipart()
s = smtplib.SMTP(host="SMTP.office365.com", port=587)
s.starttls()
s.login(mail, password)
msg['From'] = mail
msg['To'] = example#outlook.com
msg['Subject'] = messages
msg.attach(MIMEText(message, 'plain', 'utf-8'))
attachment = open("image.jpg", "rb")
p = MIMEBase('application', 'octet-stream')
p.set_payload((attachment).read())
encoders.encode_base64(p)
p.add_header('Content-Disposition', "attachment; filename= %s" % image)
msg.attach(p)
s.send_message(msg)
del msg
except Exception as e:
print(e)
My code is actually much more complex, but I just showed you the function I use to send mail.
I had to change the names of some variables while adding them here, so the above code may not work for you, you need to edit it.
How can I get that picture sent in the Mail to the bottom?
Hi I'm new to learning python and I'm trying to send emails to a few hundred different recipients with a different attachment to each of them. I have the recipients data in a database and a folder with all the files in it.
Database has supplier id, name and email
Database example
The folder structure is just one folder with all the files in it for example :
Folder screenshot
Supplier files folder --
123.xls
123.pdf
456.xls
789.pdf
any direction on how to get started with this is appreciated. Thank you
In this example I will use an answer that I gave to another question (How do I attach separate PDF's to contact list email addresses using Python?) , I use a csv file that contains the addresses and the file path that corresponds to it like img bellow :
users.csv :
folder with csv files :
And this is the code:
import smtplib, ssl
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
from string import Template
import pandas as pd
# read the file containing the database with the mail and the corresponding file
e = pd.read_csv("users.csv")
# In this example we will use gmail
context = ssl.create_default_context()
server = smtplib.SMTP_SSL('smtp.gmail.com', 465,context=context)
server.login('mymail#gmail.com','mypass')
body = ("""
Hi there
Test message
Thankyou
""")
subject = "Send emails with attachment"
fromaddr='mymail#gmail.com'
for index, row in e.iterrows():
print (row["Emails"]+row["csv"])
msg = MIMEMultipart()
msg['From'] = fromaddr
msg['Subject'] = subject
msg.attach(MIMEText(body, 'plain'))
filename = row["csv"]
toaddr = row["Emails"]
attachment = open(row["csv"], "rb")
part = MIMEBase('application', 'octet-stream')
part.set_payload((attachment).read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', "attachment; filename= %s" % filename)
msg.attach(part)
text = msg.as_string()
server.sendmail(fromaddr, toaddr, text)
print("Emails sent successfully")
server.quit()
if you use a gmail account, check that you have it permissions to send emails from other types of clients (https://support.google.com/accounts/answer/6010255)
I've just started learning Python and I'm trying to code a bot where it emails a HTML message along with a .docx (Microsoft Word) attachment. Here's my code and it works fine, but I'm confused with a few of the parameters.
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
import os
#Email Variables
myemail = "myemail#hotmail.com"
recipient = "recipientemail#hotmail.com"
#Specifying MIME variables to include in email header
mime_details = MIMEMultipart('mixed')
mime_details['Subject'] = "This is my email subject!"
mime_details['From'] = myemail
mime_details['To'] = recipient
#Creating body of message
html_body = """\
<html>\
<p>\
My email message!
</p>\
</html>\
"""
#Attaching File To Email
os.chdir('C:\\Users\Kyle\Desktop\')
openfile = open('testfile.docx', 'rb')
doc = MIMEApplication(openfile.read(), _subtype='vnd.openxmlformats-officedocument.wordprocessingml.document')
doc.add_header('Content-Disposition', 'attachment', filename='My Content.docx')
mime_details.attach(doc)
openfile.close()
#Recording MIME types of email parts
htmlpart = MIMEText(html_body, _subtype='html')
#Attaching parts to message container
mime_details.attach(htmlpart)
#Sending message via SMTP server
s = smtplib.SMTP(host='smtp.live.com', port=587)
s.ehlo()
s.starttls()
s.login(myemail, 'password')
s.sendmail(myemail, recipient, mime_details.as_string())
s.quit()
I have a few questions regarding the code above, and I would greatly appreciate it if you can help me clear whatever confused thoughts I have regarding the modules above.
A) The add_header module
mime_details['Subject'] = "This is my email subject!"
mime_details['From'] = myemail
mime_details['To'] = recipient
As you can see from the snippet above, I clearly defined each header variable in the MIMEMultipart envelope. According to Python's docs, these values will be added to the header directly. I tried using the add_header() method directly as an alternative, something like:
mime_details.add_header(Subject = "This is my email subject!", To = recipient, From = myemail)
But it gave me errors. Any idea why?
B) At the last few lines of my code, I had to append a .as_string() to the payload I was sending. I tried taking it out but it gave me a TypeError: expected string or buffer.
The Python docs give me this:
as_string(unixfrom=False, maxheaderlen=0, policy=None)
Return the entire message flattened as a string.
I assume that I have to append this in every case? the mime_details object has two parts to it - the HTML message and the .docx file. Both will be converted to strings? What about image files?
C) When I open my file to attach, I read it in 'rb' mode.
Here's the code:
openfile = open('testfile.docx', 'rb')
I tried using 'r' but it raises an error. I've read up on this and 'rb' mode simply opens the file in binary. Why would it make sense to open a .docx file in binary mode? Am I to use 'rb' mode for ALL non.txt files?
D) Finally, I've seen some people use base64 encoding for attachments. I've searched around and a particularly popular script over here is below (from How to send email attachments with Python):
import smtplib, os
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email.utils import COMMASPACE, formatdate
from email import encoders
def send_mail( send_from, send_to, subject, text, files=[], server="localhost", port=587, username='', password='', isTls=True):
msg = MIMEMultipart()
msg['From'] = send_from
msg['To'] = COMMASPACE.join(send_to)
msg['Date'] = formatdate(localtime = True)
msg['Subject'] = subject
msg.attach( MIMEText(text) )
for f in files:
part = MIMEBase('application', "octet-stream")
part.set_payload( open(f,"rb").read() )
encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="{0}"'.format(os.path.basename(f)))
msg.attach(part)
smtp = smtplib.SMTP(server, port)
if isTls: smtp.starttls()
smtp.login(username,password)
smtp.sendmail(send_from, send_to, msg.as_string())
smtp.quit()
Why does content need to be encoded in base64? Does this apply to all files and is a general thing to be added, or can I ignore this? What situations am I to invoke that method?
Finally, being a noob at Python, some of my code above may be redundant\badly structured. If you have any tips\suggestions on how I can improve my simply script, please do let me know.
Thank you!
I want to create a python script to auto reply html mail from postfix pipe:
Example in aliases file:
testmail: "| python /opt/script/autoreply.py /opt/script/autoreply.html"
The autoreply.html will contain the html email.
There is an example from python:
https://docs.python.org/2/library/email-examples.html#id5
to send an alternative MIMEMultipart
I want to use that example to my script. The idea is load the autoreply.html file.
#!/usr/bin/env python
#autoreply.py
import smtplib
import sys
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
# me == my email address
# you == recipient's email address
me = "my#email.com"
you = "you#email.com"
# Create message container - the correct MIME type is multipart/alternative.
msg = MIMEMultipart('alternative')
msg['Subject'] = "Link"
msg['From'] = me
msg['To'] = you
# Create the body of the message (a plain-text and an HTML version).
text = open(sys.argv[1], 'r')
html = open(sys.argv[2], 'r')
# Record the MIME types of both parts - text/plain and text/html.
part1 = MIMEText(text.read(), 'plain')
text.close()
part2 = MIMEText(html.read(), 'html')
html.close()
# Attach parts into message container.
# According to RFC 2046, the last part of a multipart message, in this case
# the HTML message, is best and preferred.
msg.attach(part1)
msg.attach(part2)
# Send the message via local SMTP server.
s = smtplib.SMTP('smtprelay.gameloft.org')
# sendmail function takes 3 arguments: sender's address, recipient's address
# and message to send - here it is sent as one string.
s.sendmail(me, you, msg.as_string())
s.quit()
how can I edit that script to let the pipe send an html (autoreply.html) email? Change the from address, to address, from the original message, load the autoreply.html.
If there is no autoreply.txt file, load the autoreply.html by default. (the example from python need the text/plain)
Can someone help me? It is quite complex to me.
Thanks!