Python SMTPLIB Gmail recipient security issues - python

I am trying to send emails with already made Zip attachments and I am running into errors with gmail's security kicking them back. Originally I was using a gmail account to send the email, but I learned that gmail blocks that. So now I am using an outlook email. It sends the emails, which is an improvement, but my recipient emails (gmail) are returning the emails. How do people get around this? Surely there has to be a way to send zip files to gmail addresses. Here is my code:
UPDATE: I opened the returned email I sent - the attached file is a .bin file, not the .zip file. I may be misunderstanding the code and converting the zip file to binary rather than just attaching it.
def send_mail(zips_folder):
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
sender_email = "senderEmail#outlook.com"
receiver_email ="receiverEmail#gmail.com"
message = MIMEMultipart()
message["From"] = sender_email
message['To'] = receiver_email
message['Subject'] = "subject"
zf = open(r"C:\Users\Full File Path to Zip File\Zip File Name.zip",'rb')
obj = MIMEBase('application', 'octet-stream')
obj.set_payload(zf.read())
encoders.encode_base64(obj)
obj.add_header('Content-Disposition', "attachment; filename= " )
message.attach(obj)
my_message = message.as_string()
email_session = smtplib.SMTP("smtp-mail.outlook.com", 587)
email_session.starttls()
email_session.login(sender_email, 'email password')
email_session.sendmail(sender_email, receiver_email, my_message)
email_session.quit()
print("YOUR MAIL HAS BEEN SENT SUCCESSFULLY")

Related

I have inconsistent attachment icon status when sending python email

I am using How to send email attachments?
as a basis to try and send an email with and without an attachment using python and have ended up with this code:
import smtplib
from os.path import basename
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import COMMASPACE, formatdate
def send_mail(send_from, send_to, subject, text, files=None):
assert isinstance(send_to, list)
msg = MIMEMultipart('html')
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 or []:
with open(f, "rb") as fil:
part = MIMEApplication(fil.read(),Name=basename(f))
part['Content-Disposition'] = 'attachment; filename="%s"' % basename(f)
msg.attach(part)
server = smtplib.SMTP_SSL('smtp.pobox.com', 465)
server.login('<username>', '<password>')
server.sendmail(send_from, send_to, msg.as_string())
server.close()
send_mail("<username>",["<username>"],"subject","text",["D:\\Desktop\\Python Test\\Logfile.txt"]) # with attachment
#send_mail("<username>",["<username>"],"subject","Text") # without attachment
which appears to send an email with and without attachment depending on the last two lines of the code.
The problem is that with this line of code msg = MIMEMultipart('html') the email received does not show the paperclip attachment icon even if it contains an attachment in the email. So, regardless of whether the email contains an attachment, there is no paperclip attachment icon.
If however, I change this to msg = MIMEMultipart('') I get a paperclip attachment icon on all emails even if they dont contain an attachment.
Does anyone know how I can fix this so that the paperclip attachment icon shows when there is an attachment and not when there isn't one?

send HTMLbody from file using python

I can send the plain text but unable to send html text in html format.
import email, smtplib, ssl
import os
from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
body = """
this is first mail by using python
"""
port_email = 587
smtp_server = "smtp.gmail.com"
password = "your password"
subject = "An email with attachment from Python"
sender_email = "sender#gmail.example.com"
receiver_email = "receiver#example.net"
# 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 = "file name" # In same directory as script
with open(filename.html, 'r', encoding="utf-8") as attachment:
part1 = attachment.read()
part2 = MIMEText(part1, "html")
message.attach(part2)
text = message.as_string()
context = ssl.create_default_context()
with smtplib.SMTP_SSL(smtp_server, 465 , context=context) as server:
server.login(sender_email, password)
server.sendmail(sender_email, receiver_email, text)
This will send attach file but i want to see the html text in email body.
filename is content html table so code should send the html text which will automatic available in html body with html table.
Why are you passing a bogus body if that's not what you want?
Your code seems to be written for Python 3.5 or earlier. The email library was overhauled in 3.6 and is now quite a bit more versatile and logical. Probably throw away what you have and start over with the examples from the email documentation.
Here's a brief attempt.
from email.message import EmailMessage
...
message = EmailMessage()
message["From"] = sender_email
message["To"] = receiver_email
message["Subject"] = subject
# No point in using Bcc if the recipient is already in To:
with open(filename) as fp:
message.set_content(fp.read(), 'html')
# no need for a context if you are just using the default SSL
with smtplib.SMTP_SSL(smtp_server, 465) as server:
server.login(sender_email, password)
# Prefer the modern send_message method
server.send_message(message)
If you want to send a message in both plain text and HTML, the linked examples show you how to adapt the code to do that, but then really, the text/plain body part should actually contain a useful message, not just a placeholder.
As commented in the code, there is no reason to use Bcc: if you have already specified the recipient in the To: header. If you want to use Bcc: you will have to put something else in the To: header, commonly your own address or an address list like :undisclosed-recipients;
Tangentially, when opening a file, Python (or in fact the operating system) examines the user's current working directory, not the directory from which the Python script was loaded. Perhaps see also What exactly is current working directory?
Mime has a variety of formats. By default MIMEMultipart builds a multipart/mixed message, meaning a simple text body and a bunch of attachments.
When you want an HTML representation of the body, you want a multipart/alternative message:
...
message = MIMEMultipart('alternative')
...
But you are using the old compat32 API. Since Python 3.6 you'd better use email.message.EmailMessage...

How to automatically send personalized emails with a pdf attachment in Python?

I am a beginner programmer and I am trying to write a program that automatically sends personalized emails to a list of receivers in a csv file with a pdf attachment.
My current code sends personalized emails but I don't know how to add an attachment. Also, I think it's best practice to write the program in a function but I don't know how to do that either.
It would be greatly appreciated if anyone could help me out. Also, I want to keep it as simple as possible so that I still understand what every line of code does.
import os
import smtplib, ssl
import csv
# Sender credentials (from environment variables)
email_address = os.environ.get("email_user")
email_pass = os.environ.get("email_app_pass")
context = ssl.create_default_context()
with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
server.login(email_address, email_pass) # Log into sender email account
# Email information
subject = "Testing Python Automation"
body = """ Hi {name},\n\n This email was entirely generated in Python. So cool!
"""
msg = f"Subject: {subject}\n\n{body}"
with open("contacts_test.csv") as file:
reader = csv.reader(file)
next(reader) # Skip header row
for name, email in reader:
server.sendmail(email_address, email, msg.format(name=name))
file.close()
server.quit()
This will only work using gmail and make sure you have manually set up
special permissions on your gmail account for the program to be able to send email on behalf of you. The process is described here.
You can use other email address services for that you need to change the smtp server address and the smtp port number in line 32 accordingly and take care of any other additional steps required.
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
body = """
Hi {name},\n\n This email was entirely generated in Python. So cool!
""".format(name="Name")
# details
sender = 'example1#gmail.com' # my email
password = '&*password.$' # my email's password
receiver = 'example2#gmail.com' # receiver's email
msg = MIMEMultipart()
msg['To'] = receiver
msg['From'] = sender
msg['Subject'] = 'Testing Python Automation'
msg.attach(MIMEText(body, 'plain'))
pdfname = "mypdf.pdf" # pdf file name
binary_pdf = open(pdfname, 'rb')
payload = MIMEBase('application', 'octate-stream', Name=pdfname)
payload.set_payload((binary_pdf).read())
encoders.encode_base64(payload)
payload.add_header('Content-Decomposition', 'attachment', filename=pdfname)
msg.attach(payload)
session = smtplib.SMTP('smtp.gmail.com', 587)
session.starttls()
session.login(sender, password)
text = msg.as_string()
session.sendmail(sender, receiver, text)
session.quit()
print('[#] Mail Sent!')

Sending multiple emails with Python consecutively but some are missing

I was trying to send around 10+ emails (each has an Excel file attached) consecutively by invoking the below Python function send_email(), which is based on the sample code shared by the tutorials on the web.
Somehow I found that though the 10+ emails are sent without errors/exceptions, occasionally some of the emails are not recipeved by the recipients. I checked the Sent box of the specified sender email account, for the emails that weren't received by the recipients, they are not in the sender's Sent box either.
I speculated that it could be due to those consecutive invocations of send_email() overflooded the SMTP server (but not sure) so I added 1 sec delay between the invocation (as specified below). However, the issue still happens occasionally. Now I'm trying to increase the delay from 1sec to 10sec.
Please kindly advise if my speculation is in the right direction and if there is anything I need to do to better pinpoint the root cause. Thanks a lot.
My code is as follows:
(a) Invoking send_email() consecutively in a loop. For each loop assign the corresponding email recipients, subject, message, and Excel attachment as the inputs.
(b) To add delays in between send_email() calls, time.sleep(1) is invoked to add 1 sec delay in the hope of not to overflow the SMTP server.
(c) The code of send_email() is as follows:
#Email the generated Excel file out
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
import os.path
def send_email(email_recipients, email_subject, email_message, attachment_location = ''):
email_sender = 'xxx' #xxx is the sender's email address
msg = MIMEMultipart()
msg['From'] = email_sender
msg['To'] = ", ".join(email_recipients)
msg['Subject'] = email_subject
msg.attach(MIMEText(email_message, 'plain'))
if attachment_location != '':
filename = os.path.basename(attachment_location)
attachment = open(attachment_location, "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)
try:
mailserver = smtplib.SMTP('smtp.office365.com', 587)
mailserver.ehlo()
mailserver.starttls()
mailserver.login('xx', 'xxxx') # xx and xxxx are the credentials for the smtp server
text = msg.as_string()
mailserver.sendmail(email_sender, email_recipients, text)
print('email sent')
except Exception as e:
print(e)
print("SMPT server connection error")
finally:
mailserver.quit()
return True

Sending Email to different recipients with different file attachments using python

Hi I'm new to learning python and I'm trying to send emails to a few hundred different recipients with a different attachment to each of them. I have the recipients data in a database and a folder with all the files in it.
Database has supplier id, name and email
Database example
The folder structure is just one folder with all the files in it for example :
Folder screenshot
Supplier files folder --
123.xls
123.pdf
456.xls
789.pdf
any direction on how to get started with this is appreciated. Thank you
In this example I will use an answer that I gave to another question (How do I attach separate PDF's to contact list email addresses using Python?) , I use a csv file that contains the addresses and the file path that corresponds to it like img bellow :
users.csv :
folder with csv files :
And this is the code:
import smtplib, ssl
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
from string import Template
import pandas as pd
# read the file containing the database with the mail and the corresponding file
e = pd.read_csv("users.csv")
# In this example we will use gmail
context = ssl.create_default_context()
server = smtplib.SMTP_SSL('smtp.gmail.com', 465,context=context)
server.login('mymail#gmail.com','mypass')
body = ("""
Hi there
Test message
Thankyou
""")
subject = "Send emails with attachment"
fromaddr='mymail#gmail.com'
for index, row in e.iterrows():
print (row["Emails"]+row["csv"])
msg = MIMEMultipart()
msg['From'] = fromaddr
msg['Subject'] = subject
msg.attach(MIMEText(body, 'plain'))
filename = row["csv"]
toaddr = row["Emails"]
attachment = open(row["csv"], "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()
server.sendmail(fromaddr, toaddr, text)
print("Emails sent successfully")
server.quit()
if you use a gmail account, check that you have it permissions to send emails from other types of clients (https://support.google.com/accounts/answer/6010255)

Categories