* On 4/18/25 04:23, Mark Sapiro wrote:
On 4/17/25 11:35 AM, Mihai Moldovan wrote:

New incoming messages will have the correct data, of course, but
imported ones wouldn't, so I'll have to use a more sophisticated
approach to handle them, probably by going through mailman's email
wrapper, figuring out how to generate a msgdata object for a message,
using RFC2369.process and maybe more.

Here's an example script. You need to run this with
/opt/mailman/mm/venv/bin/python to get access to the mailman imports.
```
from mailbox import Maildir, mbox
from mailman.email.message import Message
from mailman.handlers.rfc2369 import process
from mailman.interfaces.listmanager import IListManager
from mailman.utilities.email import add_message_hash
from zope.component import getUtility
mb = mbox('path/to/mbox', factory=Message, create=False)
md = Maildir('path/to/maildir', create=False)
mlist = getUtility(IListManager).get_by_list_id('your.list.id')
for msg in mb:
      add_message_hash(msg)
      process(mlist, msg, {})
      md.add(msg)
mb.close()
md.close()
```

Thank you.

Unfortunately, I'm having a hard time getting this to work correctly. My current approach is (which is modified from yours, for instance to use Prototype.archive_message() instead of writing directly to a Maildir):

```py
import copy
import sys

from mailbox import mbox
from mailman.archiving.prototype import Prototype
from mailman.core import initialize
from mailman.email.message import Message
from mailman.handlers.rfc_2369 import process
from mailman.interfaces.listmanager import IListManager
from mailman.interfaces.mailinglist import IMailingList
from mailman.utilities.email import add_message_hash
from zope.component import getUtility

initialize.initialize()

if (len(sys.argv) < 3):
  print('Usage: {0} <list-id> <mbox-file>'.format(sys.argv[0]), file=sys.stderr)
  exit(1)

mb = mbox(sys.argv[2], factory=Message, create=False)

mlist = getUtility(IListManager).get_by_list_id(sys.argv[1])

for msg in mb:
  try:
    add_message_hash(msg)
    process(mlist, msg {})
    Prototype.archive_message(mlist, msg)
  except Exception as e:
print("Error when adding {0}: {1}".format(msg['message-id'], str(e)), file=sys.stderr)

mb.close()
```

This returns "Error when adding None: '_PartialFile' object has no attribute 'header_max_count'" for each message.

This, including getting None for the Message-ID, stumped me and I got on to debugging this.

Indeed, even something as simple as

```py
for msg in mb:
  print(type(msg))
  print(msg['message-id'])
  print(msg)
  exit(0)
```

results in getting a None for the Message-ID and a stack trace:

<class 'mailman.email.message.Message'>
None
Traceback (most recent call last):
  File "/root/mailman3/prototype-import.py", line 29, in <module>
    print(msg)
  File "/usr/lib/python3.12/email/message.py", line 165, in __str__
    return self.as_string()
           ^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/mailman/email/message.py", line 55, in as_string
    value = email.message.Message.as_string(self)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/email/message.py", line 188, in as_string
    g.flatten(self, unixfrom=unixfrom)
  File "/usr/lib/python3.12/email/generator.py", line 98, in flatten
    policy = policy.clone(max_line_length=self.maxheaderlen)
             ^^^^^^^^^^^^
AttributeError: '_PartialFile' object has no attribute 'clone'. Did you mean: 'close'?

This eventually led me to realize that passing mailman.email.message.Message as the factory to mbox() internally calls factory(msg), and the base class of Message (email.message.Message) has an __init__ function that takes the policy parameter, so it looks as if it's registering the mailbox message incorrectly as the policy handler, which is totally wrong of course.

If I change the call to mb = mbox(sys.argv[2], factory=None, create=False), the output looks more promising, so converting the data to mailman.email.message.Message first seems to have been the wrong idea on my part:

```
<class 'mailbox.mboxMessage'>
<mailman.1.1399151409.10314.x2go-i...@lists.x2go.org>
Return-Path: <mailman-boun...@lists.x2go.org>
[...]
```

and indeed, if I let the import actually happen, it works.

The imported messages, do have a Message-ID-Hash, but the Archived-At and List-Archive headers are empty (literally <>).

Do you have an example message that was archived through Prototype? What are the proper header values for this module? I believe that Archived-At should be the Message-ID-Hash and the List-Archive header contain... well, given that the Prototype archiver is not meant to be publicly available, probably a file:// URL?


Mihai

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature

_______________________________________________
Mailman-users mailing list -- mailman-users@mailman3.org
To unsubscribe send an email to mailman-users-le...@mailman3.org
https://lists.mailman3.org/mailman3/lists/mailman-users.mailman3.org/
Archived at: 
https://lists.mailman3.org/archives/list/mailman-users@mailman3.org/message/SKJKPAUH377NYHTSA3345ZGE5AQDRL3T/

This message sent to arch...@mail-archive.com

Reply via email to