Short description
Currently, when MoinMoin sends email, it sends it by putting effective address into bcc-field and using the same value for both from and to (mail_from in wikiconfig.py).
It should rather use receivers address in to field. Problem is that it cannot be told from received email which address was used to deliver it.
Current solution has two advantages, 1) send only one email and 2) do not disclose user email addresses.
Obviously this requires multiple emails to be sent to maintain 2).
From source code POV, this can be accomplished simply by running a for loop in mail/sendmail.py. This of course loses 1) but IMHO it's not that important.
Current interface returns true/false for success of mailing. While running for loop, it can be counted how many mails were successfully sent and how many failed. Sending process should probably be considered failure only if no mails could be transferred.
The change seems to touch about 25 lines of code. The attached diff shows changed lines (diff -bBu).
1 --- moin-1.6.0/MoinMoin/mail/sendmail.py 2007-10-26 00:40:26.000000000 +0300
2 +++ moin/modatut/sendmail.py 2008-04-04 01:02:50.000000000 +0300
3 @@ -84,7 +84,7 @@
4
5 # Create message headers
6 # Don't expose emails addreses of the other subscribers, instead we
7 - # use the same mail_from, e.g. u"Jürgen Wiki <noreply@mywiki.org>"
8 + # send each email invidually
9 address = encodeAddress(mail_from, charset)
10 msg['From'] = address
11 msg['To'] = address
12 @@ -92,12 +92,13 @@
13 msg['Message-ID'] = make_msgid()
14 msg['Subject'] = Header(subject, charset)
15
16 - if cfg.mail_sendmail:
17 - # Set the BCC. This will be stripped later by sendmail.
18 - msg['BCC'] = ','.join(to)
19 - # Set Return-Path so that it isn't set (generally incorrectly) for us.
20 - msg['Return-Path'] = address
21 -
22 + sent_ok = 0
23 + sent_fail = 0
24 + sent_fail_msg = "OK"
25 +
26 + for subscriber in to:
27 + del msg['To']
28 + msg['To'] = subscriber
29 # Send the message
30 if not cfg.mail_sendmail:
31 try:
32 @@ -115,7 +116,8 @@
33 except:
34 pass
35 server.login(user, pwd)
36 - server.sendmail(mail_from, to, msg.as_string())
37 + server.sendmail(mail_from, subscriber, msg.as_string())
38 + sent_ok+=1
39 finally:
40 try:
41 server.quit()
42 @@ -123,12 +125,14 @@
43 # in case the connection failed, SMTP has no "sock" attribute
44 pass
45 except smtplib.SMTPException, e:
46 - return (0, str(e))
47 + sent_fail+=1
48 + sent_fail_msg=str(e)
49 except (os.error, socket.error), e:
50 - return (0, _("Connection to mailserver '%(server)s' failed: %(reason)s", formatted=False) % {
51 + sent_fail+=1
52 + sent_fail_msg = _("Connection to mailserver '%(server)s' failed: %(reason)s", formatted=False) % {
53 'server': cfg.mail_smarthost,
54 'reason': str(e)
55 - })
56 + }
57 else:
58 try:
59 sendmailp = os.popen(cfg.mail_sendmail, "w")
60 @@ -136,9 +140,20 @@
61 sendmailp.write(msg.as_string())
62 sendmail_status = sendmailp.close()
63 if sendmail_status:
64 - return (0, str(sendmail_status))
65 + sent_fail+=1
66 + sent_fail_msg=str(sendmail_status)
67 + else:
68 + sent_ok+=1
69 except:
70 - return (0, _("Mail not sent", formatted=False))
71 + sent_fail+=1
72 + sent_fail_msg=_("Mail not sent", formatted=False)
73 +
74 + if sent_ok==0:
75 + return (0, _("%(ok)s messages ok, %(fail)s failed, last %(msg)s", formatted=False) % {
76 + 'fail' : sent_fail,
77 + 'ok' : sent_ok,
78 + 'msg' : sent_fail_msg
79 + })
80
81 return (1, _("Mail sent OK", formatted=False))
82