Python: Sending an email with attachement - python

I am working on a project with a raspberry pi 3 which makes a photo when something is moving. Now I want to send an email with this photo as an attachement.
I already have a code but it tooks 30 seconds to send the mail.
The code I have so far is:
msg = MIMEMultipart()
msg['Subject'] = 'Bewegung erkannt!'+' '+timestr
msg['From'] = 'surveillance.picam#gmail.com'
msg['To'] = 'fuchsfan23#gmail.com'
body = email.mime.Text.MIMEText("""Bewegung erkannt! Hier ist der Eindrinling!""")
msg.attach(body)
directory = '/home/pi/Pictures/RaspCam/bild_{}.jpg'.format(timestr)
spl_dir=directory.split('/')
filename=spl_dir[len(spl_dir)-1]
spl_type=directory.split('.')
type=spl_type[len(spl_type)-1]
fp=open(directory,'rb')
att = email.mime.application.MIMEApplication(fp.read(),_subtype=type)
fp.close()
att.add_header('Content-Disposition','attachment',filename=filename)
msg.attach(att)
s = smtplib.SMTP('smtp.gmail.com:587')
s.starttls()
s.login('mailaddress1','passwd')
s.sendmail('mailaddress1','mailaddress2', msg.as_string())
s.quit()
This code is within an callback which makes the photo when something is moving and saves it.
I hope someone can help me...
CrypticEagle

Related

Python sends bulk mail from [BCC] insted of [TO], why?

I am writing a python script that sends every day a bulk email (connected to an outlook.com account) with the body of a news website as an ebook to multiple kindle accounts (that have already whitelisted this outlook account).
This was working so far, but since yesterday the kindle devices couldn't get the ebooks. I've tried a lot and I found out, that the problem is because all the sent emails have the receiver in the BCC part of the email. For some reason since yesterday if the receiver is on BCC, kindle doesn't receive the email (or process it).
So I am asking, what should I change on my code so I could have the receiver addresses on the [TO] part of the email instead of the [BCC]. I don't mind if it's a single email with multiple addresses or multiple single emails, as far as the receiver is not on the BCC.
receiver_email = ["email1#mail.com", "email2#mail.com", "email3#mail.com", "email4#mail.com", "email5#mail.com"]
subj = "Issue - "+fullDate
msg = MIMEMultipart('alternative')
msg['Subject'] = subj
msg['From'] = sender_email
msg.attach(MIMEText('Forward this email to your kindle account'))
# Attach the .mobi file
print("Attaching "+epubname)
fp = open(epubname, "rb")
epub_file = MIMEApplication(fp.read())
fp.close()
encoders.encode_base64(epub_file)
epub_file.add_header('Content-Disposition', 'attachment', filename=epubname)
msg.attach(epub_file)
debug = False
if debug:
print(msg.as_string())
else:
server = smtplib.SMTP('smtp.office365.com',587)
server.ehlo()
server.starttls()
server.login("##EMAIL##", "##PASSWORD##")
text = msg.as_string()+ "\r\n" + message_text
for x in range(len(receiver_email)):
email_to = receiver_email[x]
msg['To'] = email_to #msg['To'] = ", ".join(email_to)
server.sendmail(sender_email, email_to, text.encode('utf-8'))
server.quit()
I've found this question, but with no specific answer unfortunately.
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.
The simple and obvious solution is to put all the recipients in msg["to"] instead of msg["bcc"].
Here is a refactoring for Python 3.3+ (the new API was informally introduced already in 3.3).
from email.message import EmailMessage
receiver_email = ["email1#mail.com", "email2#mail.com", "email3#mail.com", "email4#mail.com", "email5#mail.com"]
subj = "Issue - "+fullDate
msg = EmailMessage()
msg['Subject'] = subj
msg['From'] = sender_email
msg['To'] = ", ".join(receiver_email)
msg.set_content('Forward this email to your Kindle account')
with open(epubname, "rb") as fp:
msg.add_attachment(fp.read()) # XXX TODO: add proper MIME type?
debug = False
if debug:
print(msg.as_string())
else:
with smtplib.SMTP('smtp.office365.com',587) as server:
server.ehlo()
server.starttls()
server.login("##EMAIL##", "##PASSWORD##")
server.send_message(msg)
This sends a single message to all the recipients; this means they can see each others' email addresses if they view the raw message. You can avoid that by going back to looping over the recipients and sending one message for each, but you really want to avoid that if you can.
As an aside, you don't need range if you don't care where you are in the list. The idiomatic way to loop over a list in Python is simply
for email_to in receiver_email:
...

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 attach email to another email with end result where top level mail content-type message/rfc822 in python 3?

I had looked into email lib of python but did not find any reference where it suggests way to attach mail to mail with content-type message/rfc822.
#Message to be attached to new mail
parsed_message = email.message_from_string(str(desearilized_message))
msg = MIMEMultipart()
msg['From'] = "somesender#send.me"
msg['To'] = "somereciver#recive.me"
msg['Subject'] = "Subject of the Mail"
body = "Body_of_the_mail"
msg.attach(parsed_message)
This results in parent mail with Content-Type: multipart and not message/rfc822.
Any reference/suggestion of how to achieve it in python3?
This works for me.
msg = EmailMessage()
msg.__setitem__("Content-type","message/rfc822")

Reply All to emails using python Imap4

I have a working code that replies to email from a specific inbox.
msg = EmailMessage()
msg['In-Reply-To'] = orig_mail['message_id']
msg['From'] = sender
msg['To'] = recipient
msg['Subject'] = subject
I need to Reply All to that email instead of just Reply .
Is there any way i can implement that here? Any help would be appreciated, Thanks.
I don't think Reply ALL feature is there. But this would work out if you want to send mail to multiple people
recipients = ['john.doe#example.com', 'john.smith#example.co.uk']
msg['From'] = sender
msg['Subject'] = subject
msg['To'] = ", ".join(recipients)

Sending an email with attachment

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
)

Categories

Resources