Problem with For to attach multiples pdfs Email Server Google Colab - python

I'm trying to create an email server to send multiple attached pdfs, I have the code below, it works good sending just one file. But with the for-loop it only sends the last document from 3, help please here maybe I didn't made the for correctly. It uses a csv file with the emails from contacts you can find that file here.
I'll put the for part after the full code...
import email, csv, smtplib, ssl
from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
subject = "An email with attachment from Python"
body = """Hi {name_lastname},
How are you?
"This is an email with attachment sent from Python"
Your mail is to Login in the platform is {mail} and your Access Code is {epassword}
Real Python has many great tutorials:
www.realpython.com"""
sender_email = input('enter sender mail address:') # Enter your address
password = input("Type your password and press enter:")
# Create a multipart message and set headers
message = MIMEMultipart()
message["From"] = sender_email
message["Subject"] = subject
#message["Bcc"] = receiver_email # Recommended for mass emails
# Add body to email
message.attach(MIMEText(body, "plain"))
filenames = ["document.pdf", "document2", "document3.pdf"] # In same directory as script
#HERE START THE FOR
# Open PDF file in binary mode
for f in filenames or []:
with open(f, "rb") as attachment:
# Add file as application/octet-stream
# Email client can usually download this automatically as attachment
part = MIMEBase("application", "octet-stream")
part.set_payload(attachment.read())
# Encode file in ASCII characters to send by email
encoders.encode_base64(part)
# Add header as key/value pair to attachment part
part.add_header(
"Content-Disposition",
f"attachment; filename= {f}",
)
#HERE ENDS THE FOR
# Add attachment to message and convert message to string
message.attach(part)
text = message.as_string()
# Log in to server using secure context and send email
context = ssl.create_default_context()
with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
server.login(sender_email, password)
with open("contacts.csv") as file:
reader = csv.reader(file)
next(reader) # Skip header row
for name_lastname, mail ,epassword in reader:
server.sendmail(
sender_email,
mail,
text.format(name_lastname=name_lastname, mail=mail, epassword=epassword),
)
Here is the for:
#HERE START THE FOR
# Open PDF file in binary mode
for f in filenames or []:
with open(f, "rb") as attachment:
# Add file as application/octet-stream
# Email client can usually download this automatically as attachment
part = MIMEBase("application", "octet-stream")
part.set_payload(attachment.read())
# Encode file in ASCII characters to send by email
encoders.encode_base64(part)
# Add header as key/value pair to attachment part
part.add_header(
"Content-Disposition",
f"attachment; filename= {f}",
)
#HERE ENDS THE FOR

Related

Send multiple emails with different attachments each

I have a list of text files and html files generated by two distinct functions. Each file is labeled signal1.txt, signal2, etc. and signal1.html, signal2.html, etc. I need to send an email with each file pair (signal1.txt and signal1.html, signal2.txt and signal.2.html, and so forth). I've tried several different ways, but I keep getting just one file pair attached (the last file number whatever it is). I have no problem sending one file type, but it gets messy when I try with two different files.
Any help is appreciated. The code is as follows.
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email import encoders
import smtplib, ssl
import os
dirname = r'C:\Path\To\Files'
ext = ('.txt','html')
for files in os.scandir(dirname):
if files.path.endswith(ext):
def sendmail():
html_body = '''
<html>
<body>
<p style="font-size: 12;"> <strong>Alert</strong><br>{html}</p>
</body>
</html>
'''.format(html=html)
subject = f'Text file content'
senders_email = 'mail#mail.com'
receiver_email = 'mail#mail.com'
# Create a multipart message and set headers
message = MIMEMultipart('alternative')
message['From'] = senders_email
message['To'] = receiver_email
message['Subject'] = subject
#Attach email body
message.attach(MIMEText(html_body, 'html'))
# Name of the file to be attached
filename = f'signal.html'
# Open file in binary mode
with open(filename, 'rb') as attachment:
# Add file as application/octet-stream
part = MIMEBase('application', 'octet-stream')
part.set_payload(attachment.read())
# Encodes file in ASCII characters to send via email
encoders.encode_base64(part)
# Add header as key/value pair to attachment part
part.add_header(
'Content-Disposition',
f"attachment; filename= {filename}",
)
# Add attachment to message and convert message to string
message.attach(part)
text = message.as_string()
# Log into server using secure connection
context = ssl.create_default_context()
with smtplib.SMTP("smtp.mail.com", 25) as server:
# server.starttls(context=context)
# server.login(senders_email, 'password')
server.sendmail(senders_email, receiver_email, text)
print("Email sent!")
sendmail()
I've adapted one of these examples for your problem. This puts all the files in one email:
# Import smtplib for the actual sending function.
import smtplib
# Here are the email package modules we'll need.
from email.message import EmailMessage
import os
dirname = 'C:\Path\To\Files'
ext = ('.txt','html')
msg = EmailMessage()
msg['Subject'] = 'Text file content'
msg['From'] = 'mail#mail.com'
msg['To'] = 'mail#mail.com'
# Open the files in binary mode. You can also omit the subtype
# if you want MIMEImage to guess it.
for filename in os.scandir(dirname):
if filename.path.endswith(ext):
with open(filename, 'rb') as fp:
data = fp.read()
msg.add_attachment(data)
# Send the email via our own SMTP server.
with smtplib.SMTP('localhost') as s:
s.send_message(msg)
Found a way that worked using glob.
dirname = r'C:\Path\To\Files'
regex = create_txt_files(event_dict)
html_file = create_html_files(event_dict)
signalfiles = sorted(list(pathlib.Path(dirname).glob('*.txt')))
htmlfiles = sorted(list(pathlib.Path(dirname).glob('*.html')))
for i, path_html_file in enumerate(htmlfiles):
sendmail(html_file[i], regex[i], path_html_file)

smtplib email file attachment is being defaulted to 'noname'

I am trying to automate some email sending with python and the smtplib library. Currently, it sends the email fine and attaches the file, but the file does not keep the name that I set.
#The body and the attachments for the mail
message.attach(MIMEText(mail_content, 'plain'))
attach_file_name = 'temp.txt'
attach_file = open(attach_file_name, 'rb') # Open the file as binary mode
payload = MIMEBase('application', 'octate-stream')
payload.set_payload((attach_file).read())
encoders.encode_base64(payload) #encode the attachment
#add payload header with filename
payload.add_header('Content-Decomposition', 'attachment', filename=attach_file_name)
message.attach(payload)
#Create SMTP session for sending the mail
session = smtplib.SMTP('-----', 587) #custom domain
session.starttls() #enable security
session.login(sender_address, sender_pass) #login with mail_id and password
text = message.as_string()
session.sendmail(sender_address, receiver_address, text)
session.quit()
print('Mail Sent')
The above code should set the attachment file name to "temp.txt" I believe, but it defaults to "noname" in the inbox that it is sent to.
I found a solution using MIMEApplication - it correctly names the attachment.
attach_file_name = 'Test.pdf'
attach_file=MIMEApplication(open(attach_file_name,"rb").read())
attach_file.add_header('Content-Disposition', 'attachment', filename=attach_file_name)
message.attach(attach_file)

Send email with plain text and html attachment

I'm trying to send email that contain both plain text in the body and html attachment. I've succeeded in adding the attachment but can't figure out how to add the plain text to the body. Any help is appreciated.
Here is the code:
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
import smtplib, ssl
from email import encoders
def sendmail():
subject = 'Subject here'
body = "Shard Count: 248" #Need to add this to body in plain text
senders_email = 'title#domain.com'
receiver_email = 'security#domain.com'
#Create a multipart message and set headers
message = MIMEMultipart('alternative')
message['From'] = senders_email
message['To'] = receiver_email
message['Subject'] = subject
message.attach(MIMEText(html_file, 'html'))
filename = 'logs.html'
# Open file in binary mode
with open(filename, 'rb') as attachment:
# Add file as application/octet-stream
part = MIMEBase('application','octet-stream')
part.set_payload(attachment.read())
# Encodes file in ASCII characters to send via email
encoders.encode_base64(part)
# Add header as key/value pair to attachment part
part.add_header(
'Content-Disposition',
f"attachment; filename= {filename}",
)
# Add attachment to message and convert message to string
message.attach(part)
text = message.as_string()
# Log into server using secure connection
context = ssl.create_default_context()
with smtplib.SMTP("smtp.domain.com", 25) as server:
# server.starttls(context=context)
# server.login(senders_email, password)
server.sendmail(senders_email,receiver_email,text)
print("Email sent!")
sendmail()
Your program looks fine for sending email with html body and an attachment. For sending plain text body, you will need to make a minor modification. I have tested your code with html body and plain text body. I am attaching both the versions of the code below.
The code with html body and an attachment is given below. I have tested this code at my end.
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
import smtplib, ssl
from email import encoders
html_body = '''
<html>
<body>
<h1>Sample email header</h1>
<p>Sample body</p>
</body>
</html>
'''
def sendmail():
subject = 'Subject here'
body = "Shard Count: 248" # Need to add this to body in plain text
senders_email = 'amal#example.com'
receiver_email = 'amalgjose#example.com'
# Create a multipart message and set headers
message = MIMEMultipart('alternative')
message['From'] = senders_email
message['To'] = receiver_email
message['Subject'] = subject
# The message body gets set here. Here we can add html body or text body.
# Syntax - message.attach(MIMEText(content, 'content-type'))
message.attach(MIMEText(html_body, 'html'))
# Name of the file to be attached
filename = 'attachment.pdf'
# Open file in binary mode
with open(filename, 'rb') as attachment:
# Add file as application/octet-stream
part = MIMEBase('application', 'octet-stream')
part.set_payload(attachment.read())
# Encodes file in ASCII characters to send via email
encoders.encode_base64(part)
# Add header as key/value pair to attachment part
part.add_header(
'Content-Disposition',
f"attachment; filename= {filename}",
)
# Add attachment to message and convert message to string
message.attach(part)
text = message.as_string()
# Log into server using secure connection
context = ssl.create_default_context()
with smtplib.SMTP("smtp.examplemail.com", 25) as server:
server.starttls(context=context)
server.login(senders_email, 'password')
server.sendmail(senders_email, receiver_email, text)
print("Email sent!")
sendmail()
If you want to send an email with plain text and an attachment, you just need a very minor change in the code. Make the following modification in the code.
text_body = "Hello, this is my text data in email"
message.attach(MIMEText(text_body))
The updated code which sends emails with plain text body and attachment is given below.
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
import smtplib, ssl
from email import encoders
text_body = '''
Hello, this is the sample text body. This program sends email with text body and an attachment.
I hope this helps
'''
def sendmail():
subject = 'Subject here'
body = "Shard Count: 248" # Need to add this to body in plain text
senders_email = 'amal#example.com'
receiver_email = 'amalgjose#example.com'
# Create a multipart message and set headers
message = MIMEMultipart('alternative')
message['From'] = senders_email
message['To'] = receiver_email
message['Subject'] = subject
# The message body gets set here. Here we can add html body or text body.
# Syntax - message.attach(MIMEText(content, 'content-type'))
message.attach(MIMEText(text_body))
# Name of the file to be attached
filename = 'attachment.pdf'
# Open file in binary mode
with open(filename, 'rb') as attachment:
# Add file as application/octet-stream
part = MIMEBase('application', 'octet-stream')
part.set_payload(attachment.read())
# Encodes file in ASCII characters to send via email
encoders.encode_base64(part)
# Add header as key/value pair to attachment part
part.add_header(
'Content-Disposition',
f"attachment; filename= {filename}",
)
# Add attachment to message and convert message to string
message.attach(part)
text = message.as_string()
# Log into server using secure connection
context = ssl.create_default_context()
with smtplib.SMTP("smtp.examplemail.com", 25) as server:
server.starttls(context=context)
server.login(senders_email, 'password')
server.sendmail(senders_email, receiver_email, text)
print("Email sent!")
sendmail()

How to send python code output over email?

I have an output of df['sentiments'] as sentiment output of twitter tweets. I want to mail that sentiment output over email to another person automatically.
Store it in a file using df['sentiments'].to_csv('sentiment.csv'). And send the file sentiment.csv via mail.
More details about to_csv function can be found here in the official docs.
EDIT: Expanding the answer for the sake of making it less troublesome. Credits for this part
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
mail_content = '''Sample message'''
#The mail addresses and password
sender_address = 'sender#gmail.com'
sender_pass = 'xxxxxxxxxxx'
receiver_address = 'receiver#gmail.com'
#Setup the MIME
message = MIMEMultipart()
message['From'] = sender_address
message['To'] = receiver_address
message['Subject'] = 'A test mail sent by Python. It has an attachment.'
#The body and the attachments for the mail
message.attach(MIMEText(mail_content, 'plain'))
filename = "database.txt" #- Attach the sentiment.csv and metadata file here
# Open PDF file in binary mode
with open(filename, "rb") as attachment:
# Add file as application/octet-stream
# Email client can usually download this automatically as attachment
part = MIMEBase("application", "octet-stream")
part.set_payload(attachment.read())
# Encode file in ASCII characters to send by email
encoders.encode_base64(part)
# Add header as key/value pair to attachment part
part.add_header(
"Content-Disposition",
f"attachment; filename= {filename}",
)
# Add attachment to message and convert message to string
message.attach(part)
#Create SMTP session for sending the mail
session = smtplib.SMTP('smtp.gmail.com', 587) #use gmail with port
session.ehlo()
session.starttls() #enable security
session.login(sender_address, sender_pass) #login with mail_id and password
text = message.as_string()
session.sendmail(sender_address, receiver_address, text)
session.quit()
print('Mail Sent')
If you get an error as follows:
(535, b'5.7.8 Username and Password not accepted. Learn more at\n5.7.8 https://support.google.com/mail/?p=BadCredentials y186sm1525057pfy.66 - gsmtp')
Follow this thread
You can use the python built in library smtplib:
https://docs.python.org/3/library/smtplib.html to send emails.
You can use, for example the GMAIL mail server to send it.
https://www.tutorialspoint.com/send-mail-from-your-gmail-account-using-python

Python - email send shows invalid syntax on Raspberry Pi

I have a python program to send emails from gmail account that works on Ubuntu, but not on Raspberry Pi. It shows next error:
f"attachment; filename= {filename}", <=it shows problem on this double quotation.
It looks like that it stops showing error msg when I delete f from the start of that string, but that will crush file for sending and I'm not able to open it after downloading from email.
Is there something that doesn't match Raspberry Pi? Could someone please tell me how to solve this problem? Thanks.
here is the code:
import email, smtplib, ssl
from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
subject = "Detection!"
body = "There was a detection from Pi"
sender_email = "example#gmail.com"
receiver_email = "example2#gmail.com"
password = "example"
# Create a multipart message and set headers
message = MIMEMultipart()
message["From"] = sender_email
message["To"] = receiver_email
message["Subject"] = subject
message["Bcc"] = receiver_email # Recommended for mass emails
# Add body to email
message.attach(MIMEText(body, "plain"))
filename = "image.jpeg" # In same directory as script
# Open PDF file in binary mode
with open(filename, "rb") as attachment:
# Add file as application/octet-stream
# Email client can usually download this automatically as attachment
part = MIMEBase("application", "octet-stream")
part.set_payload(attachment.read())
# Encode file in ASCII characters to send by email
encoders.encode_base64(part)
# Add header as key/value pair to attachment part
part.add_header(
"Content-Disposition",
f"attachment; filename= {filename}", # HERE IS THE INVALID SYNTAX ERROR
)
# Add attachment to message and convert message to string
message.attach(part)
text = message.as_string()
# Log in to server using secure context and send email
context = ssl.create_default_context()
with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
server.login(sender_email, password)
server.sendmail(sender_email, receiver_email, text)
f-strings were new in Python 3.6. Your Pi is presumably using an older version.
You can use the format method instead:
part.add_header(
"Content-Disposition",
"attachment; filename={}".format(filename),
)

Categories

Resources