mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-18 05:51:26 +02:00
new: tinymce replaced by ckeditor (personal choice)
new: sending multipart/alternative messages when using the HTML editor (far from perfect...)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
.*~$
|
||||
^[^\.]+\.pyc
|
||||
static/tmp
|
||||
static/ckeditor
|
||||
static/js/ckeditor
|
||||
|
||||
@@ -86,7 +86,7 @@ WHERE quarantine.mail_id='%s'
|
||||
msg = email.message_from_string(content)
|
||||
links = request.GET.has_key("links") and request.GET["links"] or "0"
|
||||
mode = request.GET.has_key("mode") and request.GET["mode"] or "plain"
|
||||
mail = SQLemail(msg, mode, links)
|
||||
mail = SQLemail(msg, mformat=mode, links=links)
|
||||
return _render(request, "common/viewmail.html", {
|
||||
"headers" : mail.render_headers(),
|
||||
"mailbody" : mail.body
|
||||
|
||||
@@ -581,7 +581,7 @@ def find_images_in_body(body):
|
||||
|
||||
Before sending a message in HTML format, it is necessary to find
|
||||
all img tags contained in the body in order to rewrite them. For
|
||||
example, icons provided by tinyMCE are stored on the server
|
||||
example, icons provided by CKeditor are stored on the server
|
||||
filesystem and not accessible from the outside. We must embark
|
||||
them as parts off the MIME message if we want recipients to
|
||||
display them correctly.
|
||||
@@ -589,21 +589,27 @@ def find_images_in_body(body):
|
||||
:param body: the HTML body to parse
|
||||
"""
|
||||
from email.mime.image import MIMEImage
|
||||
from urlparse import urlparse
|
||||
|
||||
html = lxml.html.fromstring(body)
|
||||
parts = []
|
||||
for tag in html.iter("img"):
|
||||
src = tag.get("src")
|
||||
fname = os.path.basename(src)
|
||||
o = urlparse(src)
|
||||
dirname = os.path.dirname(o.path).replace(settings.MEDIA_URL, "")
|
||||
fname = os.path.basename(o.path)
|
||||
cid = "%s@modoboa" % os.path.splitext(fname)[0]
|
||||
tag.set("src", "cid:%s" % cid)
|
||||
|
||||
path = "%s/%s" % (settings.MODOBOA_DIR, re.sub("\.\./", "", src))
|
||||
path = os.path.join(settings.MEDIA_ROOT, dirname, fname)
|
||||
fp = open(path, "rb")
|
||||
p = MIMEImage(fp.read())
|
||||
fp.close()
|
||||
p["Content-ID"] = "<%s>" % cid
|
||||
ct = p["Content-Type"]
|
||||
p.replace_header("Content-Type", '%s; name="%s"' % (ct, fname))
|
||||
p.replace_header("Content-Type", '%s; name="%s"' \
|
||||
% (ct, os.path.basename(fname)))
|
||||
p["Content-Disposition"] = "inline"
|
||||
parts.append(p)
|
||||
|
||||
return lxml.html.tostring(html), parts
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
{% if body %}
|
||||
<textarea id="id_body" name="id_body" class="editor">{% if bodyheader %}{{ bodyheader }}{% endif %}
|
||||
{{ body }}
|
||||
</textarea>
|
||||
</textarea>
|
||||
{% else %}
|
||||
<textarea id="id_body" name="id_body" class="editor"></textarea>
|
||||
{% endif %}
|
||||
|
||||
@@ -68,6 +68,20 @@
|
||||
window.addEvent("resize", function(evt) {
|
||||
setDivHeight("id_body", $("mailheader").getSize().y, 0);
|
||||
});
|
||||
window.fireEvent("resize");
|
||||
|
||||
var editormode = resp.editor;
|
||||
var editorid = "id_body";
|
||||
if (editormode == "html") {
|
||||
var instance = CKEDITOR.instances[editorid];
|
||||
if (instance) {
|
||||
CKEDITOR.remove(instance);
|
||||
}
|
||||
CKEDITOR.replace(editorid, {
|
||||
customConfig: "{{ MEDIA_URL }}/js/editor_config.js",
|
||||
height: $(editorid).getSize().y
|
||||
});
|
||||
}
|
||||
$$("a[name=back]").addEvent("click", loadFolder);
|
||||
$$("a[name=sendmail]").addEvent("click", function(evt) {
|
||||
evt.stop();
|
||||
@@ -86,15 +100,11 @@
|
||||
current_anchor.update();
|
||||
}
|
||||
});
|
||||
tinyMCE.triggerSave();
|
||||
if (editormode == "html") {
|
||||
CKEDITOR.instances[editorid].updateElement();
|
||||
}
|
||||
$("composemail").send();
|
||||
});
|
||||
if (resp.editor == "html") {
|
||||
new Request({url: "{% url tinymce-js 'common' %}",
|
||||
onSuccess: function(resp) { eval(resp); }
|
||||
}).get();
|
||||
}
|
||||
window.fireEvent("resize");
|
||||
}
|
||||
|
||||
loadCompose = function(event) {
|
||||
|
||||
@@ -236,6 +236,16 @@ def render_compose(request, form, posturl, email=None, insert_signature=False):
|
||||
editor=editor)
|
||||
return HttpResponse(simplejson.dumps(ctx), mimetype="application/json")
|
||||
|
||||
def __html2plaintext(content):
|
||||
html = lxml.html.fromstring(content)
|
||||
plaintext = ""
|
||||
for p in html.xpath("//text()"):
|
||||
p = p.strip('\r\t\n')
|
||||
if p == "":
|
||||
continue
|
||||
plaintext += p + "\n"
|
||||
return plaintext
|
||||
|
||||
def send_mail(request, withctx=False, origmsg=None, posturl=None):
|
||||
form = ComposeMailForm(request.POST)
|
||||
error = None
|
||||
@@ -247,16 +257,23 @@ def send_mail(request, withctx=False, origmsg=None, posturl=None):
|
||||
|
||||
subtype = parameters.get_user(request.user, "EDITOR")
|
||||
body = request.POST["id_body"]
|
||||
charset = "utf-8"
|
||||
if subtype == "html":
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
|
||||
msg = MIMEMultipart(_subtype="related")
|
||||
submsg = MIMEMultipart(_subtype="alternative")
|
||||
textbody = __html2plaintext(body)
|
||||
submsg.attach(MIMEText(textbody.encode(charset),
|
||||
_subtype="plain", _charset=charset))
|
||||
body, images = find_images_in_body(body)
|
||||
msg.attach(MIMEText(body.encode("utf-8"), _subtype=subtype,
|
||||
_charset="utf-8"))
|
||||
submsg.attach(MIMEText(body.encode(charset), _subtype=subtype,
|
||||
_charset=charset))
|
||||
msg.attach(submsg)
|
||||
for img in images:
|
||||
msg.attach(img)
|
||||
else:
|
||||
msg = MIMEText(body.encode("utf-8"), _subtype=subtype)
|
||||
msg = MIMEText(body.encode(charset), _subtype=subtype)
|
||||
|
||||
msg["Subject"] = request.POST["subject"]
|
||||
msg["From"] = request.POST["from_"]
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
CKEDITOR.editorConfig = function(config) {
|
||||
config.toolbar = "Modoboa";
|
||||
config.toolbar_Modoboa = [
|
||||
['Bold','Italic','Underline'],
|
||||
['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],
|
||||
['NumberedList','BulletedList','-','Outdent','Indent'],
|
||||
['Undo','Redo'],
|
||||
['Link','Unlink','Anchor','-','Smiley'],
|
||||
['TextColor','BGColor','-','Source'],
|
||||
['Font','FontSize'],
|
||||
['SpellChecker']
|
||||
];
|
||||
};
|
||||
@@ -4,7 +4,7 @@
|
||||
{% block html_head %}
|
||||
<link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}css/searchbar.css" />
|
||||
<script type="text/javascript" src="{{ MEDIA_URL }}js/ProgressBar.js"></script>
|
||||
<script type="text/javascript" src="{{ MEDIA_URL }}js/tiny_mce/tiny_mce.js"></script>
|
||||
<script type="text/javascript" src="{{ MEDIA_URL }}js/ckeditor/ckeditor.js"></script>
|
||||
{% block css %}{% endblock %}
|
||||
<style type="text/css">
|
||||
#navbar {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{% load i18n %}
|
||||
<table id="emailheaders">
|
||||
{% for hdr in headers %}
|
||||
<tr><th width="130px">{{ hdr.name }}</th><td>{{ hdr.value }}</td></tr>
|
||||
<tr><th width="130px">{% trans hdr.name %}</th><td>{{ hdr.value }}</td></tr>
|
||||
{% endfor %}
|
||||
{% block extraheaders %}{% endblock %}
|
||||
</table>
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
tinyMCE.init({
|
||||
mode: "specific_textareas",
|
||||
editor_selector: "editor",
|
||||
theme: "advanced",
|
||||
plugins: "spellchecker,emotions",
|
||||
language: "{{ language }}",
|
||||
spellchecker_languages: "{{ spellchecker_languages }}",
|
||||
spellchecker_rpc_url: "{{ spellchecker_rpc_url }}",
|
||||
|
||||
theme_advanced_toolbar_location: "top",
|
||||
theme_advanced_toolbar_align: "left",
|
||||
theme_advanced_buttons1: "bold,italic,underline,separator,justifyleft,justifycenter,justifyright,justifyfull,separator,bullist,numlist,indent,outdent,separator,undo,redo,separator,link,unlink,emotions,forecolor,backcolor,code,|,fontselect,fontsizeselect,spellchecker",
|
||||
theme_advanced_buttons2: "",
|
||||
theme_advanced_buttons3: ""
|
||||
});
|
||||
Reference in New Issue
Block a user