I have a code, that generate me .eml message file which I open in Outlook. But the message file is uneditable (can't edit this file). E.g.: I want to add new sender or recepiant, but I can't do that.
Does anybody know, how fix this problem, or may be there is another way to create message file?
import email
from email import generator
from email.mime.text import MIMEText
from email.encoders import encode_base64
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
import json
import SQL_from_DB
import os
import re
def create_mail(attach_file_name, message_json, mail_template_path, save_path, database, db_username, db_password, driver):
file_name_mail_template = mail_template_path + re.sub("QWE:\[.*?\]\s+","",message_json['message']) + '.txt'
try:
mail_template_file = open(file_name_mail_template.encode('utf-8'), 'r', encoding="utf-8")
except:
print("Ошибка открытия шаблона пиьсма \"" + re.sub("QWE:\[.*?\]\s+","",message_json['message']) + ".txt\"")
sys.exit()
mail_template_text = mail_template_file.read()
for var, value in message_json.items():
mail_template_text = mail_template_text.replace('${' + str(var) + '}', str(value))
# print(mail_template_text)
msg = MIMEMultipart()
msg['Subject'] = message_json['message']
msg['From'] = 'qwe#qwe.qwe'
msg['To'] = SQL_from_DB.SQL_select(database, db_username, db_password, driver, message_json['DOMAINNAME'])
#add attachment
attach_file = open(attach_file_name.encode('utf-8'), 'rb')
attachment = MIMEBase("application", "msword")
#attachment = MIMEBase("application", "pdf")
attachment.set_payload(attach_file.read())
attach_file.close()
encode_base64(attachment)
attachment.add_header('Content-Disposition','attachment',filename='Events' + ".zip")
msg.attach(attachment)
#текст письма
msg.attach(MIMEText(mail_template_text, 'html'))
#save message file
with open(save_path.encode("utf-8"), 'w') as out:
gen = email.generator.Generator(out)
gen.flatten(msg)
return(save_path)
To generate an editable Outlook file, just need generate not .eml but .emltpl (Outlook message template file).
#save message file
with open('/save_path/message.emltpl', 'w') as out:
gen = email.generator.Generator(out)
gen.flatten(msg)
return(save_path)
Related
I am trying to achieve the following:
I have an email object (eml) which can contain multiple attachments like zip/images/txt etc.
I want to download only a specific attachment and not all the attachments from this object.
I have tried the following code:
import email
import mimetypes
import uuid
import os
m = email.message_from_file(open('hello.eml'))
for part in m.walk():
filename = part.get_filename()
print('fileName: ', filename)
if part.get_content_type() == 'multipart/mixed' and not filename:
number_of_attachments = (len(part.get_payload()) - 1)
print('number_of_attachments: ', number_of_attachments)
for attachment in range(number_of_attachments):
tmp_name = str(uuid.uuid4())
fp = open('.' + tmp_name, 'wb')
attachment += 1
fp.write(part.get_payload()[attachment].get_payload(decode=True))
fp.close()
This extracts all the attachments.
Is there a way to filter only specific attachment and process that.
Any help is much appreciated!
So, I found the following way.
import email
import mimetypes
import uuid
import os
m = email.message_from_file(open('hello.eml'))
for part in m.walk():
filename = part.get_filename()
print('fileName: ', filename)
if part.get_content_type() == 'multipart/mixed' and not filename:
number_of_attachments = (len(part.get_payload()) - 1)
print('number_of_attachments: ', number_of_attachments)
for attachment in range(number_of_attachments):
filteredFile = m.get_payload()[attachment]
if filteredFile.get_content_type() == 'text/html':
print("Search successful.")
else:
print("Search unsuccessful.")
Thanks all for your inputs!
How I may send birthday congratulations with attached jpg file to our cutomers by email?
I write script, he show notifications:
import time
import os
birthdayFile = 'birthdays.csv'
def checkTodaysBirthdays():
fileName = open(birthdayFile, 'r')
today = time.strftime('%m%d')
flag = 0
for line in fileName:
if today in line:
line = line.split(' ')
flag =1
os.system('notify-send "Birthdays Today: ' + line[1]
+ ' ' + line[2] + '"')
if flag == 0:
os.system('notify-send "No Birthdays Today!')
But I dont know, how send congrats by email.
File birthdays.csv contain next row: date, name, email
You can use smtplib. Below is an implementation of the simple notification system using a class, to utilize clean context-manager behavor:
import datetime
import smtplib, csv
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email import Encoders
class SendEmail:
def __init__(self, _to, _from = 'youremail#domaim.com', subject = 'Happy Birthday!', attachment = 'birthday.jpg'):
self._to = _to
self._from = _from
self._subject = subject
self.attachment = attachment
def __enter__(self):
msg = MIMEMultipart()
for part in ['Subject', 'From', 'To']:
msg[part] = getattr(self, f'_{i.lower()}')
part = MIMEBase('application', "octet-stream")
part.set_payload(open(self.attachment, "rb").read())
Encoders.encode_base64(part)
part.add_header('Content-Disposition', f'attachment; filename="{self.attachment}"')
msg.attach(part)
server = smtplib.SMTP(self.EMAIL_SERVER)
server.sendmail(self.EMAIL_FROM, self.EMAIL_TO, msg.as_string())
return self
def __exit__(self, *args):
pass
#classmethod
def send_bulk(cls, users:list):
for date, name, email in users:
_d = datetime.datetime.now()
if _d.month in date and _d.day in date:
with cls(email, subject = f'Happy Birthday, {name}!') as f:
pass
with open('filename.csv') as f:
SendEmail.send_bulk(csv.reader(f))
New to python. Trying to send an email with attachment but keep receiving the following error:
AttributeError: module 'email.encoders' has no attribute
'endcode_base64'
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
print("Enter recipients addrss")
toaddr = input()
print("Enter senders addrss")
fromaddr = input()
msg = MIMEMultipart()
msg['From'] = fromaddr
msg['To'] = toaddr
print("Enter subjectline")
msg['Subject'] = input()
print("Type message")
body = input()
msg.attach(MIMEText(body, 'plain'))
Attach file: convert file to Base64 to send text files, pdf, images, audio and video files.
print("Enter name of file with its extension")
Enter 'none' if no attachments
print("Enter filename, No attachments? Enter none")
filename = input(" ")
if filename != "none":
print("Enter path of file")
attachment = open(input(), "rb")
part = MIMEBase("application", "octet-stream")
part.set_payload((attachment).read())
encoders.endcode_base64(part)
part.add_header('Content-Disposition',"attachment;filename= %s" %
filename)
msg.attach(part)
if toaddr.endswith(gmail):
mail= smtplib.SMTP('smtp.gmail.com',587)
mail.starttls()
mail.login(input(), input())
text = msg.as_string()
mail.sendmail(fromaddr, toaddr, text)
mail.close()
else:
if toaddr.endswith(outlook):
mail= smtplib.SMTP('smtp-mail.outlook.com',587)
mail.starttls()
mail.login(input(), input())
text = msg.as_string()
mail.sendmail(fromaddr, toaddr, text)
mail.close()
from email.MIMEMultipart import MIMEMultipart
from email.mime.application import MIMEApplication
from email.mime.text import MIMEText
from email.MIMEText import MIMEText
from email.MIMEImage import MIMEImage
from datetime import datetime
import socket
import email
import smtplib
import uuid
class EmailSender:
def __init__(self):
self.msgRoot = MIMEMultipart('related')
self.msgAlternative = MIMEMultipart('alternative')
self.msgRoot.attach(self.msgAlternative)
def AddImage(self, fileName, title):
internalFileName = '%s-%s-%s' %(fileName, datetime.now().strftime('%Y%m%d%H%M%S'), uuid.uuid4())
mimetext ='<p style="background-color:lightgrey;font-size:20px;font-weight:bold;font-family:Comic Sans MS">%s</p><br><img src="cid:%s"><br>' %(title, internalFileName)
msgText = MIMEText(mimetext, 'html')
self.msgAlternative.attach(msgText)
fp = open(fileName, 'rb')
msgImage = MIMEImage(fp.read())
fp.close()
msgImage.add_header('Content-ID', '<%s>' %(internalFileName))
self.msgRoot.attach(msgImage)
def AddFile(self, fileName):
fg = open(fileName, 'rb')
fA = MIMEApplication(fg.read(), Name=fileName)
fA['Content-Disposition'] = 'attachment; filename="%s"' %fileName
self.msgRoot.attach(fA)
This is my code of adding a image to the result email AddImage(). But when I invoke AddImage() for more than once, only the first image is shown in the result email?
Can you help find the problem?
The solution turns out to be:
def AddImage(self, fileName, title):
internalFileName = '%s-%s-%s' %(fileName, datetime.now().strftime('%Y%m%d%H%M%S'), uuid.uuid4())
self.imgHtml +='<p style="font-size:15px;font-weight:bold;font-family:Comic Sans MS">%s</p><br><img src="cid:%s"><br>' %(title, internalFileName)
fp = open(fileName, 'rb')
msgImage = MIMEImage(fp.read())
fp.close()
msgImage.add_header('Content-ID', '<%s>' %(internalFileName))
self.msgRoot.attach(msgImage)
def Send(self, toList):
msgText = MIMEText(self.imgHtml, 'html')
self.msgAlternative.attach(msgText)
self.msgRoot['Subject'] = 'Audience Ingestion Integrated Test Report #%s [%s]' %(datetime.now().strftime('%Y-%m-%d'), socket.gethostname())
strFrom = 'notifier#freewheel.tv'
self.msgRoot['From'] = strFrom
strTo = email.Utils.COMMASPACE.join(toList)
self.msgRoot['To'] = strTo
smtp = smtplib.SMTP('smtp1.dev.fwmrm.net', 25)
smtp.sendmail(strFrom, strTo, self.msgRoot.as_string())
smtp.quit()
which means that when AddImage(), just attach the MIMEImage to the MIMEMultipart and add the string to the html string, and when Send() after several invocations of AddImage(), attach the MIMEText generated from the html string to MIMEMultipart.
This code works but i am also trying to add text with each image but idk how to do that :
home = str(Path.home())
path = home + "\\Pictures"
list_of_images = glob( os.path.join(path, "*.png") )
mail = MIMEMultipart("related")
#Jinja2 for html template
main = Template('''
<html><body>
<h2>This is a Test email for python script</h2>
<br />
{% for image in pictures %}<p> $(name) </p><br /><img src="cid:{{image}}"><br />{% endfor %}
</body></html>''')
for filename in list_of_images:
fp = open(filename, 'rb')
msg_img = MIMEImage(fp.read())
fp.close()
msg_img.add_header('Content-ID', '<{}>'.format(filename))
msg_img.add_header('Content-Disposition', 'inline', filename=filename)
mail.attach(msg_img)
mail['Subject'] = "Python Script Test | You will receive this email every 30 minutes"
mail['From'] = me
mail['To'] = you
This was helpful for me.
What I found out that helped, after I have included (looped over) all the <img src="cid:%s"> use msgAlternative.as_string() and that fixed the issue. The issue being how it only included the first image now matter how many images I included.
I am trying to generate emails using the standard email library and save them as .eml files.
I must not be understanding how email.generator works because I keep getting the error 'AttributeError: 'str' object has no attribute 'write.'
from email import generator
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
active_dir = 'c:\\'
class Gen_Emails(object):
def __init__(self):
self.EmailGen()
def EmailGen(self):
sender = 'sender'
recepiant = 'recipiant'
subject = 'subject'
msg = MIMEMultipart('alternative')
msg['Subject'] = subject
msg['From'] = sender
msg['To'] = recepiant
html = """\
<html>
<head></head>
<body>
<p> hello world </p>
</body>
</html>
"""
part = MIMEText(html, 'html')
msg.attach(part)
self.SaveToFile(msg)
def SaveToFile(self,msg):
out_file = active_dir
gen = generator.Generator(out_file)
gen.flatten(msg)
Any ideas?
You are supposed to pass an open file (in write mode) to Generator(). Currently you pass it just a string, which is why it fails when it tries to call .write() on the string.
So do something like this:
import os
cwd = os.getcwd()
outfile_name = os.path.join(cwd, 'message.eml')
class Gen_Emails(object):
# ...
def SaveToFile(self,msg):
with open(outfile_name, 'w') as outfile:
gen = generator.Generator(outfile)
gen.flatten(msg)
Note: with open(outfile_name, 'w') as outfile opens the file at the path outfile_name in write mode and assigns the file pointer to the open file to outfile. The context manager also takes care of closing the file for you after you exit the with block.
os.path.join() will join paths in a cross-plattform way, which is why you should prefer it over concatenating paths by hand.
os.getcwd() will return your current working directory. If you want to your file to be saved somewhere else just change it out accordingly.
Here is a modified solution that works with extra headers too. (This was tested with Python 2.6)
import os
from email import generator
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
html_data = ...
msg = MIMEMultipart('alternative')
msg['Subject'] = ...
msg['From'] = ...
msg['To'] = ...
msg['Cc'] = ...
msg['Bcc'] = ...
headers = ... dict of header key / value pairs ...
for key in headers:
value = headers[key]
if value and not isinstance(value, basestring):
value = str(value)
msg[key] = value
part = MIMEText(html_data, 'html')
msg.attach(part)
outfile_name = os.path.join("/", "temp", "email_sample.eml")
with open(outfile_name, 'w') as outfile:
gen = generator.Generator(outfile)
gen.flatten(msg)
print "=========== DONE ============"