diff --git a/demo/__init__.py b/demo/__init__.py new file mode 100755 index 000000000..f7adcb2e9 --- /dev/null +++ b/demo/__init__.py @@ -0,0 +1,30 @@ +# coding: utf-8 +from django.core.urlresolvers import reverse +from django.utils.translation import ugettext_noop as _ +from modoboa.lib import events +from modoboa.lib.webutils import static_url + +def menu(**kwargs): + import views + + if kwargs["target"] != "top_menu_middle": + return [] + return [ + {"name" : "demo", + "label" : _("Demo"), + "img" : static_url("pics/demo.png"), + "class" : "topdropdown", + "menu" : [ + {"name" : "sendvirus", + "label" : _("Send virus"), + "img" : static_url("pics/send-receive.png"), + "url" : reverse(views.send_virus)}, + {"name" : "sendspam", + "label" : _("Send spam"), + "img" : static_url("pics/send-receive.png"), + "url" : reverse(views.send_spam)} + ] + } + ] + +events.register("UserMenuDisplay", menu) diff --git a/demo/urls.py b/demo/urls.py new file mode 100644 index 000000000..74744ed5b --- /dev/null +++ b/demo/urls.py @@ -0,0 +1,6 @@ +from django.conf.urls.defaults import * + +urlpatterns = patterns('modoboa.demo.views', + (r'^sendvirus/$', 'send_virus'), + (r'^sendspam/$', 'send_spam'), + ) diff --git a/demo/views.py b/demo/views.py new file mode 100755 index 000000000..2fd7a952e --- /dev/null +++ b/demo/views.py @@ -0,0 +1,44 @@ +# coding: utf-8 +from django.contrib.auth.decorators import login_required +from modoboa.admin.lib import is_not_localadmin +from modoboa.lib.webutils import ajax_response +from modoboa.lib.emailutils import sendmail_simple + +@login_required +@is_not_localadmin() +def send_virus(request): + status, error = sendmail_simple("virus@evil.tld", request.user.username, """ +This is the EICAR testvirus pattern. + +X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H* + +It cannot harm your computer, but virus scanners +will detect and treat it as if it were a virus. +""") + if status: + return ajax_response(request) + return ajax_response(request, "ko", respmsg=error) + +@login_required +@is_not_localadmin() +def send_spam(request): + status, error = sendmail_simple("spam@evil.tld", request.user.username, """ +This is the GTUBE, the + Generic + Test for + Unsolicited + Bulk + Email + +If your spam filter supports it, the GTUBE provides a test by which you +can verify that the filter is installed correctly and is detecting incoming +spam. You can send yourself a test mail containing the following string of +characters (in upper case and with no white spaces and line breaks): + +XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X + +You should send this test mail from an account outside of your network. +""") + if status: + return ajax_response(request) + return ajax_response(request, "ko", respmsg=error) diff --git a/lib/emailutils.py b/lib/emailutils.py index 2a6f0102d..e913dd907 100644 --- a/lib/emailutils.py +++ b/lib/emailutils.py @@ -1,17 +1,20 @@ # coding: utf-8 import re -import email -from email.header import decode_header import lxml from django.template import Template, Context from django.template.loader import render_to_string import u2u_decode +import smtplib +from email.header import decode_header +from email.mime.text import MIMEText +from email.utils import make_msgid, formatdate, parseaddr +import time class EmailAddress(object): def __init__(self, address): self.fulladdress = u2u_decode.u2u_decode(address).strip("\r\t\n") - (self.name, self.address) = email.utils.parseaddr(self.fulladdress) + (self.name, self.address) = parseaddr(self.fulladdress) if self.name == "": self.fulladdress = self.address @@ -209,3 +212,32 @@ def decode(s, encodings=('utf8', 'latin1', 'windows-1252', 'ascii'), charset=Non except UnicodeDecodeError: pass return s.decode('ascii', 'ignore') + +def sendmail_simple(sender, rcpt, content=""): + """Simple way to send a text message + + Send a text/plain message with basic headers (msg-id, date). + + Return a tuple (True, None) on success, (False, error message) + otherwise. + + :param sender: sender address + :param rcpt: recipient address + :param content: message's content + :return: tuple + """ + msg = MIMEText(content) + msg["Subject"] = "Sample message" + msg["From"] = sender + msg["To"] = rcpt + msg["Message-ID"] = make_msgid() + msg["Date"] = formatdate(time.time(), True) + + try: + s = smtplib.SMTP() + s.connect() + s.sendmail(msg["From"], [rcpt], msg.as_string()) + s.quit() + except smtplib.SMTPException, e: + return False, "SMTP error: %s" % str(e) + return True, None diff --git a/lib/templatetags/libextras.py b/lib/templatetags/libextras.py index ed04ba605..6e6015743 100644 --- a/lib/templatetags/libextras.py +++ b/lib/templatetags/libextras.py @@ -3,6 +3,7 @@ import os from django.conf import settings from django import template from django.contrib import messages +from modoboa.lib import events from modoboa.lib.sysutils import exec_cmd register = template.Library() @@ -49,3 +50,9 @@ def display_messages(msgs): """ % (level, text) +@register.simple_tag +def load_optionalmenu(user): + menu = events.raiseQueryEvent("UserMenuDisplay", target="top_menu_middle", + user=user) + return template.loader.render_to_string('common/menulist.html', + {"entries" : menu, "user" : user}) diff --git a/static/js/common.js b/static/js/common.js index 7a5d462e9..77c5ba472 100644 --- a/static/js/common.js +++ b/static/js/common.js @@ -6,6 +6,22 @@ window.addEvent('domready', function(){ parent : $("menubar"), message : "Loading" }); + + /* Specific javascript code for the demo... not the best place */ + $$("a[name=sendspam], a[name=sendvirus]").addEvent("click", function(evt) { + evt.stop(); + new Request.JSON({ + url: this.get("href"), + onSuccess: function(response) { + if (response.status == "ok") { + infobox.info(gettext("Message sent")); + infobox.hide(1); + } else { + infobox.error(response.respmsg); + } + } + }).get(); + }); }); var media_url = ""; diff --git a/static/pics/demo.png b/static/pics/demo.png new file mode 100644 index 000000000..2f66cdebb Binary files /dev/null and b/static/pics/demo.png differ diff --git a/templates/nlayout.html b/templates/nlayout.html index 3b3d4bf1a..3e34463f8 100644 --- a/templates/nlayout.html +++ b/templates/nlayout.html @@ -1,6 +1,5 @@ {% load i18n %} -{% load admin_extras %} -{% load uprefs_extras %} +{% load admin_extras uprefs_extras libextras %} @@ -31,6 +30,7 @@ {% loadextmenu user %} {% options_menu user %} {% admin_menu user %} + {% load_optionalmenu user %}
diff --git a/urls.py b/urls.py index 351a141c7..b8d4e9658 100644 --- a/urls.py +++ b/urls.py @@ -14,6 +14,7 @@ urlpatterns = patterns('', (r'^%s$' % prefix, 'modoboa.lib.webutils.topredirection'), (r'^%sadmin/' % prefix, include('modoboa.admin.urls')), (r'^%suserprefs/' % prefix, include('modoboa.userprefs.urls')), + (r'^%sdemo/' % prefix, include('modoboa.demo.urls')), (r'^accounts/login/$', 'modoboa.auth.views.dologin'), (r'^accounts/logout/$', 'modoboa.auth.views.dologout'), (r'^jsi18n/$', 'django.views.i18n.javascript_catalog',