I have this script that sends emails with multiple attachments to multiple users. However, the attachments' file names are set as their path.
Received files
Terminal Output
How can I set their names as the actual file names, thanks.
"""
import os
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
from email.MIMEImage import MIMEImage
from email.MIMEBase import MIMEBase
from email import Encoders
#Set up crap for the attachments
files = "/tmp/test/dbfiles"
filenames = [os.path.join(files, f) for f in os.listdir(files)]
#print filenames
#Set up users for email
gmail_user = "joe#email.com"
gmail_pwd = "somepasswd"
recipients = ['recipient1','recipient2']
#Create Module
def mail(to, subject, text, attach):
msg = MIMEMultipart()
msg['From'] = gmail_user
msg['To'] = ", ".join(recipients)
msg['Subject'] = subject
msg.attach(MIMEText(text))
#get all the attachments
for file in filenames:
part = MIMEBase('application', 'octet-stream')
part.set_payload(open(file, 'rb').read())
Encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="%s"' % file)
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()
#send it
mail(recipients,
"Todays report",
"Test email",
filenames)
"""
there might be a solution in this link:
Python email MIME attachment filename
Basically what the solution is according to that post is change your this line:
part.add_header('Content-Disposition', 'attachment; filename="%s"' % file)
to this line :
part.add_header('Content-Disposition', 'attachment', filename=AFileName)
Which comes down to this final change:
#get all the attachments
for file in filenames:
part = MIMEBase('application', 'octet-stream')
part.set_payload(open(file, 'rb').read())
Encoders.encode_base64(part)
***part.add_header('Content-Disposition', 'attachment', filename=file)***
msg.attach(part)
Documentation on how to use add_header
Hope that helps! :D
Update
Having this in your for loop should give you the filenames:
for file in filenames:
actual_filenames = os.path.basename(file)
#Your code
part.add_header('Content-Disposition', 'attachment', filename=actual_filenames)
if it is in the same directory:
import os
for f in os.listdir('.'):
fn, fext = os.path.splitext(f)
Related
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 create emails using an HTML template, and I attach an image to each email. Before sending my emails out I would like to first save them on a disk for a review and then have a separate script to send the saved emails out. Currently, I generate and send emails the following way.
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.MIMEImage import MIMEImage
from email.MIMEBase import MIMEBase
from email import Encoders
fileLocation = 'C:\MyDocuments\myImage.png'
attachedFile = "'attachment; filename=" + fileLocation
text = myhtmltemplate.format(**locals())
msg = MIMEMultipart('related')
msg['Subject'] = "My subject"
msg['From'] = 'sender#email.com'
msg['To'] = 'receiver#email.com'
msg.preamble = 'This is a multi-part message in MIME format.'
msgAlternative = MIMEMultipart('alternative')
msg.attach(msgAlternative)
part = MIMEBase('application', "octet-stream")
part.set_payload(open(fileLocation, "rb").read())
Encoders.encode_base64(part)
part.add_header('Content-Disposition', attachedFile)
msg.attach(part)
msgText = MIMEText('This is the alternative plain text message.')
msgAlternative.attach(msgText)
msgText = MIMEText(text, 'html')
msgAlternative.attach(msgText)
fp = open(fileLocation, 'rb')
msgImage = MIMEImage(fp.read())
fp.close()
# Define the image's ID
msgImage.add_header('Content-ID', '<image1>')
msg.attach(msgImage)
smtpObj = smtplib.SMTP('my.smtp.net')
smtpObj.sendmail(sender, receiver, msg.as_string())
smtpObj.quit()
How can I save exactly the same emails to a disk instead of sending them right away?
Just open a file and store the raw text. If the reviewer accepts it, just forward the text.
Instead of:
smtpObj = smtplib.SMTP('my.smtp.net')
smtpObj.sendmail(sender, receiver, msg.as_string())
smtpObj.quit()
Makes it save:
f = open("output_file.txt", "w+")
f.write(msg.as_string())
f.close()
Later on, whenever the reviewer accepts the text:
# Read the file content
f = open("output_file.txt", "r")
email_content = f.read()
f.close()
# Send the e-mail
smtpObj = smtplib.SMTP('my.smtp.net')
smtpObj.sendmail(sender, receiver, email_content )
smtpObj.quit()
I am trying to send mail using python script. I tried without attachment it is working.
Now i tried with attachment i am getting assertion error.
Below is the code:
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import COMMASPACE, formatdate
from email import Encoders
import os
import time
import random
msg_from = "xyz#abc.com"
to = "xyz#abc.com"
text = "test-Hello"
subject = "Test"
f = "output1.pdf"
def generate_message_id(msg_from):
domain = msg_from.split("#")[1]
r = "%s.%s" % (time.time(), random.randint(0, 100))
mid = "<%s#%s>" % (r, domain)
return mid
def send_mail(msg_from, to, subject, text,
files=[],server="10.10.10.10", debug=False):
assert type(to)==list
assert type(files)==list
msg = MIMEMultipart()
msg['From'] = msg_from
msg['To'] = COMMASPACE.join(to)
msg['Date'] = formatdate(localtime=True)
msg['Subject'] = subject
text = text.encode("utf-8")
text = MIMEText(text, 'plain', "utf-8")
msg.attach(text)
msg.add_header('Message-ID', generate_message_id(msg_from))
for file 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"'
for file 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(file))
msg.attach(part)
if not debug:
smtp = smtplib.SMTP(server)
smtp.sendmail(msg_from, to, msg.as_string())
smtp.close()
return msg
send_mail(msg_from, to, subject, text,files=[],server="10.10.10.10", debug=False)
Error i am getting:
Traceback (most recent call last):
File "testmail1.py", line 53, in <module>
send_mail(msg_from, to, subject, text,files=[],server="10.10.10.10", debug=False)
File "testmail1.py", line 24, in send_mail
assert type(to)==list
AssertionError
I am using from linux os and using python 2.7
Please help me to fix
Your to field should be a list, because you could theoretically send your email to multiple persons. So I'd suggest:
to = ["xyz#abc.com"]
The send_mail method checks first if your to field is a list, that's why you're getting the error.
Also check out the documentation
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!
I have got some code to attach files from an email using MIME module
however each time I send the email I want it to automatically send
only the first 5 most recent pictures in the file.
import os, re
import sys
import smtplib
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
SMTP_SERVER = 'smtp.gmail.com'
SMTP_PORT = 587
sender = '***#gmail.com'
password = "*******"
recipient = '***#gmail.com'
subject = 'Python emaillib Test'
message = 'Images attached.'
directory = "images/"
def main():
msg = MIMEMultipart()
msg['Subject'] = 'Python emaillib Test'
msg['To'] = recipient
msg['From'] = sender
#this is where it searches for the image
files = os.listdir(directory)
jpgsearch = re.compile(".jpg", re.IGNORECASE)
files = filter(jpgsearch.search, files)
for filename in files:
path = os.path.join(directory, filename)
if not os.path.isfile(path):
continue
img = MIMEImage(open(path, 'rb').read(), _subtype="jpg")
img.add_header('Content-Disposition', 'attachment', filename = filename)
msg.attach(img)
part = MIMEText('text', "plain")
part.set_payload(message)
msg.attach(part)
session = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
session.ehlo()
session.starttls()
session.ehlo
session.login(sender, password)
session.sendmail(sender, recipient, msg.as_string())
session.quit()
if __name__ == '__main__':
main()
I am a beginner to Python so help would be appreciated
Use os.stat to fetch atime, ctime or mtime. Then simple compare timestamps (or use some other logic based on datetime.datetime.fromtimestamp)