Sending an email with attachment - python

I am trying to write a function that send an email with an attached file. At the moment, it send an email but without attachment. Can you someone comment?
msg = MIMEMultipart()
msg['From'] = my email
msg['To'] = client email address
msg['Subject'] = subject
body = content
msg.attach(MIMEText(body, 'plain'))
##### Load the address of the file which should be attached*********************************
filename = filedialog.askopenfilename(initialdir = "/",title = "Select file",filetypes = (("Text
files","*.txt"),("all files","*.*")))
Myfile = open(filename)
attachment = MIMEText(Myfile.read())
attachment.add_header('Content-Disposition', 'attachment', filename=filename)
msg.attach(attachment)
mail = smtplib.SMTP('smtp.gmail.com', 587)
msg = f'Subject: {subject}\n\n{content}'
mail.ehlo()
mail.starttls()
mail.login('My email address', 'password')
mail.sendmail('client email', My email address, msg)
mail.close()
Thank you all in advance

First, as mentioned in my comment, you're overwriting msg here:
msg = f'Subject: {subject}\n\n{content}'
At this point, the MIMEMultipart object msg used to point to is destroyed, and you'll send only that new string. No wonder why there's no attachment: this string obviously doesn't have an attachment.
Now, you should really be using the new API of the email module, as shown in the documentation. But since you're already using the legacy API (the MIMEMultipart class, for example), you'll need to convert msg to a string, as shown here:
# This is copied straight from the last link
msg = MIMEMultipart('alternative')
msg['Subject'] = "Link"
msg['From'] = me
msg['To'] = you
...
part1 = MIMEText(text, 'plain') # example attachment
# Attach parts into message container.
# According to RFC 2046, the last part of a multipart message, in this case
# the HTML message, is best and preferred.
msg.attach(part1)
mail.sendmail(
me, you,
msg.as_string() # CONVERT TO STRING
)

Related

Embedding image in HTML email using Python

I have been trying to embed images to an email using MIMEImage but even after replicating examples I find online, I keep having the same issue...
Here is the part of the HTML that embeds the image:
<img width=779 height=467 style='width:8.1145in;height:4.8645in' src="cid:image001" alt="HRX Trend">
This is my Python code:
msg = MIMEMultipart('alternative')
msg['Subject'] = "test for daily email"
msg['From'] = me
msg['To'] = you
fp = open('path\\name.jpeg', 'rb')
msgImage = MIMEImage(fp.read())
msgImage.add_header('Content-ID', '<image001>')
part2 = MIMEText(html, 'html')
msg.attach(part2)
msg.attach(msgImage)
s = smtplib.SMTP('domain', port)
s.sendmail(me, you, msg.as_string())
s.quit()
But, when the email sends, I keep getting the error saying:
The linked image cannot be displayed. The file may have been moved, renamed, or deleted.
Screenshot of what the email ends up looking like:
I have no idea what I am doing wrong...
Thank you!
I updated the message container and the issue was resolved:
Original:
msg = MIMEMultipart('alternative')
msg['Subject'] = "test for daily email"
msg['From'] = me
msg['To'] = you
New:
msg = MIMEMultipart()
msg['Subject'] = "test for daily email"
msg['From'] = me
msg['To'] = you

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 add sender name before sender address in python email script

Here's my code
# Import smtplib to provide email functions
import smtplib
# Import the email modules
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
# Define email addresses to use
addr_to = 'user#outlook.com'
addr_from = 'user#aol.com'
# Define SMTP email server details
smtp_server = 'smtp.aol.com'
smtp_user = 'user#aol.com'
smtp_pass = 'pass'
# Construct email
msg = MIMEMultipart('alternative')
msg['To'] = addr_to
msg['From'] = addr_from
msg['Subject'] = 'test test test!'
# Create the body of the message (a plain-text and an HTML version).
text = "This is a test message.\nText and html."
html = """\
"""
# Record the MIME types of both parts - text/plain and text/html.
part1 = MIMEText(text, 'plain')
part2 = MIMEText(html, 'html')
# Attach parts into message container.
# According to RFC 2046, the last part of a multipart message, in this case
# the HTML message, is best and preferred.
msg.attach(part1)
msg.attach(part2)
# Send the message via an SMTP server
s = smtplib.SMTP(smtp_server)
s.login(smtp_user,smtp_pass)
s.sendmail(addr_from, addr_to, msg.as_string())
s.quit()
I just want the email received to display the sender name before sender email address like this : sender_name
In the year 2020 and Python 3, you do things like this:
from email.utils import formataddr
from email.message import EmailMessage
import smtplib
msg = EmailMessage()
msg['From'] = formataddr(('Example Sender Name', 'john#example.com'))
msg['To'] = formataddr(('Example Recipient Name', 'jack#example.org'))
msg.set_content('Lorem Ipsum')
with smtplib.SMTP('localhost') as s:
s.send_message(msg)
It depends on whether the "friendly name" is basic ASCII or requires special characters.
Basic example:
msg['From'] = str(Header('Magnus Eisengrim <meisen99#gmail.com>'))
If you need to use non US-ASCII characters, it's more complex, but the attached article should help, it is very thorough: http://blog.magiksys.net/generate-and-send-mail-with-python-tutorial
This is an old question - however, I faced the same problem and came up with the following:
msg['From'] = formataddr((str(Header('Someone Somewhere', 'utf-8')), 'xxxxx#gmail.com'))
You'll need to import from email.header import Header and from email.utils import formataddr.
That would make only the sender name appear on the inbox, without the <xxxxx#gmail.com>:
While the email body would include the full pattern:
Putting the sender name and the email in one string (Sender Name <sender#server.com>) would make some email clients show the it accordingly on the receiver's inbox (unlike the first picture, showing only the name).
I took the built-in example and made it with this:
mail_body = "the email body"
mailing_list = ["user1#company.com"]
msg = MIMEText(mail_body)
me = 'John Cena <mail#company.com>'
you = mailing_list
msg['Subject'] = subject
msg['From'] = me
msg['To'] = mailing_list
# Send the message via our own SMTP server, but don't include the
# envelope header.
s = smtplib.SMTP('localhost')
s.sendmail(me, [you], msg.as_string())
s.quit()
I found that if I send an email with gmail and set the From header to sender name <email#gmail.com>, the email arrives with the From like:
From sender name email#gmail.com email#gmail.com.
So I guess at least with gmail you should set the From header like as follow:
msg['From'] = "sender name"
You can use below mentioned code, you just need to change sender and receiver with user name and password, it will work for you.
import smtplib
sender = 'xyz#gmail.com'
receivers = ['abc#gmail.com']
message = """From: sender_name <xyz#gmail.com>
To: reciever_name <abc#gmail.com>
Subject: sample test mail
This is a test e-mail message.
"""
try:
smtpObj = smtplib.SMTP('smtp_server',port)
smtpObj.sendmail(sender, receivers, message)
smtpObj.login(user,password)
print ("Successfully sent email")
except:
print ("Error: unable to send email")
for more detail please visit https://www.datadivein.com/2018/03/how-to-auto-send-mail-using-python.html

Python2.7 sending mail, why msg['To'] stay empty?

I am sending multiple recipients mail with a python script, and it works, but in the "To" in the mail, the field is empty. On every mail provider I tried.
Here is my code :
def send_mail(self, server, send_from, subject, attach, foo=None, bar=None)
msg = MIMEMultipart()
msg['From'] = send_from
msg['Subject'] = subject
body = u"""<html> My Body </html>"""
#Attach file pdf
msg.attach(MIMEText(body, 'html', 'utf-8'))
filename = 'fname.pdf'
attachment = open(attach, "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()
if foo != None and bar != None:
recipients = ["a#b.fr", "b#b.fr"]
msg['To'] = ", ".join(recipients)
server.sendmail(send_from, recipients, text)
else:
msg['To'] = "c#b.fr"
server.sendmail(send_from, msg['To'], text)
sleep(1)
msg['To'] should be the "To" in my mail but it stays empty. (Even in the "else" with only one recipient). I can't find any help about it on existing question, so I come to ask for your help about that.
As per the documentation, the second parameter is a LIST of recipients. You need to change your line
server.sendmail(send_from, msg['To'], text)
to
server.sendmail(send_from, [msg['To']], text)
Finally found out:
text = msg.as_string() should be done after the assignement to msg['To'] So it will appear in my if and else block juste before the server.sendmail(send_from, msg['To'], text) since all information written in the mail, even 'To', and 'From' are in the third argument text .

Categories

Resources