I have a question about sending an email with ZIP attachments in Python. Here is how I am doing it:
def send_mail(send_from, send_to, subject, text, files=[], server="localhost"):
assert type(send_to)==list
assert type(files)==list
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:
remotezip = urllib2.urlopen(f)
#zipinmemory = io.BytesIO(remotezip.read())
#zip = zipfile.ZipFile(zipinmemory)
part = MIMEBase('application', 'octet-stream')
part.set_payload( remotezip.read())
Encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
msg.attach(part)
smtp = smtplib.SMTP('smtp.gmail.com:587')
smtp.starttls()
smtp.login('username','password')
smtp.sendmail(send_from, send_to, msg.as_string())
smtp.close()
As I have my ZIP file hosted on my web server, I am reading it using URLOpen.
This code successfully sends an email with the attachment. But the ZIP file is always 0KB. Am sure there is some issue in reading the file.
Please let me know. Thanks for your help!
Related
I want to send a .txt file attached to the mail in Python.
Currently the mail is received but without any attachment.
Code bellow
I've sent emails in PHP but Python is completely new to me
The code doesn't return any errors, it simply doesn't send the attachment with the email
with smtplib.SMTP('smtp.gmail.com', 587) as smtp:
server = smtplib.SMTP('smtp.gmail.com', 587)
smtp.ehlo()
smtp.starttls()
smtp.ehlo()
msg = MIMEMultipart()
smtp.login(EMAIL_ADRESS, EMAIL_PASSWORD)
subject = 'Log Register'
filename = 'logs-to-h4wtsh0wt.txt'
attachment = open(filename, 'rb')
part = MIMEBase('application', 'octet-stream')
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', "attachment; filename= "+filename)
msg.attach(part)
msg = f'Subject: {subject}\n\n{Body}'
smtp.sendmail(EMAIL_ADRESS,EMAIL_ADRESS, msg)
snakecharmerb is right. You are indeed overriding the message object and therefore losing everything you add before that point.
You can instead set the subject like this:
msg['Subject'] = "Subject of the Mail"
# string to store the body of the mail
body = "Body_of_the_mail"
# attach the body with the msg instance
msg.attach(MIMEText(body, 'plain'))
Because you are attaching a file you will also need to convert the multipart message into a string before sending:
text = msg.as_string()
smtp.sendmail(fromaddr, toaddr, text)
When you created msg with MIMEMultipart() it generated the message object structure for you as per RFC2822 which also gives you FROM, TO, etc.
The msg object also has a bunch of functions you can run outlined in its docs
I think the problem is in parameter server=... what should I put here?
import smtplib
import 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=r'\\myserver\User\name\PythonProject\'):
assert type(send_to)==['sendto#.com']
assert type(files)==['File Name.xlsx']
msg = MIMEMultipart()
msg['From'] = "sendfrom#.com"
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(files,"rb").read() )
encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
msg.attach(part)
smtp = smtplib.SMTP('1.1.1.1: 25')
smtp.sendmail(send_from, send_to, msg.as_string())
smtp.close()
This code has number of problems.
The default value of server in the function signature
the string ends with \', which escapes the closing quote: remove it or escape it (the "r" prefix escapes the backslashes inside the string, but the terminal backslash is interpreted as escaping the closing quote and so outside the string)
server is not used in the function
Using a mutable default value like files=[] is usually a bad idea; better to use files=None and check the value in your code before trying to iterate over it
the assert statements don't work.
use isinstance rather than type to check object types
part.set_payload( open(files,"rb").read() ) is trying to open the list of files, it only needs to open the current file in the loop: open(f, ...)
Here is a "fixed" version of the code
def send_mail(
send_from,
send_to,
subject,
text,
files=None,
server=r"\\myserver\User\name\PythonProject\\",
):
assert isinstance(send_to, list)
assert isinstance(files, list)
msg = MIMEMultipart()
msg["From"] = "sendfrom#.com"
msg["To"] = COMMASPACE.join(send_to)
msg["Date"] = formatdate(localtime=True)
msg["Subject"] = subject
msg.attach(MIMEText(text))
if files is not None:
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="%s"' % os.path.basename(f)
)
msg.attach(part)
smtp = smtplib.SMTP('1.1.1.1:25')
smtp.sendmail(send_from, send_to, msg.as_string())
smtp.close()
I made a program to send email with attachment.
While the program is loading the files to be attached, the gui stops responding and Windows changes the window status to 'not responding', but when it has finished loading the files everything is back working. I wonder if there is a way to prevent Windows from changing the state, thanks in advance.
Code:
def send_mail(self, send_to, files=[]):
msg = MIMEMultipart()
msg['From'] = self.programData['name']
msg['To'] = ''
msg['Date'] = formatdate(localtime = True)
msg['Subject'] = self.programData['name']
txt = self.programData['emailText']
text = txt
msg.attach(MIMEText(text))
for path in files:
part = MIMEBase('application', "octet-stream")
with open(path, 'rb') as file:
part.set_payload(file.read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="{0}"'.format(os.path.basename(path)))
msg.attach(part)
smtp = smtplib.SMTP('smtp.gmail.com', 587)
smtp.starttls()
smtp.login('user','passw')
smtp.sendmail('sender', send_to, msg.as_string())
smtp.quit()
I am sending multiple recipients mail with a python script, and it works, but in the "To" in the mail, the field is empty. On every mail provider I tried.
Here is my code :
def send_mail(self, server, send_from, subject, attach, foo=None, bar=None)
msg = MIMEMultipart()
msg['From'] = send_from
msg['Subject'] = subject
body = u"""<html> My Body </html>"""
#Attach file pdf
msg.attach(MIMEText(body, 'html', 'utf-8'))
filename = 'fname.pdf'
attachment = open(attach, "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()
if foo != None and bar != None:
recipients = ["a#b.fr", "b#b.fr"]
msg['To'] = ", ".join(recipients)
server.sendmail(send_from, recipients, text)
else:
msg['To'] = "c#b.fr"
server.sendmail(send_from, msg['To'], text)
sleep(1)
msg['To'] should be the "To" in my mail but it stays empty. (Even in the "else" with only one recipient). I can't find any help about it on existing question, so I come to ask for your help about that.
As per the documentation, the second parameter is a LIST of recipients. You need to change your line
server.sendmail(send_from, msg['To'], text)
to
server.sendmail(send_from, [msg['To']], text)
Finally found out:
text = msg.as_string() should be done after the assignement to msg['To'] So it will appear in my if and else block juste before the server.sendmail(send_from, msg['To'], text) since all information written in the mail, even 'To', and 'From' are in the third argument text .
I am trying to send an email with an attachment from my Python script.
To send the text in the body seems ok but I am not sure about the syntax for the file attachment.
My code snippet is:
import smtplib
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
def send_email(self):
fromaddress = "rladhani#gmail.com"
toaddress = "riaz.ladhani#company.com"
text = "subject line test"
username = "rladhani#gmail.com"
password = "-"
msg = MIMEMultipart()
msg['from'] =fromaddress
msg['to'] = toaddress
msg['subject'] = text
msg.attach(MIMEText (text))
attachment = open(r"C:\Webdriver\ClearCoreRegression Test\TestReport\TestReport_01052016.html", "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.ehlo()
server.starttls()
server.ehlo()
server.login(username, password)
server.sendmail(fromaddress, toaddress, msg.as_string())
server.quit()
How can I add the file attachment to the email?
Also I am getting an unresolved reference error on
encoders.encode_base64(part)
Thanks, Riaz
Looks like this one has been asked a few times.
How to send email attachments with Python
How do I send an email with a .csv attachment using Python
Sending Email attachment (.txt file) using Python 2.7 (smtplib)
Hope these help!