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:
tonio
2010-09-17 17:17:40 +02:00
parent c01d6de7d8
commit ac47357f45
11 changed files with 65 additions and 35 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
.*~$
^[^\.]+\.pyc
static/tmp
static/ckeditor
static/js/ckeditor
+1 -1
View File
@@ -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
+10 -4
View File
@@ -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
+1 -1
View File
@@ -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 %}
+17 -7
View File
@@ -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) {
+20 -3
View File
@@ -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_"]
+13
View File
@@ -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']
];
};
+1 -1
View File
@@ -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 -1
View File
@@ -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>
-15
View File
@@ -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: ""
});
-1
View File
@@ -10,7 +10,6 @@ urlpatterns = patterns('',
(r'^accounts/logout/$', 'modoboa.auth.views.dologout'),
(r'^jsi18n/$', 'django.views.i18n.javascript_catalog',
{'packages': ('modoboa',),}),
(r'^tinymce/', include('tinymce.urls')),
*loadextensions()
)