I am sending mail from a linux box from a directory path which has three csv files. I want to attach all three in my email. Below is the script.
def mailer(sender, to, path):
msg = MIMEMultipart()
msg['Subject'] = 'UMR_EOD_RECONCILLATIONS'
msg['From'] = sender
msg['To'] = to
for file in os.listdir(path):
f = open( path + file, 'rb')
csv = MIMEText(f.read())
f.close()
msg.attach(csv)
mailer = smtplib.SMTP('localhost')
mailer.sendmail(sender,to, msg.as_string())
mailer.quit()
I have been scratching my head for a while and tried multiple times but still facing below issues.
The files which are attached are text files i.e. .txt extension, I want is to be csv
The files have funny names ATT00001.txt and ATT00002.txt which remains the same.
The third file is never attached to the mail it contents are outputted in the body and it's the damn same file however times I may try.
I have tried setting below but to no avail.
msg["Content-Disposition"] = "attachment; filename=" + file + ";"
msg.add_header('Content-Disposition', 'attachment', filename=file)
1) The first text object will be displayed as the email message. So, add an extra text object first.
2) CSV files should be transmitted as content-type: text/csv, not content-type: text/plain.
#UNTESTED
def mailer(sender, to, path):
msg = MIMEMultipart()
msg['Subject'] = 'UMR_EOD_RECONCILLATIONS'
msg['From'] = sender
msg['To'] = to
msg.attach(MIMEText('Here are the reports you asked for.'))
for file in os.listdir(path):
f = open( path + file, 'rb')
csv = MIMEText(f.read(), 'csv')
f.close()
csv.add_header('Content-Disposition', 'attachment', filename=file)
msg.attach(csv)
mailer = smtplib.SMTP('localhost')
mailer.sendmail(sender,to, msg.as_string())
mailer.quit()
I always advise to run from doing MIME stuff when you just want to send emails. I feel like no one wants to deal with that. It feels like Java.
Try yagmail; my apologies, I'm the developer.
Its purpose is to make it super easy to send emails with HTML, inline images and attachments.
The code for what you want:
import os
import yagmail
def mailer(sender, to, path):
yag = yagmail.SMTP(sender, host="localhost", smtp_skip_login=True)
contents = ['Here are the reports you asked for.'] + os.listdir(path)
yag.send(to, 'UMR_EOD_RECONCILLATIONS', contents)
I'd suggest to read the README for more nice tricks in there :)
To get started, use pip install yagmail to install yagmail.
Related
I am struggling with sending email with the attachment of excel file by Python.
The problem I am facing now is python change excel file format to '.aaf' format or other unknown formats.
It happens when python sends excel files to specific email addresses, which I guess are intranet mail address. Other personal email addresses(e.g. gmail) have no trouble, no change in file format. The assuming-intranet mail addresses also receieve pdf file with awkward format as well as excel file.
I am digging out any clue to solve it day and night, but can't find any advice related to it. Any help? Below is my code :
note) attachment = file path + file name
def send_mail(mail_list, cc_list, subject, text, attachment):
msg = EmailMessage()
msg["From"] = MY_ID
msg["To"] = ",".join(mail_list)
msg["Cc"] = ",".join(cc_list)
msg["Subject"] = subject
msg.set_content(text)
if attachment:
filename = Path(attachment).name
with open(filename, "rb") as f:
msg.add_attachment(f.read(), maintype="application", subtype="xlsx", filename=filename)
msg.add_header('Content-Disposition', 'attachment; filename='+filename)
with SMTP_SSL("smtp.gmail.com", 465) as smtp:
smtp.login(MY_ID, MY_PW)
smtp.send_message(msg)
A guy left a comment, which seems removed, and it solved the problem. The solution is :
replace the code I wrote
msg.add_attachment(f.read(), maintype="application", subtype="xlsx", filename=filename)
with one below :
msg.add_attachment(f.read(), maintype="application", subtype="vnd.openxmlformats-officedocument.spreadsheetml.sheet", filename=filename)
The complete script makes a picture with my raspberry pi camera every minute and sends it via email to my adress. The picture is as an attachment in the email but it has no file extension.
1. What do i have to add that the file get the original file extension that they are saved on the raspberry.
Or if its possible:
2. How can I get the pictures embed in the email. This would be much easier so I don`t have to safe them first on my pc.
I hope you all know what I mean, my englich is not the best :)
def sendMail(data):
global texte
mail = MIMEMultipart()
mail['Subject'] = "Pictures from home"
mail['From'] = fromaddr
mail['To'] = toaddr
mail.attach(MIMEText(body, 'plain'))
dat='%s.jpg'%data
attachment = open(dat, 'rb')
image=MIMEImage(attachment.read())
attachment.close()
mail.attach(image)
server = smtplib.SMTP('smtp.web.de', 587)
server.starttls()
server.login(fromaddr, "PASSWORD")
text = mail.as_string()
server.sendmail(fromaddr, toaddr, text)
server.quit()
movepic(data)
To add a filename to the attachment, you need to add the "Content-Disposition" header to that MIME part, i.e. add this to the code:
attachment = open(dat, 'rb')
image=MIMEImage(attachment.read())
attachment.close()
image.add_header('Content-Disposition', 'attachment; filename=filename.extension')
mail.attach(image)
To send the image without saving it to the file, you have to have the image contents and pass them to MIMEImage constructor. You are currently reading them from file in attachment.read().
So, if you can pass the image binary (instead of filename) to the function, like this:
def sendMail(image_binary_data):
then just pass it, like this:
image=MIMEImage(image_binary_data)
image.add_header('Content-Disposition', 'attachment; filename=filename.extension')
mail.attach(image)
BTW, if you are reading the image from file, it's safer to open and read files this way, to be sure it always closes properly:
with open(dat, 'rb') as image_file:
image=MIMEImage(image_file.read())
# no need to close explicitly
I am writing a script that creates multiple plotly interactive charts that are saved in HTML format. I want to write code that sends these HTML files out in an email as an attachment. I can't seem to find any documentation on this, only instructions on how to embed the HTML in an email which is not what I want. I just want to attach the file, just like I was attaching a JPG picture or PDF file.
Code I have so far, which just embeds the HTML:
import lxml.html
import smtplib
import sys
import os
page = 'report.html'
root = lxml.html.parse(page).getroot()
root.make_links_absolute()
content = lxml.html.tostring(root)
message = """From: <me#gmail.com>
To: <you#gmail.com>
MIME-Version: 1.0
Content-type: text/html
Subject: %s
%s""" %(page, content)
s = smtplib.SMTP('localhost')
s.sendmail('me#gmail.com', ['you#gmail.com'], message)
s.quit()
Appreciate the help. I'd hopefully like to find a dynamic way to send files that are in multiple formats, so that I don't have to worry about different functions to send different types of files.
In standard documentation see third example with module email
https://docs.python.org/3.6/library/email.examples.html#email-examples
# Import smtplib for the actual sending function
import smtplib
# And imghdr to find the types of our images
import imghdr
# Here are the email package modules we'll need
from email.message import EmailMessage
# Create the container email message.
msg = EmailMessage()
msg['Subject'] = 'Our family reunion'
# me == the sender's email address
# family = the list of all recipients' email addresses
msg['From'] = me
msg['To'] = ', '.join(family)
msg.preamble = 'Our family reunion'
# Open the files in binary mode. Use imghdr to figure out the
# MIME subtype for each specific image.
for file in pngfiles:
with open(file, 'rb') as fp:
img_data = fp.read()
msg.add_attachment(img_data, maintype='image',
subtype=imghdr.what(None, img_data))
# Send the email via our own SMTP server.
with smtplib.SMTP('localhost') as s:
s.send_message(msg)
EDIT: for other files you can get maintype, subtype
import mimetypes
filename = 'file.html'
ctype, encoding = mimetypes.guess_type(filename)
maintype, subtype = ctype.split("/", 1)
print(maintype, subtype)
# text html
str_htmlHeader = "<!DOCTYPE HTML PUBLIC>\n<html>\n";
str_htmlHeader += "<head>\n\t<title>Audi Cloud Services</title>\n</head>\n\n";
str_htmlHeader += "<body>\n\n<h1>Nightly build test results</h1>\n";
str_htmlFooter = "\n</body>\n\n</html>";
for root, dirnames, filenames in os.walk(r'\\ac-srvfile01\_Embedded\VCon1\proj_customer\337159_Audi_ACR_and_TSSS\pcm-audio'):
for filename in fnmatch.filter(filenames, '*.html'):
reportContent = open(os.path.join(root,filename)).read()
attachment = MIMEText(str_htmlHeader+reportContent+str_htmlFooter, 'html')
msg.attach(attachment)
#msg.attach(MIMEText(open(filename).read(), "text/html"))
I am sending the message to a concerned person but the email is going to the respected person in a different email. I want to collect all the reports and send it as a single email. but the above code is sending the reports as a different email. Can someone help me how to fix that?
You want to create a single container message, then add MIME parts to it in the loop.
The multipart/alternative container is not suitable for this, as it indicates that the client should select one of the parts for display, and ignore the rest. I have used multipart/related instead. You could perhaps prefer multipart/mixed which does not imply a relationship of some sort between the parts.
str_htmlHeader = '''<!DOCTYPE HTML PUBLIC>
<html>
<head><title>Audvices</title></head>
<body><h1>Nightt results</h1>'''
str_htmlFooter = '''"
</body>\n\n</html>'''
msg = MIMEMultipart('related')
msg['From'] = 'ucd_test'
msg['To'] = 'hemappa#nce.com'
msg['Subject'] = 'AUDICES'
for root, dirnames, filenames in os.walk(r'\\ac-srvR_and_TSSS\pcm-audio'):
for filename in fnmatch.filter(filenames, '*.html'):
reportContent = open(os.path.join(root,filename)).read()
attachment = MIMEText(str_htmlHeader+reportContent+str_htmlFooter, 'html')
attachment.add_header("Content-Disposition", "attachment",\
filename=os.path.basename(filename))
msg.attach(attachment)
server = smtplib.SMTP('eu-smtp.nuance.com')
server.ehlo()
#server.starttls()
#server.login(username,password)
server.sendmail(fromaddress,toaddress.split(','),msg.as_string())
server.quit()
I'm trying to attach a PDF file to an email like this:
def send_email(gmail, password, post_description,
reply_email, attachment_path, email_body_path):
msg = MIMEMultipart()
with open(email_body_path) as f:
msg.attach(MIMEText(f.read()))
if attachment_path != None:
with open(attachment_path, 'rb') as f:
msg.attach(MIMEApplication(
f.read(),
Content_Disposition='attachment, filename="%s"' % basename(f)))
smtp = smtplib.SMTP('smtp.gmail.com',587)
smtp.login(gmail, password)
smtp.sendmail(gmail, 'address#gmail.com', msg.as_string()
The PDF is attached and has the correct title, but the contents are always "ECO" and nothing else.
See email examples on how to make attachments correctly:
outer = MIMEMultipart()
<...>
fp = open(path, 'rb')
msg = MIMEAplication(fp.read(), _subtype=subtype) #or another appropriate subclass
#some subclasses have additional parameters
<or>
msg = MIMEBase(maintype, subtype)
msg.set_payload(fp.read())
encoders.encode_base64(msg)
msg.add_header('Content-Disposition', 'attachment', filename=filename)
outer.attach(msg)
To add text to the message, you need to attach a MIMEText as well as the PDF as per multipart/alternative example (do not forget to specify encoding if it's not the RFC-dictated default, iso-8859-1):
part = MIMEText(<text>, _charset='<charset>')
outer.attach(part)
So, you were doing everything correctly except forming the MIMEApplication. MIMEBase.__init__ source code shows that extra parameters on the constructor call all go into the Content-Type header.