| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
removing the module. Then, fix a few tests that failed as a result of
this work.
Mailman/Handlers/Hold.py: Call hold_message() instead of
mlist.HoldMessage().
The message store also no longer requires a Date: header, so clean up
a few tests that were still expecting that.
Extend cleaning_teardown() in test_documentation.py so that both the
message store and any list-centric requests are cleaned up after each
test.
|
| |
|
|
| |
modernization of Hold.py was performed.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
confident the Elixir branch is ready to become mainline. Also, fewer branches
makes for an easier migration to a dvcs.
Don't expect much of the old test suite to work, or even for much of the old
functionality to work. The changes here are disruptive enough to break higher
level parts of Mailman. But that's okay because I am slowly building up a new
and improved test suite, which will lead to a functional system again.
For now, only the doctests in Mailman/docs (and their related test harnesses)
will pass, but they all do pass. Note that Mailman/docs serve as system
documentation first and unit tests second. You should be able to read the
doctest files to understand the underlying data model.
Other changes included in this merge:
- Added the Mailman.ext extension package.
- zope.interfaces uses to describe major components
- SQLAlchemy/Elixir used as the database model
- Top level doinstall target renamed to justinstall
- 3rd-party packages are now installed in pythonlib/lib/python to be more
compliant with distutils standards. This allows us to use just --home
instead of all the --install-* options.
- No longer need to include the email package or pysqlite, as Python 2.5 is
required (and comes with both packages).
- munepy package is included, for Python enums
- IRosterSets are added as a way to manage a collection of IRosters. Roster
sets are named so that we can maintain the indirection between mailing lists
and rosters, where the two are maintained in different storages.
- IMailingListRosters: remove_*_roster() -> delete_*_roster()
- Remove IMember interface.
- Utils.list_names() -> config.list_manager.names
- fqdn_listname() takes an optional hostname argument.
- Added a bunch of new exceptions used throughout the new interfaces.
- Make LockFile a context manager for use with the 'with' statement.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
during early initialization so that we're guaranteed to get the right value
regardless of the shell umask used to invoke the command line script. While
we're at it, we can remove almost all individual umask settings previously in
the code, and make file permissions consistently -rw-rw---- (IOW, files are no
longer other readable).
The only subsystem that wasn't changed was the archiver, because it uses its
own umask settings to ensure that private archives have the proper
permissions. Eventually we'll mess with this, but if it ain't broken...
Note that check_perms complains about directory permissions, but I think
check_perms can be fixed (or perhaps, even removed?!). If we decide to use
LMTPRunner and HTTPRunner exclusively then no outside process will be touching
our files potentially with the incorrect permissions, umask, owner, or group.
If we control all of our own touch points then I think we can lock out
'other'.
Another open question is whether Utils.set_global_password() can have its
umask setting removed. It locks permissions down so even the group can't
write to the site password file, but the default umask of 007 might be good
enough even for this file.
Utils.makedirs() now takes an optional mode argument, which defaults to 02775
for backward compatibility. First, the default mode can probably be changed
to 02770 (see above). Second, all code that was tweaking the umask in order
to do a platform compatible os.mkdir() has now been refactored to use
Utils.makedirs().
Another tricky thing was getting SQLite via SQLAlchemy to create its
data/mailman.db file with the proper permissions. From the comment in
dbcontext.py:
# XXX By design of SQLite, database file creation does not honor
# umask. See their ticket #1193:
# http://www.sqlite.org/cvstrac/tktview?tn=1193,31
More details in that file, but the work around is to essentially 'touch' the
database file if 'sqlite' is the scheme of the SQLAlchemy URL. This little
pre-touch sets the right umask honoring permission and won't hurt if the file
already exists. SQLite will happily keep the existing permissions, and in
fact that ticket referenced above recommends doing things this way.
In the Mailman.database.initialize(), create a global lock that prevents more
than one process from entering this init function at the same time. It's
probably not strictly necessary given that I believe all the operations in
dbcontext.connect() are multi-processing safe, but it also doesn't seem to
hurt and prevents race conditions regardless of the database's own
safeguards (or lack thereof).
Make sure nightly_gzip.py calls initialize().
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
and fixing the invocation and shutdown of mailmanctl. While the tests in this
module work individually, they do not yet work as a group.
-C added to testall.py, and mailmanctl now passes that flag on to qrunner.
UserNotification sets reduced_list_header in the msgdata, but the behavior of
this flag has changed. It used to suppress List-Help, List-Subscribe, and
List-Unsubscribe as well as List-Post and List-Archive. However, List-Help,
List-Subscribe and List-Unsubscribe should definitely be included in
UserNotifications, and List-Post has a different variable controlling it now.
Therefore, always add List-Help, List-Subscribe, and List-Unsubscribe.
Some style updates to Message.py
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
traces of our crufty old Syslog. Most of this work was purely mechanical,
except for:
1) Initializing the loggers. For this, there's a new module
Mailman/loginit.py (yes all modules from now on will use PEP 8
names). We can't call this 'logging.py' because that will
interfere with importing the stdlib module of the same name (can
you say Python 2.5 and absolute imports?).
If you want to write log messages both to the log file and to
stderr, pass True to loginit.initialize(). This will turn on
propagation of log messages to the parent 'mailman' logger, which
is set up to print to stderr. This is how bin/qrunner works when
not running as a subprocess of mailmanctl.
2) The driver script. I had to untwist the StampedLogger stuff and
implement differently printing exceptions and such to log/error
because standard logging objects don't have a write() method. So
we write to a cStringIO and then pass that to the logger.
3) SMTPDirect.py because of the configurability of the log messages.
This required changing SafeDict into a dict subclass (which is
better than using UserDicts anyway -- yay Python 2.3!). It's
probably still possible to flummox things up if you change the
name of the loggers in the SMTP_LOG_* variables in mm_cfg.py.
However, the worst you can do is cause output to go to stderr and
not go to a log file.
Note too that all entry points into the Mailman system must call
Mailman.loginit.initialize() or the log output will go to stderr
(which may occasionally be what you want). Currently all CGIs and
qrunners should be working properly.
I wish I could have tested all code paths that touch the logger, but
that's infeasible. I have tested this, but it's possible that there
were some mistakes in the translation.
- Mailman.Bouncers.BounceAPI.Stop is a singleton, but not a class
instance any more.
- True/False code cleanup, PEP 8 import restructuring, whitespace
normalization, and copyright year updates, as appropriate.
|
| |
|
|
|
|
|
|
|
|
|
| |
- Remove True/False binding cruft
- Remove __future__ statements for nested scopes
- Remove ascii_letters import hack from Utils.py
- Remove mimetypes.guess_all_extensions import hack from Scrubber.py
- In Pending.py, set _missing to object() (better than using [])
Also, update copyright years where appropriate, and re-order imports more to
my PEP 8 tastes. Whitespace normalize.
|
| | |
|
| | |
|
| |
|
|
|
| |
lower than the highest entry in the list config.db, so the assertion was
being triggered. We can just deal with the problem instead.
|
| |
|
|
|
|
|
|
| |
MM2.1. Specifically,
__opendb(): The on-the-fly conversion of db entries had two bugs:
First, it was comparing the id instead of the entry type. Second, it
wasn't aware of len==4 SUBSCRIPTION entries.
|
| |
|
|
| |
Les Niles.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
page has a comma separated list of addresses. Do a better job of
splitting this field up and forwarding a copy to each address.
One nit: if the forward to address is a single member address, we try
to set the language to that member's preference. If we're looking at
a list of addresses though, it think it makes most sense to use the
list's preferred language.
Closes SF bug #577919.
|
| |
|
|
|
| |
forwarding message to the outer container. Fixes and closes SF bug
#585833.
|
| | |
|
| | |
|
| |
|
|
| |
text, not as pickles.
|
| |
|
|
|
|
|
|
|
| |
the copy of the Message instance doesn't get passed to
UserNotification's constructor via the `text' argument. Instead, it
should get attached via set_payload() after the Content-Type: is set
to message/rfc822.
Bug reported by Ron Jarrell.
|
| |
|
|
|
|
|
| |
saved on disk as pickles or plaintext. I don't want to promote this
to a mm_cfg.py variable.
HoldMessage(): Optionally store the message in plain text.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
__handlepost(), __refuse(): Send messages from the -bounces address so
that errors will get bounce processed.
__refuse(): In the refuse.txt, use the -owner address as the
%(adminaddr)s expansion so that when the human acts on this message,
they'll contact a human without going through the bounce processor.
_UpdateRecords(): This is will be used in bin/update to canonicalize
all the request.db records. Specifically, the SUBSCRIPTION records
will always be of length 6 and the HELDMSG records will also always be
6. For shorter records, provide reasonable defaults.
|
| |
|
|
|
|
| |
interface, also add an `adminapproved' key to the metadata. This is
used to tell the Emergency handler the message is okay to let
through.
|
| |
|
|
|
| |
X-Mailman-Approved-At: and remove the address of the approver (it's
always going to be some alias for the list's moderators or admins).
|
| |
|
|
|
|
|
|
| |
UserNotification constructor so that the admin gets the unsub request
notice in the proper language.
__refuse(): Be sure to create the Subject: header and other i18n text
in the language of the recipient of the rejection message.
|
| |
|
|
|
|
|
|
|
|
|
| |
message object, pass in the language that the message should be in.
This allows us to get the character set and header encodings right.
Note that in the former method, we try to set the language to the
forwarding address, if it is a member of the list. If not, the list's
preferred language will be used.
Patch by Ben Gertzfield, with modifications by Barry.
|
| |
|
|
| |
refusal messages. Use the same default as in __handlepost().
|
| |
|
|
|
|
|
|
| |
__opendb(): Catch EOFError that marshal.load() could throw. In that
case, log the error and blow away the old database.
__closedb(): A more robust save of the requests.db file. Save to a
temp file first and then atomically os.rename() it to the real file.
|
| |
|
|
| |
self.preferred_language.
|
| |
|
|
| |
Content-Type: headers to the admin message we send out.
|
| |
|
|
| |
instead of assuming that DEFER's value is false.
|
| |
|
|
|
| |
is composed. Be sure to add a MIME-Version: header and use
set_payload() instead of add_payload() to include the forwarded copy.
|
| |
|
|
|
|
| |
to be sent to the list moderators, it should be sent in the list's own
preferred language, not in the requested language of the subscribee.
Reported by Daniel Buchmann.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
GetUnsubscriptionIds(): Return all the pending admin requests that are
UNSUBSCRIPTIONs.
HandleRequest(): Add support for UNSUBSCRIPTION type records.
HoldSubscription(): Use the list's internal name, not its real name in
the message to the admin.
HoldUnsubscription(), __handleunsubscription(): Support for holding
unsubscription requests, as well as handling their disposition, which
can be DEFER, DISCARD, REJECT, or UNSUBSCRIBE.
|
| |
|
|
| |
message/rfc822 MIME encapsulation rather than Resent-To: headers.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Also, use cStringIO directly instead of our own hack-around StringIO
module.
InitTempVars(): Don't set __filename here, since InitTempVars() is
never called when the list is Create()'d (which may itself be a
buglet).
__filename(), __opendb(), __closedb(): New method to return the
request.db absolute path on the fly. Use this in __opendb() and
__closedb().
HoldMessage(): Store the message as a pickle instead of generating the
plain text representation. This should be faster than reparsing
on input.
readMessage(): New function that will read either pickle or plain text
held messages, depending on the file extension. This helps with
backwards compatibility.
|
| |
|
|
|
|
|
| |
more informative message to logs/vette (one that includes the
Message-ID: of the original message). Also, include an
X-Moderated: header which lets recipients know when -- and by
whom -- the message was approved.
|
| |
|
|
|
| |
HandleRequest(): Add a note for later about syncing the held message
db and the confirmation cookie.
|
| |
|
|
|
|
| |
getMemberLanguage() instead of GetPreferredLanguage().
__handlesubscription(): Use UserDesc convenience class.
|
| |
|
|
| |
there's a "version" key.
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
__opendb(): Automatically update the schema based on the 'version'
entry (or lack thereof). Specifically, add a fullname field to
any held SUBSCRIPTION entries, and a msgdata dictionary to any
HELDMSG entries (but only if they don't have enough fields). This
update is currently keyed off the lack of 'version' entry; after
the update 'version' is set to REQUESTS_FILE_SCHEMA_VERSION.
__closedb(): Set the 'version' entry to REQUESTS_FILE_SCHEMA_VERSION
NumRequestsPending(): Subtract one from the length of the dictionary
to account for the internal bookkeeping 'version' entry.
__handlepost(): Remove the backwards compatibility hack for pre 2.0b3,
since __opendb() now does this.
HoldSubscription(): Accept a fullname field.
__handlesubscription(): Unpack the fullname field.
|
| | |
|
| |
|
|
|
|
|
|
|
|
| |
the subscription request email should appear to come from the -owner
not the -admin to avoid unnecessary bounce processing.
Also, because this message is part of the pending moderation requests
(i.e. a moderator can approve or disapprove a subscription request),
set the message metadata key "tomoderators" so that the message will
be delivered to both the list owners and the list moderators.
|
| |
|
|
|
| |
preferred language, simple pass in self; maketext() digs the preferred
language out of the list object.
|
| | |
|
| |
|
|
| |
Errors.MMAlreadyMember. That's way too many M's and A's there!
|
| |
|
|
|
| |
someone who is already on the list. Since the person was added between the
subscription request and the approval, just drop the request.
|
| |
|
|
|
|
| |
requests too. This means you can defer making a decision about a
subscription just like a held message. You can also discard a
subscription request without sending a rejection notice.
|
| |
|
|
| |
HoldMessage(): GetSender() -> get_sender()
|
| |
|
|
|
|
|
| |
Fix the Utils.maketext() calls to pass the language in as a keyword
argument.
Fix some _() wrappings to use local variables.
|
| |
|
|
|
|
|
|
| |
References to HandlerAPI module removed.
Use new mimelib and switchboard interfaces.
Use other Python 2.0 features as appropriate.
|