Migration einer Mailingliste zu Discourse (mbox, Listserv, Google Groups usw)

Ich versuche, einen standardmäßigen mbox-Dump von einer Mailingliste zu importieren, stoße aber auf Probleme mit „Process killed

1 „Gefällt mir“

Ich vermute, dass der Parser bei einer bestimmten E-Mail in diesem mbox-Format hängt. Die index.db ist eine SQLite-Datenbank. Schauen Sie sich die Tabelle email an, filtern Sie nach dem mbox-Dateinamen in der Spalte filename und finden Sie den höchsten Wert in der Spalte last_line_number. Es ist sehr wahrscheinlich, dass der Parser bei der nächsten E-Mail nach dieser Zeilennummer in der mbox-Datei hängt.

3 „Gefällt mir“

Vielen Dank @gerhard, ich habe es geschafft, die letzte erfolgreich indizierte E-Mail und die unmittelbar darauf folgende E-Mail zu identifizieren, die (wie ich vermute) den Hänger verursacht. Allerdings scheint mir an diesen E-Mails nichts Außergewöhnliches zu sein. Ist es in Ordnung, wenn ich Ihnen diese beiden Beispiel-E-Mails in einer privaten Nachricht sende, um zu sehen, ob etwas auffällt?

Klar, du kannst mir eine PN schicken. Und versuch mal, diese E-Mails aus der mbox-Datei zu entfernen und zu testen, ob die Indexierung funktioniert.

3 „Gefällt mir“

Danke, gesendet. Ich konnte dir nicht direkt per PN schreiben, also habe ich es über die Teamgruppe gesendet. Ich hoffe, das ist in Ordnung. Ich werde versuchen, auch die E-Mail zu entfernen und schauen, wie weit wir kommen, bevor es wieder hängt.

1 „Gefällt mir“

Danke für die E-Mails. Ich habe nichts Ungewöhnliches bemerkt, und in meinen Tests funktionierte alles problemlos.

Dies ist nicht getestet, aber Sie könnten versuchen, den folgenden Git-Patch vor dem Ausführen des Import-Skripts anzuwenden. Er fügt ein Timeout von 60 Sekunden für das Parsen einer E-Mail hinzu. Das könnte Ihnen helfen, den Übeltäter zu finden und weiterzumachen, falls nur ein paar Nachrichten betroffen sind.

From 92efb4fc68724cfa20d5de48ba33b99c126a3a08 Mon Sep 17 00:00:00 2001
From: Gerhard Schlager
Date: Fri, 2 Oct 2020 17:27:39 +0200
Subject: [PATCH] Add timeout for parsing email in mbox importer

---
 script/import_scripts/mbox/support/indexer.rb | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/script/import_scripts/mbox/support/indexer.rb b/script/import_scripts/mbox/support/indexer.rb
index dc6e092c29..01523dad13 100644
--- a/script/import_scripts/mbox/support/indexer.rb
+++ b/script/import_scripts/mbox/support/indexer.rb
@@ -65,11 +65,15 @@ module ImportScripts::Mbox
     def index_emails(directory, category_name)
       all_messages(directory, category_name) do |receiver, filename, opts|
         begin
-          msg_id = receiver.message_id
-          parsed_email = receiver.mail
-          from_email, from_display_name = receiver.parse_from_field(parsed_email)
-          body, elided, format = receiver.select_body
-          reply_message_ids = extract_reply_message_ids(parsed_email)
+          msg_id = parsed_email = from_email = from_display_name = body = elided = format = reply_message_ids = nil
+
+          Timeout.timeout(60) do
+            msg_id = receiver.message_id
+            parsed_email = receiver.mail
+            from_email, from_display_name = receiver.parse_from_field(parsed_email)
+            body, elided, format = receiver.select_body
+            reply_message_ids = extract_reply_message_ids(parsed_email)
+          end
 
           email = {
             msg_id: msg_id,
-- 
2.28.0
3 „Gefällt mir“

Vielen Dank @gerhard, dein Patch funktioniert einwandfrei. Für meine Zwecke ist es in Ordnung, die fehlerhaften Nachrichten zu überspringen, da es nur eine geringe Anzahl gibt. Allerdings haben wir nun zusätzliche Ausgaben, falls diese hilfreich sein sollten, um das Problem zu lösen oder das Import-Skript robuster zu gestalten:

Failed to index message in /shared/import/data/lammps-users/chunk_10.mbox at lines 726814-729353
execution expired
["/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/nokogumbo-2.0.2/lib/nokogumbo/html5.rb:243:in `escape_text'",
"/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/nokogumbo-2.0.2/lib/nokogumbo/html5.rb:214:in `serialize_node_internal'",
"/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/nokogumbo-2.0.2/lib/nokogumbo/html5/node.rb:58:in `write_to'",
"/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.10/lib/nokogiri/xml/node.rb:699:in `serialize'",
"/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.10/lib/nokogiri/xml/node.rb:855:in `to_format'",
"/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.10/lib/nokogiri/xml/node.rb:711:in `to_html'",
"/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/nokogumbo-2.0.2/lib/nokogumbo/html5/node.rb:28:in `block in inner_html'",
"/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.10/lib/nokogiri/xml/node_set.rb:238:in `block in each'",
"/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.10/lib/nokogiri/xml/node_set.rb:237:in `upto'",
"/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.10/lib/nokogiri/xml/node_set.rb:237:in `each'",
"/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/nokogumbo-2.0.2/lib/nokogumbo/html5/node.rb:28:in `map'",
"/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/nokogumbo-2.0.2/lib/nokogumbo/html5/node.rb:28:in `inner_html'",
"/var/www/discourse/lib/html_to_markdown.rb:74:in `block (2 levels) in hoist_line_breaks!'",
"/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.10/lib/nokogiri/xml/node_set.rb:238:in `block in each'",
"/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.10/lib/nokogiri/xml/node_set.rb:237:in `upto'",
"/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/nokogiri-1.10.10/lib/nokogiri/xml/node_set.rb:237:in `each'",
"/var/www/discourse/lib/html_to_markdown.rb:57:in `block in hoist_line_breaks!'",
"/var/www/discourse/lib/html_to_markdown.rb:54:in `loop'",
"/var/www/discourse/lib/html_to_markdown.rb:54:in `hoist_line_breaks!'",
"/var/www/discourse/lib/html_to_markdown.rb:16:in `initialize'",
"/var/www/discourse/lib/email/receiver.rb:387:in `new'",
"/var/www/discourse/lib/email/receiver.rb:387:in `select_body'",
"/var/www/discourse/script/import_scripts/mbox/support/indexer.rb:74:in `block (2 levels) in index_emails'", 
"/usr/local/lib/ruby/2.6.0/timeout.rb:108:in `timeout'",
"/var/www/discourse/script/import_scripts/mbox/support/indexer.rb:70:in `block in index_emails'", 
"/var/www/discourse/script/import_scripts/mbox/support/indexer.rb:139:in `block (2 levels) in all_messages'",
"/var/www/discourse/script/import_scripts/mbox/support/indexer.rb:171:in `block in each_mail'", 
"/var/www/discourse/script/import_scripts/mbox/support/indexer.rb:190:in `block in each_line'",
 "/var/www/discourse/script/import_scripts/mbox/support/indexer.rb:189:in `each_line'", 
"/var/www/discourse/script/import_scripts/mbox/support/indexer.rb:189:in `each_line'", 
"/var/www/discourse/script/import_scripts/mbox/support/indexer.rb:166:in `each_mail'", 
"/var/www/discourse/script/import_scripts/mbox/support/indexer.rb:132:in `block in all_messages'", 
"/var/www/discourse/script/import_scripts/mbox/support/indexer.rb:125:in `foreach'", 
"/var/www/discourse/script/import_scripts/mbox/support/indexer.rb:125:in `all_messages'", 
"/var/www/discourse/script/import_scripts/mbox/support/indexer.rb:66:in `index_emails'", 
"/var/www/discourse/script/import_scripts/mbox/support/indexer.rb:25:in `block in execute'", 
"/var/www/discourse/script/import_scripts/mbox/support/indexer.rb:22:in `each'", 
"/var/www/discourse/script/import_scripts/mbox/support/indexer.rb:22:in `execute'", 
"/var/www/discourse/script/import_scripts/mbox/importer.rb:43:in `index_messages'", 
"/var/www/discourse/script/import_scripts/mbox/importer.rb:27:in `execute'", 
"/var/www/discourse/script/import_scripts/base.rb:47:in `perform'", 
"script/import_scripts/mbox.rb:12:in `<module:Mbox>'", 
"script/import_scripts/mbox.rb:10:in `<module:ImportScripts>'", 
"script/import_scripts/mbox.rb:9:in `<main>'"]

Wie zuvor kann ich die betreffende Nachricht gerne zur Verfügung stellen, falls hilfreich – diesmal liefert die Fehlermeldung die genauen Zeilennummern, sodass wir mit hoher Sicherheit davon ausgehen können, dass wir die richtige Nachricht identifiziert haben.

4 „Gefällt mir“

Gerne, bitte teile die Nachrichten mit mir, und ich werde mir das ansehen. Falls es ein Problem gibt, können wir es beheben. Das wird nicht nur den Importer verbessern, sondern auch Discourse selbst, da derselbe Parser für eingehende E-Mails verwendet wird.

1 „Gefällt mir“

Ich lasse dieses Skript seit mehreren Monaten täglich für eine Website laufen, die eigentlich darauf angewiesen wäre, die Kategorie an die Gruppe zu abonnieren – das wurde jedoch noch nicht umgesetzt. Es funktioniert einwandfrei, außer dass ich gelegentlich eine neue cookies.txt-Datei benötige. Vor etwa einem Monat passierte etwas, und es meldete: „Es scheint, als hätten Sie keine Berechtigung, E-Mail-Adressen einzusehen. Vorgang abgebrochen.

1 „Gefällt mir“

Nun, ich schaue mir das nochmal an und es scheint, dass Links wie

 https://groups.google.com/forum/message/raw?msg=GROUP_NAME/THREAD_ID/POST_ID

früher die vollständigen E-Mail-Adressen enthielten, jetzt aber nicht mehr. Ich kann bestätigen, dass ich, wenn ich eingeloggt bin, auf „Über

Ich habe es kürzlich nicht ausprobiert, daher ist es möglich, dass es Änderungen gibt, die der Scraper derzeit nicht bewältigen kann.

@riking hat bemerkt, dass Google Takeout MBOX-Dateien für Gruppeninhaber exportiert, was eine Option sein könnte, die man prüfen sollte.

5 „Gefällt mir“

Danke. Nun, vor einer Woche hat es für eine zweite Seite funktioniert, und nachdem ich meine Cookie-Datei noch einmal aktualisiert habe, wurden die Daten für die erste Seite heruntergeladen. Es scheint nur ein oder zwei Tage funktioniert zu haben, und jetzt geht es wieder nicht – für keine der beiden Seiten. Ich sehe die vollständige E-Mail-Adresse in meinem Browser, lade die Cookies für diesen Tab herunter, aber es bringt nichts.

Ich werde mir den „takout

4 „Gefällt mir“

Ein Befehlszeilen-Tool zum Konvertieren einer Mailman2-Mailingliste (d. h. den Inhalt der config.pck mit Optionen, Mitgliedern, Moderatoren, privaten oder öffentlichen Flags usw.) in eine Discourse-Kategorie ist hier verfügbar: Client Challenge

1 „Gefällt mir“

@gerhard Hast du Ideen, wie man diese Anweisungen an eine Dev-Installation statt die Standardinstallation anpasst? Ich habe das Gefühl, dass ich mit nur wenigen Befehlen fast eine listserv-Migration zum Laufen gebracht habe, aber der letzte Schritt, den ich annehme, funktioniert mit keinem der folgenden Befehle:

ruby /src/script/import_scripts/mbox.rb ~/import/settings.yml
bundle exec ruby /src/script/import_scripts/mbox.rb /home/discourse/import/settings.yml

Beide Befehle scheitern daran, alle Abhängigkeiten zu laden. Siehe hier für die vollständige Befehlsliste, die ich verwendet habe, und die Fehlermeldungen. Hast du Ideen? Vielleicht fehlen einige d/bundle-Aufrufe?

Als Nächstes werde ich eine Ubuntu-VM ausprobieren und dort eine „Standardinstallation

3 „Gefällt mir“

Es sieht so aus, als hättest du das Meiste schon herausgefunden.

Ich habe das noch nie mit der Docker-basierten Entwicklerinstallation versucht, aber ich vermute, du musst "gem 'sqlite3'" zur Gemfile hinzufügen und apt install -y libsqlite3-dev innerhalb des Containers ausführen, bevor du d/bundle install ausführst.

Danach sollte bundle exec ruby ... funktionieren.

3 „Gefällt mir“

@gerhard danke für den sanften Stoß – ich habe alles von Grund auf neu durchlaufen lassen (ab git clone) und gem 'sqlite3' ans Ende von /src/Gemfile hinzugefügt, da ich annahm, dass dies die von dir gemeinte Datei war. Es hat funktioniert! Zur Information hier die von mir verwendeten Anweisungen (für die mne_analysis-Mailingliste):

1. Auf dem Ubuntu-Host

git clone https://github.com/discourse/discourse.git
cd discourse
d/boot_dev --init
d/rails db:migrate RAILS_ENV=development
d/shell
vim /src/Gemfile  # am Ende gem 'sqlite3' hinzufügen
exit
d/bundle

2. In der Docker-Shell

sudo mkdir -p /shared/import/data
sudo chown -R discourse:discourse /shared/import
wget -r -l1 --no-parent --no-directories "https://mail.nmr.mgh.harvard.edu/pipermail//mne_analysis/" -P /shared/import/data/mne_analysis -A "*-*.txt.gz"
rm /shared/import/data/mne_analysis/robots.txt.tmp
gzip -d /shared/import/data/mne_analysis/*.txt.gz
wget https://gist.githubusercontent.com/larsoner/940cd6c7100b87c4c5668cb0bc540afb/raw/9e78513620d11355ad0e10f4a2470996c26ebc8c/mailmanToMBox.py -O ~/mailmanToMBox.py
python3 ~/mailmanToMBox.py /shared/import/data/mne_analysis/
rm /shared/import/data/mne_analysis/*.txt
sudo apt install -y libsqlite3-dev  # bei mir keine Wirkung

# Ergebnisse prüfen
cat /shared/import/data/mne_analysis/*.mbox > ~/all.mbox
sudo apt install -y procmail
mkdir -p ~/split
export FILENO=0000
formail -ds sh -c 'cat > ~/split/msg.$FILENO' < ~/all.mbox
rm -rf ~/split ~/all.mbox

# Einstellungen
wget https://raw.githubusercontent.com/discourse/discourse/master/script/import_scripts/mbox/settings.yml -O /shared/import/settings.yml

# Ausführen
cd /src
bundle exec ruby script/import_scripts/mbox.rb /shared/import/settings.yml

Dies ergab eine Reihe informativer Ausgaben, und am Ende:

...
Updating featured topics in categories
        5 / 5 (100.0%)  [6890 items/min]   ]  
Resetting topic counters


Done (00h 06min 21sec)

Dann beenden und auf dem Ubuntu-Host:

d/unicorn &
google-chrome http://0.0.0.0:9292

Fertig!

Ich werde die Einstellungen wahrscheinlich noch anpassen, um das [Mne_analysis]-Präfix zu entfernen, aber ich bin begeistert, dass es bereits so gut funktioniert!

4 „Gefällt mir“

@gerhard Kann dein MBox-Importer nur bei der ersten Installation von Discourse verwendet werden oder auch später, wenn bereits andere Nutzer Discourse verwenden? Wenn der Importer genutzt wird, während Discourse von anderen Personen benutzt wird, werden dann Nebenwirkungen sichtbar?

1 „Gefällt mir“

Damit der Importer Nachrichten von Google Groups scrapen konnte, musste ich diese Änderung in /script/import_scripts/google_groups.rb rückgängig machen:
https://review.discourse.org/t/fix-google-groups-import-changed-login-url-9432/10615

Ich habe die Zeile

    wait_for_url { |url| url.start_with?("https://accounts.google.com") }

zurück auf

    wait_for_url { |url| url.start_with?("https://myaccount.google.com") }

geändert.

Andernfalls würde ich bei jedem Versuch diese Meldung erhalten:

Logging in...
Failed to login. Please check the content of your cookies.txt
6 „Gefällt mir“

@gerhard Ich habe nach dem Import festgestellt, dass die Nachrichten zwar in Ordnung aussehen, aber überhaupt keine gestaffelten Benutzer vorhanden sind, obwohl es so scheint, als ob es welche geben sollte (ich habe den Standardwert staged: true verwendet). Die Ausgaben sehen wie folgt aus:

...
Indexierung von Antworten und Benutzern

Erstellen von Kategorien
        1 / 1 (100,0 %)  [13440860 Elemente/Min]  
Erstellen von Benutzern

Erstellen von Themen und Beiträgen
     7399 / 7399 (100,0 %)  [1421 Elemente/Min]     
...

Sollte dort auch ein Benutzerzähler angezeigt werden?

Ich habe es auch mit staged: false versucht, und die gleiche Ausgabe wurde angezeigt. Keine der Mailinglisten-Benutzer befindet sich in irgendeiner Gruppe. Falls es hilfreich ist zu sehen, was tatsächlich verarbeitet wird, hier ist eine der vielen .mbox-Dateien, die importiert wird:

2020-December.zip (49,5 KB)

Die einzige nicht-standardmäßige Einstellung war das Hinzufügen von:

tags:
  "Mne_analysis": "mne_analysis"

Es wäre toll, wenn diese Benutzer als gestaffelt angezeigt würden, damit sie bei der Registrierung ihre alten Beiträge beanspruchen können. Daher sind alle Tipps oder Ideen willkommen!

1 „Gefällt mir“

Es sollte wahrscheinlich einfach beides akzeptieren?