Sending Email attachment (.txt file) using Python 2.7 (smtplib) [duplicate] - python

This question already has answers here:
How to send email attachments?
(19 answers)
Closed 8 years ago.
So I'm trying to send a .txt file as an attachment and I can't find the right code to work. Here is my code:
import pythoncom
import win32gui
import win32console
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
fromaddr = 'zover1#gmail.com'
toaddrs = 'zover2#gmail.com'
msg = "contrl text file"
username = 'zover1#gmail.com'
password= 'xxxxxxxxxxxx'
server = smtplib.SMTP('smtp.gmail.com:587')
f = file("d:/control.txt")
attachment = MIMEText(f.read())
attachment.add_header('Content-Disposition', 'attachment', filename="d:/control.txt")
msg.attach(attachment)
server.ehlo()
server.starttls()
server.login(username, password)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
And when I run the module I get this error:
Traceback (most recent call last):
File "C:\Python278\emailonlytester.pyw", line 19, in <module>
msg.attach(attachment)
AttributeError: 'str' object has no attribute 'attach'
Any help would be much appreciated.

You can try this to send an attached file with python:
msg = MIMEMultipart()
msg['From'] = 'your adress'
msg['To'] = 'someone'
msg['Date'] = formatdate(localtime=True)
msg['Subject'] = 'a random subject'
msg.attach(MIMEText("some text"))
file = 'd:/control.txt'
attachment = MIMEBase('application', 'octet-stream')
attachment.set_payload(open(file,'rb').read())
encoders.encode_base64(attachment)
attachment.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(file))
msg.attach(attachment)
This is the part for the creation of the Email, not the sending.

The error is clearly stating the reason. msg is a string in your case. You may want to do the following instead:
msg = MIMEMultipart()
Docs are here.

Related

Can't send an attachment to my email using smtplib

I'm trying to send a csv file to my email address using smtplib library. When I run the script below, it sends the email without any issues. However, when I open that email I could see that there is no attachment in there.
I've tried with:
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
attachment = "outputfile.csv"
msg = MIMEMultipart()
msg['Subject'] = "Email a csv file"
msg['Body'] = "find the attachment"
msg['From'] = "someemail#gmail.com"
msg['To'] = "anotheremail#gmail.com"
part = MIMEBase('application', "octet-stream")
part.set_payload(open(attachment, "rb").read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment', filename=attachment)
msg.attach(part)
msg = f"Subject: {msg['Subject']}\n\n{msg['Body']}"
with smtplib.SMTP('smtp.gmail.com',587) as server:
server.ehlo()
server.starttls()
server.ehlo()
server.login('someemail#gmail.com','ivfpklyudzdlefhr')
server.sendmail(
'someemail#gmail.com',
'anotheremail#gmail.com',
msg
)
What possible change should I bring about to send a csv file to my email?
The code needs two changes
msg = f"Subject: {msg['Subject']}\n\n{msg['Body']}" is overwriting the message object msg with a string. It is not required and may be deleted.
To send a message object (as opposed to a string), use SMTP.send_message.
This code ought to work:
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
attachment = "outputfile.csv"
msg = MIMEMultipart()
msg['Subject'] = "Email a csv file"
msg['Body'] = "find the attachment"
msg['From'] = "someemail#gmail.com"
msg['To'] = "anotheremail#gmail.com"
part = MIMEBase('application', "octet-stream")
part.set_payload(open(attachment, "rb").read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment', filename=attachment)
msg.attach(part)
with smtplib.SMTP('smtp.gmail.com',587) as server:
server.ehlo()
server.starttls()
server.ehlo()
server.login('someemail#gmail.com','ivfpklyudzdlefhr')
server.send_message(msg)

Can't find file to send file as attachment in python

I found this code from another website repository and its used to send emails using python and attach's a file as well. It encodes the file in to base64 brfore sending it. I've tested the code before using an '.xlsx' file and it was sent with out a problem. But now the program doesnt send it for some reason. The file is in the same folder as the code.
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
fromaddr = "FROM EMAIL"
toaddr = "TO EMAIL"
msg = MIMEMultipart()
msg['From'] = fromaddr
msg['To'] = toaddr
msg['Subject'] = "SUBJECT"
body = "MESSAGE"
msg.attach(MIMEText(body, 'plain'))
filename = "05-11-2016 - Saturday.xlsx"
attachment = open("05-11-2016 - Saturday", "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)
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(fromaddr, "PASSWORD")
text = msg.as_string()
server.sendmail(fromaddr, toaddr, text)
server.quit()
When i run it ths is the error that is outputted:
line 21, in <module>
attachment = open("05-11-2016 - Saturday", "rb")
FileNotFoundError: [Errno 2] No such file or directory: '05-11-2016 - Saturday'
Any help would be appreciated.
you have defined filename in the line above - so why don't you use it? :)
(you forgot the extension 'xlsx' in the open statement)
You now have learned the usefullnes of the DRY-principle:
http://wiki.c2.com/?DontRepeatYourself
By typing it twice, you can change the filename definition and not notice, that the open uses another file...
I just ran your code using my credentials and made a small txt file in the same directory as the code to replicate your conditions. Here's what you need to modify:
filename = "ExplicitFileName.txt"
attachment = open("/USE/COMPLETE/PATH/TO/FILE/ExplicitFileName.txt", "rb")
Or as Ilja pointed out the DRY principle you could do it like this:
filename = "ExplicitFileName.txt"
attachment = open("/COMPLETE/PATH/TO/FILE/" + filename, "rb")
Both of these will work just fine.

Python how do i send multiple files in the email. I can send 1 file but how to send more than 1

I have the following code to send a html file SeleniumTestReport_part1.html in an email in Python.
I want to send more than 1 file in the email. How do can i do this?
The files I want to send are:
SeleniumTestReport_part1.html
SeleniumTestReport_part2.html
SeleniumTestReport_part3.html
My code to send 1 file is:
def send_selenium_report():
fileToSend = r"G:\test_runners\selenium_regression_test_5_1_1\TestReport\SeleniumTestReport_part1.html"
with open(fileToSend, "rt") as f:
text = f.read()
msg = MIMEText(text, "html")
msg['Subject'] = "Selenium ClearCore_Regression_Test_Report_Result"
msg['to'] = "4_server_dev#company.com"
msg['From'] = "system#company.com"
s = smtplib.SMTP()
s.connect(host=SMTP_SERVER)
s.sendmail(msg['From'], msg['To'], msg.as_string())
s.close()
Thanks,
Riaz
If you want to attach files to the email you can use just iterate over files and attach them to the message. You also may want to add some text to the body.
Here is the code:
import smtplib
import os
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
def send_selenium_report():
dir_path = "G:/test_runners/selenium_regression_test_5_1_1/TestReport"
files = ["SeleniumTestReport_part1.html", "SeleniumTestReport_part2.html", "SeleniumTestReport_part3.html"]
msg = MIMEMultipart()
msg['To'] = "4_server_dev#company.com"
msg['From'] = "system#company.com"
msg['Subject'] = "Selenium ClearCore_Regression_Test_Report_Result"
body = MIMEText('Test results attached.', 'html', 'utf-8')
msg.attach(body) # add message body (text or html)
for f in files: # add files to the message
file_path = os.path.join(dir_path, f)
attachment = MIMEApplication(open(file_path, "rb").read(), _subtype="txt")
attachment.add_header('Content-Disposition','attachment', filename=f)
msg.attach(attachment)
s = smtplib.SMTP()
s.connect(host=SMTP_SERVER)
s.sendmail(msg['From'], msg['To'], msg.as_string())
print 'done!'
s.close()
I have implemented this for sending mail from gmail.
import smtplib
from email.mime.text import MIMEText
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email import Encoders
def send_mail_gmail(username,password,toaddrs_list,msg_text,fromaddr=None,subject="Test mail",attachment_path_list=None):
s = smtplib.SMTP('smtp.gmail.com:587')
s.starttls()
s.login(username, password)
#s.set_debuglevel(1)
msg = MIMEMultipart()
sender = fromaddr
recipients = toaddrs_list
msg['Subject'] = subject
if fromaddr is not None:
msg['From'] = sender
msg['To'] = ", ".join(recipients)
if attachment_path_list is not None:
for each_file_path in attachment_path_list:
try:
file_name=each_file_path.split("/")[-1]
part = MIMEBase('application', "octet-stream")
part.set_payload(open(each_file_path, "rb").read())
Encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment' ,filename=file_name)
msg.attach(part)
except:
print "could not attache file"
msg.attach(MIMEText(msg_text,'html'))
s.sendmail(sender, recipients, msg.as_string())
You can pass multiple address as element of toaddrs_list to whom you want to send mail and multiple attachments files names with their path in attachment_path_list.

add excel file attachment when sending python email

How do i add a document attachment when sending an email with python ?
i get the email to send
(please ignore: i am looping the email to send every 5 seconds, only for testing purposes, i want it to send every 30 min, just have to change 5 to 1800)
here is my code so far. how do i attach a document from my computer?
#!/usr/bin/python
import time
import smtplib
while True:
TO = 'xxxx#gmail.com'
SUBJECT = 'Python Email'
TEXT = 'Here is the message'
gmail_sender = 'xxxx#gmail.com'
gmail_passwd = 'xxxx'
server = smtplib.SMTP('smtp.gmail.com',587)
server.ehlo()
server.starttls()
server.ehlo()
server.login(gmail_sender, gmail_passwd)
BODY = '\n'.join([
'To: %s' % TO,
'From: %s' % gmail_sender,
'Subject:%s' % SUBJECT,
'',
TEXT
])
try:
server.sendmail(gmail_sender,[TO], BODY)
print 'email sent'
except:
print 'error sending mail'
time.sleep(5)
server.quit()
This is the code that worked for me- to send an email with an attachment in python
#!/usr/bin/python
import smtplib,ssl
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email.utils import formatdate
from email import encoders
def send_mail(send_from,send_to,subject,text,files,server,port,username='',password='',isTls=True):
msg = MIMEMultipart()
msg['From'] = send_from
msg['To'] = send_to
msg['Date'] = formatdate(localtime = True)
msg['Subject'] = subject
msg.attach(MIMEText(text))
part = MIMEBase('application', "octet-stream")
part.set_payload(open("WorkBook3.xlsx", "rb").read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="WorkBook3.xlsx"')
msg.attach(part)
#context = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
#SSL connection only working on Python 3+
smtp = smtplib.SMTP(server, port)
if isTls:
smtp.starttls()
smtp.login(username,password)
smtp.sendmail(send_from, send_to, msg.as_string())
smtp.quit()
I found an easy way to do it using what Corey Shafer explains in this video on sending emails with python.
import smtplib
from email.message import EmailMessage
SENDER_EMAIL = "sender_email#gmail.com"
APP_PASSWORD = "xxxxxxx"
def send_mail_with_excel(recipient_email, subject, content, excel_file):
msg = EmailMessage()
msg['Subject'] = subject
msg['From'] = SENDER_EMAIL
msg['To'] = recipient_email
msg.set_content(content)
with open(excel_file, 'rb') as f:
file_data = f.read()
msg.add_attachment(file_data, maintype="application", subtype="xlsx", filename=excel_file)
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:
smtp.login(SENDER_EMAIL, APP_PASSWORD)
smtp.send_message(msg)
Here is just a slight tweak on SoccerPlayer's post above that got me 99% of the way there. I found a snippet Here that got me the rest of the way. No credit is due to me. Just posting in case it helps the next person.
file = 'File.xlsx'
username=''
password=''
send_from = ''
send_to = 'recipient1 , recipient2'
Cc = 'recipient'
msg = MIMEMultipart()
msg['From'] = send_from
msg['To'] = send_to
msg['Cc'] = Cc
msg['Date'] = formatdate(localtime = True)
msg['Subject'] = ''
server = smtplib.SMTP('smtp.gmail.com')
port = '587'
fp = open(file, 'rb')
part = MIMEBase('application','vnd.ms-excel')
part.set_payload(fp.read())
fp.close()
encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment', filename='Name File Here')
msg.attach(part)
smtp = smtplib.SMTP('smtp.gmail.com')
smtp.ehlo()
smtp.starttls()
smtp.login(username,password)
smtp.sendmail(send_from, send_to.split(',') + msg['Cc'].split(','), msg.as_string())
smtp.quit()
Using python 3, you can use MIMEApplication:
import os, smtplib, traceback
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
def sendMail(sender,
subject,
recipient,
username,
password,
message=None,
xlsx_files=None):
msg = MIMEMultipart()
msg["Subject"] = subject
msg["From"] = sender
if type(recipient) == list:
msg["To"] = ", ".join(recipient)
else:
msg["To"] = recipient
message_text = MIMEText(message, 'html')
msg.attach(message_text)
if xlsx_files:
for f in xlsx_files:
attachment = open(f, 'rb')
file_name = os.path.basename(f)
part = MIMEApplication(attachment.read(), _subtype='xlsx')
part.add_header('Content-Disposition', 'attachment', filename=file_name)
msg.attach(part)
try:
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
server.ehlo()
server.login(username, password)
server.sendmail(sender, recipient, msg.as_string())
server.close()
except Exception as e:
error = traceback.format_exc()
print(error)
print(e)
Note* I simply used print(error) in this example. Typically, I send errors to logging.critical(error)
To send an attachment create a MIMEMultipart object and add the attachment to that. Here is an example from the python email examples.
# Import smtplib for the actual sending function
import smtplib
# Here are the email package modules we'll need
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
COMMASPACE = ', '
# Create the container (outer) email message.
msg = MIMEMultipart()
msg['Subject'] = 'Our family reunion'
# me == the sender's email address
# family = the list of all recipients' email addresses
msg['From'] = me
msg['To'] = COMMASPACE.join(family)
msg.preamble = 'Our family reunion'
# Assume we know that the image files are all in PNG format
for file in pngfiles:
# Open the files in binary mode. Let the MIMEImage class automatically
# guess the specific image type.
fp = open(file, 'rb')
img = MIMEImage(fp.read())
fp.close()
msg.attach(img)
# Send the email via our own SMTP server.
s = smtplib.SMTP('localhost')
s.sendmail(me, family, msg.as_string())
s.quit()
You can also accomplish this with Red Mail nicely:
from redmail import EmailSender
from pathlib import Path
import pandas as pd
gmail = EmailSender(
host='smtp.gmail.com',
port=465,
user_name="you#gmail.com",
password="<YOUR PASSWORD>"
)
gmail.send(
subject="Python Email",
receivers=["you#gmail.com"],
text="Here is the message",
attachments={
# From path on disk
"my_file.xlsx": Path("path/to/file.xlsx"),
# Or from Pandas dataframe
"my_frame.xlsx": pd.DataFrame({"a": [1,2,3]})
}
)
You may also pass bytes if you wish to attach your Excel file that way.
To install Red Mail:
pip install redmail
Red Mail is an open source email library full of features. It is well tested and well documented. Documentation is found here: https://red-mail.readthedocs.io/en/latest/

Attach a txt file in Python smtplib

I am sending a plain text email as follows:
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
def send_message():
msg = MIMEMultipart('alternative')
s = smtplib.SMTP('smtp.sendgrid.net', 587)
s.login(USERNAME, PASSWORD)
toEmail, fromEmail = to#email.com, from#email.com
msg['Subject'] = 'subject'
msg['From'] = fromEmail
body = 'This is the message'
content = MIMEText(body, 'plain')
msg.attach(content)
s.sendmail(fromEmail, toEmail, msg.as_string())
In addition to this message, I would like to attach a txt file, 'log_file.txt'. How would I attach a txt file here?
The same way, using msg.attach:
from email.mime.text import MIMEText
filename = "text.txt"
f = file(filename)
attachment = MIMEText(f.read())
attachment.add_header('Content-Disposition', 'attachment', filename=filename)
msg.attach(attachment)
Since Python3.6, I would recommend start using EmailMessage instead of MimeMultipart. Fewer imports, fewer lines, no need to put the recipients both to the message headers and to the SMTP sender function parameter.
import smtplib
from email.message import EmailMessage
msg = EmailMessage()
msg["From"] = FROM_EMAIL
msg["Subject"] = "Subject"
msg["To"] = TO_EMAIL
msg.set_content("This is the message body")
msg.add_attachment(open(filename, "r").read(), filename="log_file.txt")
s = smtplib.SMTP('smtp.sendgrid.net', 587)
s.login(USERNAME, PASSWORD)
s.send_message(msg)
Even better is to install library envelope by pip3 install envelope that's aim is to handle many things in a very intuitive manner:
from envelope import Envelope
from pathlib import Path
Envelope()\
.from_(FROM_EMAIL)\
.subject("Subject")\
.to("to")\
.message("message")\
.attach(Path(filename))\
.smtp("smtp.sendgrid.net", 587, USERNAME, PASSWORD)\
.send()
It works for me
sender = 'spider#fromdomain.com'
receivers = 'who'
msg = MIMEMultipart()
msg['Subject'] = 'subject'
msg['From'] = 'spider man'
msg['To'] = 'who#gmail.com'
file='myfile.xls'
msg.attach(MIMEText("Labour"))
attachment = MIMEBase('application', 'octet-stream')
attachment.set_payload(open(file, 'rb').read())
encoders.encode_base64(attachment)
attachment.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(file))
msg.attach(attachment)
print('Send email.')
conn.sendmail(sender, receivers, msg.as_string())
conn.close()

Categories