"""Process subscription or roster requests from listinfo form."""
import sys
import os
import cgi
import signal
from Mailman import mm_cfg
from Mailman import Utils
from Mailman import MailList
from Mailman import Errors
from Mailman import i18n
from Mailman import Message
from Mailman.UserDesc import UserDesc
from Mailman.htmlformat import *
from Mailman.Logging.Syslog import syslog
SLASH = '/'
ERRORSEP = '\n\n<p>'
_ = i18n._
i18n.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE)
def main():
doc = Document()
doc.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE)
parts = Utils.GetPathPieces()
if not parts:
doc.AddItem(Header(2, _("Error")))
doc.AddItem(Bold(_('Invalid options to CGI script')))
print doc.Format()
return
listname = parts[0].lower()
try:
mlist = MailList.MailList(listname, lock=0)
except Errors.MMListError, e:
safelistname = Utils.websafe(listname)
doc.AddItem(Header(2, _("Error")))
doc.AddItem(Bold(_('No such list <em>%(safelistname)s</em>')))
print doc.Format()
syslog('error', 'No such list "%s": %s\n', listname, e)
return
cgidata = cgi.FieldStorage()
language = cgidata.getvalue('language')
if not Utils.IsLanguage(language):
language = mlist.preferred_language
i18n.set_language(language)
doc.set_language(language)
def sigterm_handler(signum, frame, mlist=mlist):
mlist.Unlock()
sys.exit(0)
mlist.Lock()
try:
signal.signal(signal.SIGTERM, sigterm_handler)
process_form(mlist, doc, cgidata, language)
mlist.Save()
finally:
mlist.Unlock()
def process_form(mlist, doc, cgidata, lang):
listowner = mlist.GetOwnerEmail()
realname = mlist.real_name
results = []
email = cgidata.getvalue('email', '')
if not email:
results.append(_('You must supply a valid email address.'))
fullname = cgidata.getvalue('fullname', '')
fullname = Utils.canonstr(fullname, lang)
remote = os.environ.get('REMOTE_HOST',
os.environ.get('REMOTE_ADDR',
'unidentified origin'))
if email == mlist.GetListEmail():
syslog('mischief', 'Attempt to self subscribe %s: %s', email, remote)
results.append(_('You may not subscribe a list to itself!'))
password = cgidata.getvalue('pw')
confirmed = cgidata.getvalue('pw-conf')
if password is None and confirmed is None:
password = Utils.MakeRandomPassword()
elif password is None or confirmed is None:
results.append(_('If you supply a password, you must confirm it.'))
elif password <> confirmed:
results.append(_('Your passwords did not match.'))
digestflag = cgidata.getvalue('digest')
if digestflag:
try:
digest = int(digestflag)
except ValueError:
digest = 0
else:
digest = mlist.digest_is_default
if not mlist.digestable:
digest = 0
elif not mlist.nondigestable:
digest = 1
if results:
print_results(mlist, ERRORSEP.join(results), doc, lang)
return
if mlist.private_roster == 0:
privacy_results = ''
else:
privacy_results = _("""\
Your subscription request has been received, and will soon be acted upon.
Depending on the configuration of this mailing list, your subscription request
may have to be first confirmed by you via email, or approved by the list
moderator. If confirmation is required, you will soon get a confirmation
email which contains further instructions.""")
try:
userdesc = UserDesc(email, fullname, password, digest, lang)
mlist.AddMember(userdesc, remote)
results = ''
except Errors.MembershipIsBanned:
results = _("""The email address you supplied is banned from this
mailing list. If you think this restriction is erroneous, please
contact the list owners at %(listowner)s.""")
except Errors.MMBadEmailError:
results = _("""\
The email address you supplied is not valid. (E.g. it must contain an
`@'.)""")
except Errors.MMHostileAddress:
results = _("""\
Your subscription is not allowed because the email address you gave is
insecure.""")
except Errors.MMSubscribeNeedsConfirmation:
if privacy_results:
results = privacy_results
else:
results = _("""\
Confirmation from your email address is required, to prevent anyone from
subscribing you without permission. Instructions are being sent to you at
%(email)s. Please note your subscription will not start until you confirm
your subscription.""")
except Errors.MMNeedApproval, x:
if privacy_results:
results = privacy_results
else:
x = _(str(x))
results = _("""\
Your subscription request was deferred because %(x)s. Your request has been
forwarded to the list moderator. You will receive email informing you of the
moderator's decision when they get to your request.""")
except Errors.MMAlreadyAMember:
if not privacy_results:
results = _('You are already subscribed.')
else:
results = privacy_results
listaddr = mlist.GetListEmail()
mlang = mlist.getMemberLanguage(email)
otrans = i18n.get_translation()
i18n.set_language(mlang)
try:
msg = Message.UserNotification(
mlist.getMemberCPAddress(email),
mlist.GetBouncesEmail(),
_('Mailman privacy alert'),
_("""\
An attempt was made to subscribe your address to the mailing list
%(listaddr)s. You are already subscribed to this mailing list.
Note that the list membership is not public, so it is possible that a bad
person was trying to probe the list for its membership. This would be a
privacy violation if we let them do this, but we didn't.
If you submitted the subscription request and forgot that you were already
subscribed to the list, then you can ignore this message. If you suspect that
an attempt is being made to covertly discover whether you are a member of this
list, and you are worried about your privacy, then feel free to send a message
to the list administrator at %(listowner)s.
"""), lang=mlang)
finally:
i18n.set_translation(otrans)
msg.send(mlist)
except Errors.MMCantDigestError:
results = _('This list does not support digest delivery.')
except Errors.MMMustDigestError:
results = _('This list only supports digest delivery.')
else:
if privacy_results:
results = privacy_results
else:
results = _("""\
You have been successfully subscribed to the %(realname)s mailing list.""")
print_results(mlist, results, doc, lang)
def print_results(mlist, results, doc, lang):
doc.suppress_head = 1
replacements = mlist.GetStandardReplacements(lang)
replacements['<mm-results>'] = results
output = mlist.ParseTags('subscribe.html', replacements, lang)
doc.AddItem(output)
print doc.Format()