fix(postfach): Zeitgrenze gilt auch in Folgelaeufen des Erstabgleichs

Lehnt Graph den Serverfilter ab, laeuft der Erstabgleich ohne Filter - und zieht
sich dann ueber mehrere Laeufe. Der Merker dafuer galt nur im ersten Lauf, in
allen folgenden waere der Rest des Postfachs trotz eingestellter Grenze
hereingekommen. Die Grenze wird jetzt immer geprueft, und zwar nur fuer noch
unbekannte Mails: eine bereits gespiegelte Mail soll auch dann aktualisiert
werden, wenn sie aus dem Zeitfenster gelaufen ist.

insertCandidates() gibt die Zeilen jetzt in der Form der Datenbank zurueck. Die
Umformung an der Aufrufstelle waere bei jedem neuen Feld still auseinandergelaufen
und haette es bei der automatischen Uebernahme verloren.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sascha Wolf
2026-08-11 00:08:33 +02:00
co-authored by Claude Opus 5
parent 6fd713497d
commit 8090d0aae1
3 changed files with 60 additions and 65 deletions
+26 -22
View File
@@ -158,39 +158,43 @@ const CANDIDATE_COLUMNS = [
/**
* Vorschlaege zu einer Mail speichern. INSERT IGNORE zusammen mit dem
* Unique-Schluessel (message_id, dedupe_hash) macht den Aufruf wiederholbar.
* Zurueck kommen die tatsaechlich neu angelegten Zeilen.
*
* Zurueck kommen die tatsaechlich neu angelegten Zeilen - und zwar in der Form
* der Datenbank (snake_case), damit sie direkt an adoptCandidate() weitergegeben
* werden koennen. Eine Umformung an der Aufrufstelle wuerde bei jedem neuen Feld
* still auseinanderlaufen.
*/
export async function insertCandidates(messageId, candidates) {
const created = [];
for (const candidate of candidates) {
const values = [
messageId,
candidate.dedupeHash,
candidate.firstName,
candidate.lastName,
candidate.salutation,
candidate.email,
candidate.phone,
candidate.mobile,
candidate.company,
candidate.position,
candidate.street,
candidate.zip,
candidate.city,
candidate.website,
candidate.linkedin,
candidate.origin,
candidate.confidence,
];
const row = {
message_id: messageId,
dedupe_hash: candidate.dedupeHash,
first_name: candidate.firstName,
last_name: candidate.lastName,
salutation: candidate.salutation,
email: candidate.email,
phone: candidate.phone,
mobile: candidate.mobile,
company: candidate.company,
position: candidate.position,
street: candidate.street,
zip: candidate.zip,
city: candidate.city,
website: candidate.website,
linkedin: candidate.linkedin,
origin: candidate.origin,
confidence: candidate.confidence,
};
const [result] = await pool.query(
`INSERT IGNORE INTO crm_mail_contact_candidates (${CANDIDATE_COLUMNS.join(', ')})
VALUES (${CANDIDATE_COLUMNS.map(() => '?').join(', ')})`,
values
CANDIDATE_COLUMNS.map((column) => row[column])
);
if (result.affectedRows > 0) created.push({ id: result.insertId, ...candidate });
if (result.affectedRows > 0) created.push({ id: result.insertId, ...row });
}
return created;