# HG changeset patch
# User Sylvain Thénault <sylvain.thenault@logilab.fr>
# Date 1384354573 -3600
# Wed Nov 13 15:56:13 2013 +0100
# Node ID 24c0a2fb624e7a38cc022164f2dcd1f7d2237e62
# Parent 1865d9c595a7c0fdc703ebb2922398eaeb0542f9
allow to specify sender (both 'From' header and helo_addr)
# User Sylvain Thénault <sylvain.thenault@logilab.fr>
# Date 1384354573 -3600
# Wed Nov 13 15:56:13 2013 +0100
# Node ID 24c0a2fb624e7a38cc022164f2dcd1f7d2237e62
# Parent 1865d9c595a7c0fdc703ebb2922398eaeb0542f9
allow to specify sender (both 'From' header and helo_addr)
@@ -63,11 +63,11 @@
1 self.vreg['controllers'].select, 'sendmail', self.request()) 2 3 def test_controller_admin(self): 4 self.user().cw_set(firstname=u'Sÿt', surname=u'Thénault') 5 rset = self.execute('CWUser X') 6 - req = self.request(subject='tôtô', 7 + req = self.request(subject='tôtô', sender=u'S. Thénô <stheno@dactylo.fr>', 8 recipient=[str(eid) for eid, in rset], 9 mailbody='hôp %(firstname)s %(surname)s') 10 ctrl = self.vreg['controllers'].select('sendmail', req) 11 with self.assertRaises(Redirect) as cm: 12 ctrl.publish()
@@ -76,10 +76,12 @@
13 self.assertEqual(len(testlib.MAILBOX), len(rset)) 14 email = [mail for mail in testlib.MAILBOX 15 if mail.recipients == ['admin@cubicweb.org']][0] 16 self.assertEqual(email.content, u'hôp Sÿt Thénault') 17 self.assertEqual(u'tôtô', email.subject) 18 + self.assertEqual(u'S. Thénô <stheno@dactylo.fr>', email.helo_addr) 19 + self.assertEqual(u'S. Thénô <stheno@dactylo.fr>', email.message['From']) 20 21 22 if __name__ == '__main__': 23 from logilab.common.testlib import unittest_main 24 unittest_main()
@@ -19,15 +19,17 @@
25 26 __docformat__ = "restructuredtext en" 27 _ = unicode 28 29 import operator 30 +import re 31 from functools import reduce 32 33 from cubicweb.predicates import (is_instance, authenticated_user, 34 adaptable, match_form_params) 35 from cubicweb.view import EntityView 36 +from cubicweb.mail import format_mail 37 from cubicweb.web import (Redirect, stdmsgs, controller, action, 38 form, formfields as ff) 39 from cubicweb.web.formwidgets import CheckBox, TextInput, AjaxWidget, ImgButton 40 from cubicweb.web.views import forms, formrenderers 41
@@ -62,22 +64,26 @@
42 needs_js = ('cubicweb.edition.js', 'cubicweb.widgets.js',) 43 needs_css = ('cubicweb.mailform.css') 44 domid = 'sendmail' 45 action = 'sendmail' 46 47 - sender = ff.StringField(widget=TextInput({'disabled': 'disabled'}), 48 - label=_('From:'), 49 - value=lambda form, field: '%s <%s>' % ( 50 - form._cw.user.dc_title(), 51 - form._cw.user.cw_adapt_to('IEmailable').get_email())) 52 - recipient = ff.StringField(widget=CheckBox(), label=_('Recipients:'), 53 - choices=recipient_vocabulary, 54 - value= lambda form, field: [entity.eid for entity in form.cw_rset.entities() 55 - if entity.cw_adapt_to('IEmailable').get_email()]) 56 - subject = ff.StringField(label=_('Subject:'), max_length=256) 57 - mailbody = ff.StringField(widget=AjaxWidget(wdgtype='TemplateTextField', 58 - inputid='mailbody')) 59 + sender = ff.StringField( 60 + label=_('From:'), 61 + value=lambda form, field: '%s <%s>' % ( 62 + form._cw.user.name(), 63 + form._cw.user.cw_adapt_to('IEmailable').get_email()), 64 + max_length=256) 65 + recipient = ff.StringField( 66 + widget=CheckBox(), label=_('Recipients:'), 67 + choices=recipient_vocabulary, 68 + value=lambda form, field: [e.eid for e in form.cw_rset.entities() 69 + if e.cw_adapt_to('IEmailable').get_email()]) 70 + subject = ff.StringField( 71 + label=_('Subject:'), max_length=256) 72 + mailbody = ff.StringField( 73 + widget=AjaxWidget(wdgtype='TemplateTextField', 74 + inputid='mailbody')) 75 76 form_buttons = [ImgButton('sendbutton', "javascript: $('#sendmail').submit()", 77 _('send email'), 'SEND_EMAIL_ICON'), 78 ImgButton('cancelbutton', "javascript: history.back()", 79 _(stdmsgs.BUTTON_CANCEL[0]), stdmsgs.BUTTON_CANCEL[1])]
@@ -150,11 +156,12 @@
80 form.render(w=self.w) 81 82 83 class SendMailController(controller.Controller): 84 __regid__ = 'sendmail' 85 - __select__ = authenticated_user() & match_form_params('recipient', 'mailbody', 'subject') 86 + __select__ = authenticated_user() & match_form_params( 87 + 'sender', 'recipient', 'mailbody', 'subject') 88 89 def recipients(self): 90 """returns an iterator on email's recipients as entities""" 91 eids = self._cw.form['recipient'] 92 # eids may be a string if only one recipient was specified
@@ -163,15 +170,21 @@
93 else: 94 rset = self._cw.execute('Any X WHERE X eid in (%s)' % (','.join(eids))) 95 return rset.entities() 96 97 def publish(self, rset=None): 98 - # XXX this allows users with access to an cubicweb instance to use it as 99 - # a mail relay 100 - body = self._cw.form['mailbody'] 101 - subject = self._cw.form['subject'] 102 + req = self._cw 103 + sender = req.form['sender'] 104 + text = req.form['mailbody'] 105 + subject = req.form['subject'] 106 for recipient in self.recipients(): 107 iemailable = recipient.cw_adapt_to('IEmailable') 108 - text = body % iemailable.as_email_context() 109 - self.sendmail(iemailable.get_email(), subject, text) 110 - url = self._cw.build_url(__message=self._cw._('emails successfully sent')) 111 + body = text % iemailable.as_email_context() 112 + recipient = iemailable.get_email() 113 + uinfo = re.match(ur'(?P<name>.+) <(?P<email>.+)>', sender, re.U).groupdict() 114 + msg = format_mail(uinfo, [recipient], body, subject) 115 + if not req.vreg.config.sendmails([(msg, [recipient])], sender): 116 + msg = req._('could not connect to the SMTP server') 117 + url = req.build_url(__message=msg) 118 + raise Redirect(url) 119 + url = req.build_url(__message=req._('emails successfully sent')) 120 raise Redirect(url)