/usr/lib/python2.7/dist-packages/mailmanapi/api.py is in mailman-api 0.2.9-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | import os
import uuid
import logging
from bottle import route, request, template, default_app
try:
from Mailman import Utils, Errors, Post, mm_cfg
except ImportError:
logging.error('Could not import Mailman module')
from .members import Member
from .utils import parse_boolean, jsonify, get_mailinglist, get_timestamp
CWD = os.path.abspath(os.path.dirname(__file__))
EMAIL_TEMPLATE = os.path.join(CWD, 'templates', 'message.tpl')
@route('/', method='GET')
def list_lists():
"""Lists existing mailing lists on the server.
**Method**: GET
**URI**: /
Returns a list of the mailing lists that exist on this server."""
all_lists = Utils.list_names()
lists = []
include_description = request.query.get('description')
address = request.query.get('address')
for listname in all_lists:
mlist = get_mailinglist(listname, lock=False)
members = mlist.getMembers()
if not address or address in members:
if include_description:
lists.append((listname, mlist.description.decode('latin1')))
else:
lists.append(listname)
return jsonify(lists)
@route('/<listname>', method='PUT')
def subscribe(listname):
"""Adds a new subscriber to the list called `<listname>`
**Method**: PUT
**URI**: /<listname>
**Parameters**:
* `address`: email address that is to be subscribed to the list.
* `fullname`: full name of the person being subscribed to the list.
* `digest`: if this equals `true`, the new subscriber will receive
digests instead of every mail sent to the list.
"""
address = request.forms.get('address')
fullname = request.forms.get('fullname')
digest = parse_boolean(request.forms.get('digest'))
mlist = get_mailinglist(listname)
userdesc = Member(fullname, address, digest)
try:
mlist.ApprovedAddMember(userdesc, ack=True, admin_notif=True)
except Errors.MMAlreadyAMember:
return jsonify("Address already a member.", 409)
except Errors.MembershipIsBanned:
return jsonify("Banned address.", 403)
except (Errors.MMBadEmailError, Errors.MMHostileAddress):
return jsonify("Invalid address.", 400)
else:
mlist.Save()
finally:
mlist.Unlock()
return jsonify(True)
@route('/<listname>', method='DELETE')
def unsubscribe(listname):
"""Unsubsribe an email address from the mailing list.
**Method**: DELETE
**URI**: /<listname>
**Parameters**:
* `address`: email address that is to be unsubscribed from the list
"""
address = request.forms.get('address')
mlist = get_mailinglist(listname)
try:
mlist.ApprovedDeleteMember(address, admin_notif=False, userack=True)
mlist.Save()
except Errors.NotAMemberError:
return jsonify("Not a member.", 404)
finally:
mlist.Unlock()
return jsonify(True)
@route('/<listname>', method='GET')
def members(listname):
"""Lists subscribers for the `listname` list.
**Method**: GET
**URI**: /<listname>
Returns an array of email addresses."""
mlist = get_mailinglist(listname, lock=False)
return jsonify(mlist.getMembers())
@route('/<listname>/sendmail', method='POST')
def sendmail(listname):
"""Posts an email to the mailing list.
**Method**: POST
**URI**: /<listname>/sendmail
**Parameters**:
* `name_from`: name of the poster
* `email_from`: email address of the poster
* `subject`: the subject of the message
* `body`: the body of the message.
* `in_reply_to` (optional): Message-ID of the message that is being
replied to, if any."""
mlist = get_mailinglist(listname, lock=False)
context = {}
context['email_to'] = mlist.GetListEmail()
context['message_id'] = uuid.uuid1()
context['ip_from'] = request.environ.get('REMOTE_ADDR')
context['timestamp'] = get_timestamp()
context['name_from'] = request.forms.get('name_from')
context['email_from'] = request.forms.get('email_from')
context['subject'] = request.forms.get('subject')
context['body'] = request.forms.get('body')
in_reply_to = request.forms.get('in_reply_to')
if in_reply_to:
context['in_reply_to'] = in_reply_to
if None in context.values():
return jsonify('Missing information. `email_from`, `subject` and '
'`body` are mandatory', 400)
email = template(EMAIL_TEMPLATE, context)
Post.inject(listname, email.encode('utf8'), qdir=mm_cfg.INQUEUE_DIR)
return jsonify(True)
def get_application(allowed_ips):
bottle_app = default_app()
def application(environ, start_response):
if environ['REMOTE_ADDR'] not in allowed_ips:
status = '403 FORBIDDEN'
headers = [('Content-type', 'text/plain')]
start_response(status, headers)
return 'FORBIDDEN'
return bottle_app(environ, start_response)
return application
|