I want to create a mailing list that is used for announcements only. I'd like attempts to post to be rejected with a notification.
I was able to set the list pw and verify it works with the Approved header using this reference:
https://docs.mailman3.org/projects/mailman/en/latest/src/mailman/rules/docs/...
I find that if both:
Default action to take when a member posts to the list
Default action to take when a non-member posts to the list
are set to "reject (with notification)", the approved header is ignored and messages are always rejected (posted via "mailman inject")
Would it be bad to test the approved header before rejecting a message? Essentially always accept a message with a valid approved header? Is there another way for me to achieve this?
On another front, I'm unable to have messages posted via "mailman inject" use postorius created list templates. Would it be difficult to add this functionality?
On 4/28/26 5:17 PM, Craig Leres via Mailman-users wrote:
I want to create a mailing list that is used for announcements only. I'd like attempts to post to be rejected with a notification.
I was able to set the list pw and verify it works with the Approved header using this reference:
https://docs.mailman3.org/projects/mailman/en/latest/src/mailman/rules/ docs/approved.html
I find that if both:
Default action to take when a member posts to the list Default action to take when a non-member posts to the list
are set to "reject (with notification)", the approved header is ignored and messages are always rejected (posted via "mailman inject")
This should not be the case. The message is checked for an Approved: header prior to the member/nonmember checks.
Would it be bad to test the approved header before rejecting a message? Essentially always accept a message with a valid approved header? Is there another way for me to achieve this?
That's the way it should be working. There is a potential issue if the password in the Approved: header when encrypted doesn't match the encrypted value in the lists moderator_password attribute, it is treated as if there were no Approved: header. This is a bug <https://gitlab.com/mailman/mailman/-/work_items/1276>. I.e., the message should be rejected but with a reason indicating the password was wrong.
On another front, I'm unable to have messages posted via "mailman inject" use postorius created list templates. Would it be difficult to add this functionality?
That should not be the case. Are you saying messages posted via email use Postorius created templates, but messages posted via mailman inject do not? If the templates are used for messages posted via email, they should also me used for messages posted via mailman inject. Have you verified that the templates are used for messages posted via email?
-- Mark Sapiro <mark@msapiro.net> The highway is for gamblers, San Francisco Bay Area, California better use your sense - B. Dylan
Ah. So when I thought I set the list pw, I didn't understand how "mailman shell" worked. Now I find that I cannot actually set it (see appended stack trace). However I found this thread:
https://lists.mailman3.org/archives/list/mailman-users@mailman3.org/thread/Q...
and was able to use curl to set the list pw using something like:
curl --user restadmin:restpass -X PATCH --data \
'moderator_password=????????????' \
http://localhost:8001/3.1/lists/test.example.com/config
With that in place, posting with the correct approved header works for "mailman inject" and SMTP. And in both cases, the modified footer template was used. Also, members and non-members get the (custom) bounce message when they attempt to post.
The help and patience are appreciated.
Craig
mm 299 % mailman shell Welcome to the GNU Mailman shell Use commit() to commit changes. Use abort() to discard changes since the last commit. Exit with ctrl+D does an implicit commit() but exit() does not.
from zope.component import getUtility from mailman.interfaces.listmanager import IListManager listspec = 'test.example.com' mlist = getUtility(IListManager).get(listspec) pw = '????????????' mlist.moderator_password = config.password_context.encrypt(pw) commit() Traceback (most recent call last): File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1815, in _execute_context context = constructor( ^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/default.py", line 1494, in _init_compiled l_param: List[Any] = [ ^ File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/default.py", line 1496, in <listcomp> flattened_processorskey File "/usr/local/lib/python3.11/site-packages/sqlalchemy/sql/sqltypes.py", line 918, in process return DBAPIBinary(value) ^^^^^^^^^^^^^^^^^^ TypeError: memoryview: a bytes-like object is required, not 'str' The above exception was the direct cause of the following exception:
Traceback (most recent call last): File "<console>", line 1, in <module> File "/usr/local/lib/python3.11/site-packages/mailman/database/base.py", line 54, in commit self.store.commit() File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/session.py", line 2030, in commit trans.commit(_to_root=True) File "<string>", line 2, in commit File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/state_changes.py", line 137, in _go ret_value = fn(self, *arg, **kw) ^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/session.py", line 1311, in commit self._prepare_impl() File "<string>", line 2, in _prepare_impl File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/state_changes.py", line 137, in _go ret_value = fn(self, *arg, **kw) ^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/session.py", line 1286, in _prepare_impl self.session.flush() File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/session.py", line 4331, in flush self._flush(objects) File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/session.py", line 4466, in _flush with util.safe_reraise(): File "/usr/local/lib/python3.11/site-packages/sqlalchemy/util/langhelpers.py", line 121, in __exit__ raise exc_value.with_traceback(exc_tb) File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/session.py", line 4427, in _flush flush_context.execute() File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute rec.execute(self) File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute util.preloaded.orm_persistence.save_obj( File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/persistence.py", line 85, in save_obj _emit_update_statements( File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/persistence.py", line 912, in _emit_update_statements c = connection.execute( ^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1419, in execute return meth( ^^^^^ File "/usr/local/lib/python3.11/site-packages/sqlalchemy/sql/elements.py", line 527, in _execute_on_connection return connection._execute_clauseelement( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement ret = self._execute_context( ^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1821, in _execute_context self._handle_dbapi_exception( File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 2363, in _handle_dbapi_exception raise sqlalchemy_exception.with_traceback(exc_info[2]) from e File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1815, in _execute_context context = constructor( ^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/default.py", line 1494, in _init_compiled l_param: List[Any] = [ ^ File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/default.py", line 1496, in <listcomp> flattened_processorskey File "/usr/local/lib/python3.11/site-packages/sqlalchemy/sql/sqltypes.py", line 918, in process return DBAPIBinary(value) ^^^^^^^^^^^^^^^^^^ sqlalchemy.exc.StatementError: (builtins.TypeError) memoryview: a bytes-like object is required, not 'str' [SQL: UPDATE mailinglist SET moderator_password=? WHERE mailinglist.id = ?] [parameters: [{'moderator_password': '$0$aaaaaa=000000$a0aA00aaAaAaaAaa$AaAA0.aAAaAA0AAAAaaAAaaAaAAA0aA0Aa0A00aA0AAaAa0A0aAaaaA0AAAaAa0Aaaaaaaaaa0aaAAaaAa0Aa/', 'mailinglist_id': 1}]]
On 4/29/26 12:01 PM, Craig Leres via Mailman-users wrote:
Ah. So when I thought I set the list pw, I didn't understand how "mailman shell" worked. Now I find that I cannot actually set it (see appended stack trace). ... mm 299 % mailman shell Welcome to the GNU Mailman shell Use commit() to commit changes. Use abort() to discard changes since the last commit. Exit with ctrl+D does an implicit commit() but exit() does not.
from zope.component import getUtility from mailman.interfaces.listmanager import IListManager
The above two lines are unnecessary because mailman shell in interactive mode imports those things. See below.
listspec = 'test.example.com' mlist = getUtility(IListManager).get(listspec) pw = '????????????' mlist.moderator_password = config.password_context.encrypt(pw)
This needs to be
mlist.moderator_password = config.password_context.encrypt(pw).encode()
to make it bytes. It needs to be bytes because of the way the column is defined in the mailinglist model. It works as a string in the doctests at <https://docs.mailman3.org/projects/mailman/en/latest/src/mailman/rules/docs/...> because in those fragments the list object is never saved to a database.
The following illustrates all the names defined when mailman shell is invoked interactively.
$ mailman shell Welcome to the GNU Mailman shell Use commit() to commit changes. Use abort() to discard changes since the last commit. Exit with ctrl+D does an implicit commit() but exit() does not.
dir() ['ALL_TEMPLATES', 'ALT_TEMPLATE_NAMES', 'ALWAYS_REPLY', 'AcceptEvent', 'AcceptOwnerEvent', 'Action', 'AddressAlreadyLinkedError', 'AddressError', 'AddressNotLinkedError', 'AddressVerificationEvent', 'AlreadySubscribedError', 'ArchivePolicy', 'ArchiveRenderingMode', 'BadDomainSpecificationError', 'BounceContext', 'ChainEvent', 'ClobberDate', 'ConfigurationUpdatedEvent', 'ContinueProcessing', 'DMARCMitigateAction', 'DatabaseError', 'DeliveryMode', 'DeliveryStatus', 'DigestFrequency', 'DiscardEvent', 'DiscardMessage', 'DomainCreatedEvent', 'DomainCreatingEvent', 'DomainDeletedEvent', 'DomainDeletingEvent', 'DuplicateStyleError', 'EmailError', 'ExistingAddressError', 'FilterAction', 'FilterType', 'HoldEvent', 'IAPI', 'IAcceptableAlias', 'IAcceptableAliasSet', 'IAddress', 'IArchiver', 'IAutoResponseRecord', 'IAutoResponseSet', 'IBan', 'IBanManager', 'IBounceEvent', 'IBounceProcessor', 'ICLISubCommand', 'ICacheManager', 'IChain', 'IChainIterator', 'IChainLink', 'IConfiguration', 'IContentFilter', 'IDatabase', 'IDatabaseFactory', 'IDomain', 'IDomainManager', 'IEmailCommand', 'IEmailResults', 'IEmailValidator', 'IHandler', 'IHeaderMatch', 'IHeaderMatchList', 'ILanguage', 'ILanguageManager', 'IListArchiver', 'IListArchiverSet', 'IListManager', 'IListRequests', 'IMailTransportAgentAliases', 'IMailTransportAgentDelivery', 'IMailTransportAgentLifecycle', 'IMailingList', 'IMember', 'IMembershipManager', 'IMessage', 'IMessageStore', 'IMutableChain', 'IOneLastDigest', 'IPendable', 'IPended', 'IPendedKeyValue', 'IPendings', 'IPipeline', 'IPlugin', 'IPreferences', 'IRoster', 'IRule', 'IRunner', 'IStyle', 'IStyleManager', 'ISubscriptionManager', 'ISubscriptionService', 'ISwitchboard', 'ITemplate', 'ITemplateLoader', 'ITemplateManager', 'IUser', 'IUserManager', 'IWorkflowState', 'IWorkflowStateManager', 'InvalidConfigurationError', 'InvalidEmailAddressError', 'InvalidListNameError', 'LinkAction', 'ListAlreadyExistsError', 'ListCreatedEvent', 'ListCreatingEvent', 'ListDeletedEvent', 'ListDeletingEvent', 'MailmanError', 'MemberRole', 'MembershipChangeEvent', 'MembershipError', 'MembershipIsBannedError', 'MissingConfigurationFileError', 'MissingPreferredAddressError', 'MissingUserError', 'NewsgroupModeration', 'NoSuchListError', 'NotAMemberError', 'PasswordChangeEvent', 'PendType', 'Personalization', 'RejectEvent', 'RejectMessage', 'ReplyToMunging', 'RequestRecord', 'RequestType', 'Response', 'ResponseAction', 'RunnerCrashEvent', 'RunnerInterrupt', 'SomeRecipientsFailed', 'SubscriptionConfirmationNeededEvent', 'SubscriptionEvent', 'SubscriptionInvitationNeededEvent', 'SubscriptionMode', 'SubscriptionPendingError', 'SubscriptionPolicy', 'TokenOwner', 'TooManyMembersError', 'UnrecognizedBounceDisposition', 'UnsubscriptionConfirmationNeededEvent', 'UnsubscriptionEvent', 'UnverifiedAddressError', '__builtins__', 'abort', 'commit', 'config', 'getUtility', 'm']
-- Mark Sapiro <mark@msapiro.net> The highway is for gamblers, San Francisco Bay Area, California better use your sense - B. Dylan
participants (2)
-
mailman26@xse.com -
Mark Sapiro