I am generating a bunch of html emails in django, and I want to save them into a model, in a FileField. I can quite easily generate the html content and dump in into a File, but I want to create something that can be opened in email clients, e.g. an eml file. Does anyone know of a python or django module to do this? Just to be clear, I'm not looking for an alternative email backend, as I also want the emails to be sent when they're generated.
Edit: After a bit of reading, it looks to me like the EmailMessage.messge() should return the content that should be stored int he eml file. However, if I try to save it like this, the file generated is empty:
import tempfile
name = tempfile.mkstemp()[1]
fh = open(name, 'wb')
fh.write(bytes(msg.message()))
fh.close()
output = File(open(name, 'rb'), msg.subject[:50])
I want to use a BytesIO instead of a temp file, but the temp file is easier for testing.
EML file is actually a text file with name value pairs. A valid EML file would be like
From: test#example.com
To: test#example.com
Subject: Test
Hello world!
If you follow the above pattern and save it in file with .eml extension, thunderbird like email clients will parse and show them without any problem.
Django's EmailMessage.message().as_bytes() will return the content of the .eml file. Then you just need to save the file to the directory of your choice:
from django.core.mail import EmailMessage
msg = EmailMessage(
'Hello',
'Body goes here',
'from#example.com',
['to3#example.com'],
)
eml_content = msg.message().as_bytes()
file_name = "/path/to/eml_output.eml"
with open(file_name, "wb") as outfile:
outfile.write(eml_content)
I had the similar problem. I found ticket on Django site. Last comment suggests using django-eml-email-backend. It helps me and it is very useful and simple.
Example:
installing:
$ pip install django-eml-email-backend
using:
EMAIL_BACKEND = 'eml_email_backend.EmailBackend'
EMAIL_FILE_PATH = 'path/to/output/folder/'
Related
I'm trying to parse a .eml file. The .eml has an excel attachment that's currently base 64 encoded. I'm trying to figure out how to decode it into XML so that I can later turn it into a CSV I can do stuff with.
This is my code right now:
import email
data = file('Openworkorders.eml').read()
msg = email.message_from_string(data)
for part in msg.walk():
c_type = part.get_content_type()
c_disp = part.get('Content Disposition')
if part.get_content_type() == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
excelContents = part.get_payload(decode = True)
print excelContents
The problem is
When I try to decode it, it spits back something looking like this.
I've used this post to help me write the code above.
How can I get an email message's text content using Python?
Update:
This is exactly following the post's solution with my file, but part.get_payload() returns everything still encoded. I haven't figured out how to access the decoded content this way.
import email
data = file('Openworkorders.eml').read()
msg = email.message_from_string(data)
for part in msg.walk():
if part.get_content_type() == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
name = part.get_param('name') or 'MyDoc.doc'
f = open(name, 'wb')
f.write(part.get_payload(None, True))
f.close()
print part.get("content-transfer-encoding")
As is clear from this table (and as you have already concluded), this file is an .xlsx. You can't just decode it with unicode or base64: you need a special package. Excel files specifically are a bit tricker (for e.g. this one does PowerPoint and Word, but not Excel). There are a few online, see here - xlrd might be the best.
Here is my solution:
I found 2 things out:
1.) I thought .open() was going inside the .eml and changing the selected decoded elements. I thought I needed to see decoded data before moving forward. What's really happening with .open() is it's creating a new file in the same directory of that .xlsx file. You must open the attachment before you will be able to deal with the data.
2.) You must open an xlrd workbook with the file path.
import email
import xlrd
data = file('EmailFileName.eml').read()
msg = email.message_from_string(data) # entire message
if msg.is_multipart():
for payload in msg.get_payload():
bdy = payload.get_payload()
else:
bdy = msg.get_payload()
attachment = msg.get_payload()[1]
# open and save excel file to disk
f = open('excelFile.xlsx', 'wb')
f.write(attachment.get_payload(decode=True))
f.close()
xls = xlrd.open_workbook(excelFilePath) # so something in quotes like '/Users/mymac/thisProjectsFolder/excelFileName.xlsx'
# Here's a bonus for how to start accessing excel cells and rows
for sheets in xls.sheets():
list = []
for rows in range(sheets.nrows):
for col in range(sheets.ncols):
list.append(str(sheets.cell(rows, col).value))
I'm using O365 for Python.
Sending an email and building the body my using the setBodyHTML() function. However at the present I need to write the actual HTML code inside the function. I don't want to do that. I want to just have python look at an HTML file I saved somewhere and send an email using that file as the body. Is that possible? Or am I confined to copy/pasting my HTML into that function? I'm using office365 for business. Thanks.
In other words instead of this: msg.setBodyHTML("<h3>Hello</h3>") I want to be able to do this: msg.setBodyHTML("C:\somemsg.html")
I guess you can assign the file content to a variable first, i.e.:
file = open('C:/somemsg.html', 'r')
content = file.read()
file.close()
msg.setBodyHTML(content)
You can do this via a simple reading of that file into a string, which you then can pass to the setBodyHTML function.
Here's a quick function example that will do the trick:
def load_html_from_file(path):
contents = ""
with open(path, 'r') as f:
contents = f.read()
return contents
Later, you can do something along the lines of
msg.setBodyHTML(load_html_from_file("C:\somemsg.html"))
or
html_contents = load_html_from_file("C:\somemsg.html")
msg.setBodyHTML(html_contents)
I am writing an application that creates a midi file using the MIDIUtil library. When the user submits an HTML form, a midi file object is created with MIDIUtil. How do I allow the user to download this as a .mid file? I have tried the following code, but I end up downloading a file of 0 bytes.
return Response(myMIDIFile, mimetype='audio/midi')
I use a variant of the following code to allow my users to download images they generate. The below code should work for you. Please note that you will most likely need to specify the full server path to the file being downloaded.
from flask import send_file
download_filename = FULL_PATH_TO_YOUR_MIDI_FILE
return(send_file(filename_or_fp = download_filename,mimetype="audio/midi",as_attachment=True))
I ended up using this, and it worked.
new_file = open('test.mid', 'wb')
myMIDI.writeFile(new_file)
new_file.close()
new_file = open('test.mid', 'rb')
return send_file(new_file, mimetype='audio/midi')
Might want to just try using send_file
from flask import send_file
return send_file("yourmidifile.mid", as_attachement=True, mimetype="audio\midi")
I am working on a function that sends emails with an attachment in PYTHON. In order to attach the file, I have to put it with the complete URL from the server, but the name of the file includes the hole URL. How can extrac only the filename from the URL.
I get the file from this URL:
/var/www/RH/HV/FILE.doc
And I want the attachment to appear
FILE.doc
here is the part of the code where i think the instructions should be added...
#adjunto
adjunto = MIMEBase('application', "octet-stream")
adjunto.set_payload(open(file, "rb").read())
encode_base64(adjunto)
adjunto.add_header('Content-Disposition', 'attachment; filename= "%s"' % file)
msg.attach(adjunto)
I hope someone could help!
THKS!!!
Use os.path.basename():
import os.path
p = '/var/www/RH/HV/FILE.doc'
print os.path.basename(p)
This assumes you're working with normal file paths, not URLs. But based on the question it looks like you're not looking at URLs.
I am learning Python/Django and my pet project is a photo sharing website. I would like to give users the ability to upload their photos using an email address like Posterous, Tumblr. Research has led me to believe I need to use the following:
-- cron job
-- python mail parser
-- cURL or libcurl
-- something that updates my database
How all these parts will work together is still where I need clarification. I know the cron will run a script that parses the email (sounds simple when reading), but how to get started with all these things is daunting. Any help in pointing me in the right direction, tutorials, or an answer would be greatly appreciated.
Read messages from maildir. It's not optimized but show how You can parse emails. Of course you should store information about files and users to database. Import models into this code and make right inserts.
import mailbox
import sys
import email
import os
import errno
import mimetypes
mdir = mailbox.Maildir(sys.argv [1], email.message_from_file)
for mdir_msg in mdir:
counter = 1
msg = email.message_from_string(str(mdir_msg))
for part in msg.walk():
# multipart/* are just containers
if part.get_content_maintype() == 'multipart':
continue
# Applications should really sanitize the given filename so that an
# email message can't be used to overwrite important files
filename = part.get_filename()
if not filename:
ext = mimetypes.guess_extension(part.get_content_type())
if not ext:
# Use a generic bag-of-bits extension
ext = '.bin'
filename = 'part-%03d%s' % (counter, ext)
counter += 1
fp = open(os.path.join('kupa', filename), 'wb')
fp.write(part.get_payload(decode=True))
fp.close()
#photomodel imported from yourapp.models
photo = PhotoModel()
photo.name = os.path.join('kupa', filename)
photo.email = ....
photo.save()
Not sure what you need cURL for in that list - what's it supposed to be doing?
You don't really say where you're having trouble. It seems to me you can do all this in a Django management command, which can be triggered on a regular cron. The standard Python library contains everything you need to access the mailbox (smtplib) and parse the message to get the image (email and email.message). The script can then simply save the image file to the relevant place on disk, and create a matching entry in the database via the normal Django ORM.