I am working on a simple program with Python 3.4 on Windows 8.1, and being a newcomer to programming, I am a bit stumped.
When I send myself an email to my Godaddy office 365 account, the only thing I can see is the title "No Subject", (I would like to have something there.) I can see the From field which is my email address, and the rest is blank. Nothing in the body of the email. I figured I would ask someone who has more experience than I do as to what I am doing wrong. Here is my code, cleaned up a bit.
#Send Email
import smtplib
server=smtplib.SMTP('smtp.office365.com',587)
server.starttls()
server.login('mylogininfo','mypassword')
server.sendmail('email#myaddress.com','email#address.com',"This is a test
Pyhton Email")
I don't know if there is a better way of doing this but I am open to suggestions. Thanks Everyone.
You should create your email with MIMEMultipart as follows:
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
def send_email():
to_emails= "to_email#gmail.com"
message="Hi, this is the email body"
s = smtplib.SMTP(host='smtp.office365.com', port=587)
s.starttls()
s.login('mylogininfo','mypassword')
msg = MIMEMultipart()
msg['From']='mylogininfo'
msg['To']=to_emails
msg['Subject']="My Subject"
msg.attach(MIMEText(message, 'plain'))
s.send_message(msg)
del msg
s.quit()
send_email()
Related
I am creating a program where I send an image to someone by mail with Tkinter and smtplib in python 3. Everything works fine but when someone receives the email it looks like this:
but I want it to look like this:
does anyone know why the { ? } shows up?
the code I use to send the photo is this:
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
msg = MIMEMultipart()
fp = open(image, 'rb')
photo = MIMEImage(fp.read(), _subtype="jpg")
fp.close()
msg.attach(photo)
Thanks!
I am working on python code which will add one string in excel file and will attach that file to email. I am sending this email using AWS SES.
When I am trying to run my code it is giving me below error -
TypeError: expected bytes-like object, not Workbook
Below is my code-
import boto3
import xlsxwriter
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
def lambda_handler(event, context):
client = boto3.client('ses',region_name=AWS_REGION)
sender = "xxx#gmail.com"
to = "aaa#gmail.com"
workbook = xlsxwriter.Workbook('abc.xlsx')
worksheet = workbook.add_worksheet()
worksheet.write('A1', 'Hello..')
#send email with attachment
msg = MIMEMultipart()
msg['Subject'] = 'Test Email'
msg['From'] = sender
msg['To'] = to
body_text = MIMEText(BODY_TEXT, "html")
attachment = MIMEApplication(workbook)
attachment.add_header('Content-Disposition', 'attachment', filename='Expenses01.xlsx')
msg.attach(attachment)
msg.attach(body_text)
response = client.send_raw_email(
Source=sender,
Destinations=[to],
RawMessage={"Data": msg.as_string()}
)
I know there is something wrong with workbook object. But I don't know how to resolve this issue. Can someone please help me out?
After reading XLSXWriter documentation, I found answer for this. Link - https://xlsxwriter.readthedocs.io/workbook.html
I am posting this answer, so that it can help other new python developers like me.
Earlier MIMEApplication() was not accepting workbook object so we need to convert it. I have updated my code. I have used BytesIO to create Workbook object and then added that object to MIMEApplication(). This example will create excel file and will attach that file to email.
New code-
from io import BytesIO
output = BytesIO()
workbook = xlsxwriter.Workbook(output)
worksheet = workbook.add_worksheet()
worksheet.write('A1', 'Hello..')
attachment = MIMEApplication(output.getvalue())
attachment.add_header('Content-Disposition', 'attachment', filename='abc.xlsx')
attachment.add_header('Content-Type', 'application/vnd.ms-excel; charset=UTF-8')
Your question did not say where the error occurs,
but I think it happens here:
attachment = MIMEApplication(workbook)
You should pass in bytes, rather than a complex python object.
Call workbook.close() to write out the 'abc.xlsx' file,
and send that binary file as an attachment.
As you may well know, some mail addresses need to turn off security for less secure apps in gmail.
Turning off options works like a charm with smtplib and attachments, but without turning off it don't works at all.
Then I discovered an API way using Auth 2.0 in ezgmail module, and it can send emails very easy, but however the attachments are not attached well. they have some problem at encoded, because they don't display well the documents.
The code I ended up with is:
import ezgmail
import os, sys, glob
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
pathFile = '<path>'
folder = os.getcwd()
def compose():
# email_from = '<my email>'
subject = 'Hello,'
body = '''Here I put the text I want.'''
return [subject, body]
def send_email(email_to):
subject, body = compose()
ezgmail.EMAIL_ADDRESS = '<my email>' # email_from
os.chdir(pathFile)
list_pdfs = glob.glob('*.pdf')
file1 = max(list_pdfs, key=os.path.getctime) # select latest file
# this should do the *encode part*
attachment = open(file1, 'rb')
file = MIMEBase('application','octet-stream')
file.set_payload((attachment).read())
encoders.encode_base64(file)
os.chdir(folder)
ezgmail.send(email_to, subject, body, file.as_string())
print("Mail sent")
send_email(to#example.com)
And the question it's : how to attach properly documents (pdf, word, excel) to ezgmail ?
The attachment(s) need to be a string (or list of strings) representing the path(s) to the document(s):
def send_email(email_to):
subject, body = compose()
ezgmail.EMAIL_ADDRESS = '<my email>' # email_from
os.chdir(pathFile)
list_pdfs = glob.glob('*.pdf')
file1 = max(list_pdfs, key=os.path.getctime) # select latest file
os.chdir(folder)
ezgmail.send(email_to, subject, body, os.sep.join([pathFile, file1]))
print("Mail sent")
The encoding is a separate issue.
The author says:
EZGmail isn't meant to be comprehensive and do everything the Gmail API lets
you do, it's meant to make the simple things simple
It does attempt to do the MIME conversion, but there is nothing specific for pdf files
the following code needs to be inserted into the EZgmail module in the _createMessageWithAttachments method:
elif sub_type == 'pdf':
mimePart = MIMEBase('application','octet-stream')
mimePart.set_payload((fp).read())
encoders.encode_base64(mimePart)
and you need to import encoders from email
As a brief summary, I have a bunch of '.eml' files in a directory. I need to forward these emails back to 'email#example.com'.
The problem is that the field 'From' in the header of the '.eml' file contains another email address which doesn't match with 'email#example.com'.
I've searched for a way to parse the file and update the content of the header.
At first, I was using the following modules:
eml.parser to parse the file.
pyo365 to connect to MSGraph API
I was able to send the content of the body but when I would try to send the attachments, I had to decode from base64 and extract the attachments in a folder, then send everything. I did not need to change the content of the header.
I know this was a bad move because there is probably a way to send the attachments encoded.
Also, since MSGraph attachment's file size limit is 4mb per requests, I decided to try to change for:
smtplib to send the email
I tried mail-parser without success to update anything in the content since the updated values would not be permanent, for instance:
mail = mailparser.parse_from_bytes(byte_mail)
mail.from_ = [('My Name' , 'email#example.com')]
print(mail.headers) #This would print the original header
I also tried with mail.update() and various method using this module without success.
I found a post Python: Modify Values in eml file (email header) which suggested to use Parser, replace_header and as_string from email but I was unable to make it work either as I wouldn't be able to call replace_header and as_string:
from email.message import EmailMessage #contains as_string
from email.parser import HeaderParser
file = open(filename, 'r')
h = HeaderParser().parse(file)
#stuck here
I know this is probably not only one question but the main goal is to send eml files back to a particular address, from 'email#example.com'.
The issue was resolved by parsing the email with eml_parser. I created my own header, attached the HTML body content and the attachments.
from passlib.context import CryptContext
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from email.header import Header
def send(self, dst):
try:
self.m = MIMEMultipart()
self.m['From'] = self.client_addr
self.m['To'] = dst
# Must have Header() in python 3.x otherwise you get UnicodeError
self.m['Subject'] = Header(self.get_subject(), 'utf-8')
#Attach HTML body with the right encoding
self.m.attach(MIMEText(self.get_body().encode('utf-8'), 'html', 'utf-8'))
# Extract attachments to self.attachment_path
self.extract_attachments(self.parsed_eml)
server = smtplib.SMTP('smtp.office365.com', 587)
server.ehlo()
server.starttls()
# Compare hash in config.json file
if self.pwd_context.verify(self.client_plain_secret, self.client_secret):
server.login(self.client_addr, self.client_plain_secret)
server.sendmail(self.m['From'], self.m['To'], self.m.as_string())
server.quit()
except:
print("An error occured trying to send the email.")
finally:
self.clean_attachments()
I used SMTP to send images through mail. It can send mail, but the images can't be opened; it said unsupported format. The image was taken using opencv. Here is the code I used. Please tell me what I did wrong in the program. There is no error but the image can't opened.
Cods:
import cv2
i=0
camera = cv2.VideoCapture(0)
if(i==0):
for i in range(1):
return_value, image = camera.read()
cv2.imwrite('Disease'+str(i)+'.png', image)
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
fromaddr = "xxxxxx#gmail.com"
toaddr = "yyyyyy#gmail.com"
msg = MIMEMultipart()
msg['From'] = fromaddr
msg['To'] = toaddr
msg['Subject'] = "DISEASE"
body = "FOR NOTIFICATION"
msg.attach(MIMEText(body, 'plain'))
filename = "Disease.png"
attachment = open("C:/tensorflow1/models/research/object_detection/capture.py", "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()
You are attaching a piece of Python code and claiming that it is an image. I imagine you probably want to run that code and attach its output.
Assuming C:/tensorflow1/models/research/object_detection/capture.py is the path to the code which you included which creates the image, and that C:/tensorflow1/models/research/object_detection/ is on your PYTHONPATH, you simply want to
import disease
though arguably, a better design is to restructure this file so that it declares a function you can call when you need to, rather than running the code exactly once immediately when you import it; the standard mechanism for this is
def functionname():
# ... Your code here
if __name__ == '__main__':
functionname()
and the way to import and call this code is then
import disease
# ... Other code ...
disease.functionname()
(Obviously, a better name than functionname would be something properly descriptive, like generate_png.)
Perhaps you might want to avoid writing the image to disk at all if you are only using it to attach it to an email message and then discarding it, but as this is somewhat speculative, and hitting the disk is not a major efficiency problem, I won't elaborate on that at this point.
As another detail, you are attaching the image as a generic application/octet-stream body part. Images have their own designated MIME types; you'll want image/png for a PNG picture.
The Python class for this type of attachment is MIMEImage.
from email.mime.image import MIMEImage
# ...
image_filename = './Disease.png'
image = MIMEImage(open(image_filename, 'rb').read(), name=os.path.basename(image_filename))
msg.attach(image)
The class generally already knows how to set detailed attributes like the precise image type and the content disposition and transfer encoding.
As a stylistic aside, import statements should generally be at the top of the file; see PEP-8.