| Commit message (Collapse) | Author | Age | Files | Lines |
| ... | |
| |
|
|
|
|
|
|
|
| |
send a message from a list, but with an explicit list of recipients).
There is both an importable API and a command line API when called as
a script.
TopicMgr.py contains the mixin class for initializing MailList
attributes related to the topic filter feature.
|
| | |
|
| |
|
|
|
| |
GetConfigInfo() structures that used to be in the modules one
directory up.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- There's no more GetConfigInfo() in the mixin classes. All admin
ui categories and content comes from components in the new
Mailman.Gui package.
- All MailList attribute access for user-centric information is
moved out of here into the OldStyleMemberships (a subclass, aka
implementation of the MemberAdaptor interface).
- An extension mechanism to MailList objects has been added. Drop
a file called extend.py in the lists/<yourlist> directory; this
gets execfile'd, and the function extend() is called after the
instance is initialized. Use this to override anything
(e.g. the _memberadaptor attribute).
- Lots of code reorganization.
Specific changes:
MailList subclasses: Added TopicMgr
__init__(): Don't call MailCommandHandler.__init__() explicitly.
Instead, loop through base classes calling their __init__()'s if
they have them.
Initialize _memberadaptor to be an OldStyleMemberships instance.
After the instance has been locked and loaded <snort!> execfile
extend.py and run its extend() function, if it has one.
InitTempVars(): Like __init__(), cycle through all base classes,
calling each's InitTempVars() if they have one. Also, instantiate
the gui components by dir'ing the Gui package and instantiating
each callable not prefixed by _ (they will be the individual
classes).
GetMembers(), GetDigestMembers(), GetDeliveryMembers(),
GetDigestDeliveryMembers(), __AddMember(),
GetUserSubscribedAddress(), GetUserCanonicalAddress(),
GetUserOption(), SetUserOption(), FindUser(): Removed.
__getattr__(): Added for auto-delegation first to the _memberadaptor,
and then to the gui components.
__repr__(): Change the printable representation slightly so that
"(unlocked)" is printed if the list is unlocked, and also to not
include the class/module name. Also use %x format instead of
coercing the id to hex().
InitVars(): Add usernames and passwords dicts for traditional
membership management. Like __init__(), cycle through all base
classes, calling each's InitVars() if they have one. Set
self.password here instead of in SecurityManager's InitVar().
GetConfigCategories(): New method which returns a CategoryDict
instance (subclass of UserDict), containing the order
ADMIN_CATEGORIES as extracted from the gui components
GetConfigCategory() methods.
GetConfigSubCategories(): For a particular category, get the list of
subcategories by calling a gui component's
GetConfigSubCategories() method if it has one.
GetConfigInfo(): Delegate to gui components.
Save(): Ignore attributes if their name starts with _ (like before) or
if their value type is MethodType.
AddMember(): Rewrite to use (Python 2.2's) rfc822.parseaddr() which
supplants Utils.ParseAddrs(). We also don't remove spaces from
the name any more, but we do still lowercase the domain. Also,
IsMember() -> isMember(). Call ApprovedAddMember() passing in the
fullname. Same with HoldSubscription().
ApprovedAddMembers(): Use MemberAdaptor API, and
rfc822.parseaddr().
DeleteMember() -> ApprovedDeleteMember(). Also rewrite to use
MemberAdaptor API.
ChangeMemberName(): New method which changes a member's real name,
both for this list, and globally.
ChangeMemberAddress(), ApprovedChangeMemberAddress(): Use
MemberAdaptor API.
ProcessConfirmation(): DeleteMember() -> ApprovedDeleteMember().
GetPreferredLanguage(): Allow name to default to None, meaning return
the list's preferred_language.
|
| |
|
|
|
|
|
|
|
|
|
| |
MMAlreadyAMember: Make these class based exceptions.
MemberError, NotAMemberError, AlreadyReceivingDigests,
AlreadyReceivingRegularDeliveries, CantDigestError, MustDigestError:
Add these "new wave" exceptions, which are raised by the
MemberAdaptors.
NB: I really need to go through and make all the exceptions sane!
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
API instead, e.g.
IsMember() -> isMember()
self.passwords.* -> getMemberPassword()
ConfirmUserPassword() -> [do the comparison ourselves]
ChangeUserPassword() -> setMemberPassword()
GetUserOption() -> getMemberOption()
GetDigestMembers() -> getDigestMemberKeys()
GetMembers() -> getRegularMemberKeys()
DeleteMember() -> ApprovedDeleteMember()
option_info: Make order agree w/ option_desc.
ProcessPasswordCmd(): Fix the response string so that it isn't broken
on two lines. Remove unnecessary exception handlers.
be raised.
ProcessOptionsCmd(), ProcessSetCmd(), ProcessUnsubscribeCmd(): Rewrite
and simply to use the new membership API. Remove unnecessary
exception handlers.
ProcessSetCommand(): Split usage printing into __setcmd_usage()
method.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
API instead, e.g.
GetDigestMembers() -> getDigestMemberKeys()
GetUserOption() -> getMemberOption()
GetMembers() -> getRegularMemberKeys()
FormatOptionButton(): Add ReceiveNonmatchingTopics flag.
FormatBox(): Add optional `value' parameter, which if supplied is the
default value for teh input box (default is the empty string).
|
| |
|
|
|
|
|
|
|
|
|
|
| |
depends on it).
ADMIN_CATEGORIES: Here's where we define the category names for the
admin ui.
Topics: A new widget type.
ReceiveNonmatchingTopics: New member option flag controlling whether a
user receives or ignores a message that does not matching any topics.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
API instead, e.g.
GetUserOption() -> getMemberOption()
GetPreferredLanguage() -> getMemberLanguage()
IsMember() -> isMember()
GetDigestDeliveryMembers() -> getDigestMemberKeys()
ToDigest.py: clear the one_last_digest() dictionary after sending the
digest.
|
| | |
|
| | |
|
| |
|
|
| |
that the msgfp file is definitely closed.
|
| | |
|
| |
|
|
| |
process_form(): IsMember()/FindUser() -> isMember();
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
member's real names. Specifically,
main(): IsMember() -> isMember();
FindUser()/GetUserSubscribedAddress() -> getMemberCPAddress()
GetPreferredLanguage() -> getMemberLanguage()
Support the printing of topic details when they click on the
"Details" link after the topic name (works like admin interface's
VARHELP).
In the change-of-address stanza, add a check for the fullname
field, which contains the member's real name. After extracting
the fullname, new-address, and confirm-address fields, be more
careful about including error messages, so that if the real name
field is set or cleared, we ignore the address fields if they are
both blank. Handle setting the member's name globally, just like
a global change of address.
DeleteMember() -> ApprovedDeleteMember()
Add recognition of the ReceiveNonmatchingTopics flag to determine
what the user wants for messages that match no topics (they can
either receive them or ignore them).
GetUserOption() -> getMemberOption()
Add processing of user topic selections.
SetUserOption() -> setMemberOption() and don't special case when
setting digest deliver; setMemberOption() handles that properly.
options_page(): Include the user's full name in presentable_user, as
in "john.doe@dom.ain, John Doe". If there's no user name then
just print the email address as before.
"Change My Address" button -> "Change My Address and Name"
Add replacements for the fullname box, and the topics option.
IsMember() -> isMember()
ChangeUserPassword() -> setMemberPassword()
SetUserOption() -> setMemberOption()
topic_details(): New method to include the topic details in the top
information area.
|
| |
|
|
|
|
|
|
|
|
|
| |
when the admin is trying to login with an empty password field.
When WebAuthenticate() fails, check the `adminpw' cgi key to
determine whether this was a login attempt, or the first visit of
this link.
show_requests(): SUBSCRIPTION pending records now include the supplied
user real name (i.e. fullname), so use this when unpacking the
tuple.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
and to be able to set/get member's real names. Specifically,
CATEGORIES: Don't hardwire these here. Instead they are extracted via
mlist.GetConfigCategories().
main(): GetMembers() -> getRegularMemberKeys()
get_config_options(): Removed. Use mlist.GetConfigInfo() instead.
show_results(): Don't hardwire sub-categories. Instead get them from
mlist.GetConfigSubCategories().
get_item_gui_value(): Added a new kind of gui widget, the `Topics'
widget which includes at least three boxes (for topic name,
regexp, and description), along with possibly a Delete button, an
Add button, and an "add where" pull down menu.
membership_options(): Instead of using GetMembers() and
GetDigestMembers(), use the new membership API methods
getMembers(), getMemberName(). Also use getMemberOption() instead
of GetUserOption(). In the membership list, add a text box for
the member's real name.
change_option(): We now allow gui components to optionally handle the
form data themselves. If the component has a HandleForm() method,
it is called, passing the MailList object, the cgi form data
structure, and the Document object.
DeleteMember() -> ApprovedDeleteMember()
SetUserDigest() -> setMemberOption(... mm_cfg.Digests, ...)
SetPreferredLanguage() -> setMemberLanguage()
SetUserOption() -> setMemberOption()
Added setMemberName() to set the member's full name.
get_config_options(): Removed.
|
| | |
|
| |
|
|
|
|
| |
is a flag specifying whether pending entries should be removed from
the database or not, and will be used with the revamped confirmation
web ui.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
zero arguments, so we remove the crypted_password parameter. This
means that self.password will be set in MailList instead.
AuthContextInfo(): Instead of getting the user password directly out
of self.passwords, use the API method getMemberPassword() -- which
itself raises MMNotAMemberError if the user isn't a member of the
list.
ChangeUserPassword(): Removed. Use the new setMemberPassword() API
method.
|
| |
|
|
|
|
|
|
|
|
| |
ValidateEmail(): Add `/' to the list of _badchars in email addresses
instead of making it bad only if it points to an existing directory
(!).
ParseAddrs(): Removed since rfc822.parseaddr() now works for all
cases, according to RFC 2822 (but we'll need to supply the rfc822.py
from Python 2.2 now).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
GetConfigInfo(): Removed. All admin ui gui elements are moved into
components in the Mailman/Gui subdirectory.
All membership related attribute access should use the MemberAdaptor
API instead, e.g.
IsMember() -> isMember()
GetUserOption() -> getMemberOption()
SetUserOption() -> setMemberOption()
Also use ApprovedDeleteMember() instead of DeleteMember().
Deliverer.py:
Remove last vestiges of os.environ['LANG']
Digester.py:
SetUserDigest(): Removed. This is replaced by
OldStyleMemberships's setMemberOption() method when flag ==
mm_cfg.Digests
|
| |
|
|
| |
so the new variables from versions.py will get installed.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
don't already have them:
- topics: a list of all admin specified topics
- topics_enabled: a flag specifying whether topics are enabled
- topics_bodylines_limit: the number of lines of the body that the
topic tagger should look for Subject: and Keywords: lines
- one_last_digest: A hold over from an earlier time, this holds
addresses of folks who switched from digest to regular
delivery
- usernames: holds the dictionary of email addresses to Real Names
but if a user has no assigned Real Name, they have no entry in
this dictionary.
|
| | |
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
| |
instead let them percolate up to Runner.__oneloop(). Now, the proper
action when an uncaught exception occurs is to shunt the message
instead of trying forever to re-deliver it (possibly causing
logs/error to fill up /very/ quickly).
Shunted messages can always be resent by moving them back to
qfiles/in.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
dictionary interpolation. Since they're coming from the great
unwashed masses, the autoresponse texts could have bogus %()s bits in
them, and using a SafeDict doesn't guard against all kinds of
exceptions.
So, if any exception is caught during interpolation, log it, and use
the raw autoresponse text in the email.
Also, because we're not using the buggy rfc822.py module anymore, we
don't need to special case the situation when the first line of the
autoresponse text has a colon in it.
|
| |
|
|
|
|
|
|
|
|
|
| |
notifying the administrator of the held message), use the list's
preferred_language to get the charset. This fixes the
UnboundLocalError that occurs if dont_respond_to_post_requests and
admin_immed_notify are both true (it shouldn't have been using `lang'
in the first place, since that's the /user's/ preferred language, not
the admin's).
Bug found by Mentor Cana.
|
| |
|
|
| |
Found by Juan Carlos Rey Anaya.
|
| |
|
|
| |
the error code on e.errno, not e.code. Found by Mentor Cana.
|
| |
|
|
|
| |
Also added a note why "mailmanctl restart" doesn't Do The Right Thing
w.r.t. allowing the subrunners to re-import various Mailman modules.
|
| |
|
|
|
|
| |
were sent and the user confirmed (by web click) them both. The first
will delete the member but the second will raise this exception, so do
something more sensible than letting it trickle to the top.
|
| |
|
|
|
|
|
| |
the Subject: header so that it contains just the word "confirm" and
the confirmation cookie. This doesn't lose any important information
(which is still contained in the body of the message), and it helps
for MUAs that like to wrap long Subject: lines.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
AddToResponse(): Use augmented assignment where appropriate.
ParseMailCommands(): Set the __noresponse flag to 0 at the top of this
method, so there's no chance that a previously handled command will
mess up sending a response to this command.
ProcessConfirmCmd(): Save the results from ProcessConfirmation() and
check the operation in the first element. If it's a
Pending.SUBSCRIPTION and the mailing list already sends out welcome
messages, then don't send a "succeed" confirmation ourselves.
Also, in the big except clause, catch MMNoSuchUserError which can
happen if the user has made two unsub requests and confirmed them both
(the second will trigger the exception). Do something more sensible
than letting the exception trickle all the way back up. ;)
|
| |
|
|
|
| |
trick-out of template_data. Add back the definition of _ (provided by
Juan Carlos Rey Anaya).
|
| |
|
|
|
|
|
|
|
| |
function from the dynamically imported module.
Also, MessageHeld -> HoldMessage
Also, catch RejectMessage exceptions, bouncing the rejected message
via mlist.BounceMessage().
|
| | |
|
| |
|
|
| |
explains the wrapping rules for the value.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
(either the list administrator's, or the list moderator's). If the
message contains this header with a matching password, the message is
sent to the entire list membership immediately, even to those members
who receive the message via digests. Note that the message /is/ still
digested too. Specifically,
RejectUrgentMessage: New class, derived from RejectMessage, which is
raised if the password in the Urgent: header does not match. Thus,
the original message is returned to the sender immediately, and is not
held or posted.
process(): Check Urgent: for a matching list moderator's or list
administrator's header. If found, set the recipients list to both the
regular and digest delivery members. If Urgent: is found, but the
password doesn't match, bounce the message back to the sender.
|
| | |
|
| | |
|
| |
|
|
| |
'option_descs' -> 'option_desc', as that is what the global is named.
|
| | |
|
| | |
|
| | |
|
| | |
|
| |
|
|
|
|
| |
correctly.
prepare_message(): 'COMMA' -> 'COMMASPACE'
|
| | |
|