@@ -440,10 +440,16 @@ def create_segmentation_regex_list() -> Iterable[str]:
440440 List of segmentation regexs
441441
442442 """
443+ # Match everything until the end of the line.
444+ tolerant_line_start = r"^.{,5}"
445+ semicolon_pattern = r" ?\n? ?: *\n?"
446+ dash_pattern = r"(?:[\n ]*--+)"
447+ # Match anything until first line break and following line breaks
448+ end_pattern = r"[^\n]*\n[\n ]*"
449+
443450 # Meta patterns of the form "META_KEYWORD : META_CONTENT"
444451 # Ex: "De : jean@gmail.com"
445- meta_keywords_list_with_semicolon = [
446- r"Date" ,
452+ mandatory_meta_keywords_list_with_semicolon = [
447453 r"De" ,
448454 r"Exp[ée]diteur" ,
449455 r"[ÀA]" ,
@@ -455,26 +461,47 @@ def create_segmentation_regex_list() -> Iterable[str]:
455461 r"To" ,
456462 r"Sent" ,
457463 r"Cc" ,
464+ ]
465+ optional_meta_keywords_list_with_semicolon = [
466+ r"Date" ,
458467 r"Copie" ,
459468 r"Attachments" ,
469+ r"Objet" ,
470+ r"Object" ,
471+ r"Subject" ,
472+ r"Sujet" ,
460473 ]
461- piped_keywords_with_semicolon = "(?:" + "|" .join (meta_keywords_list_with_semicolon ) + ")"
462- # Ajout d'un pattern pour gérer les cas sans ':' mais avec retour à la ligne
463- starter_pattern_with_semicolon = rf"^.{{,5}}(?:{ piped_keywords_with_semicolon } ?\n? ?: *\n?)"
464- starter_pattern_with_newline = rf"^.{{,5}}(?:{ piped_keywords_with_semicolon } )\n"
474+ mandatory_pattern = (
475+ "(?:"
476+ + tolerant_line_start
477+ + "(?:"
478+ + "|" .join (mandatory_meta_keywords_list_with_semicolon )
479+ + ")"
480+ + semicolon_pattern
481+ + ")"
482+ )
483+ optional_pattern = (
484+ "(?:"
485+ + tolerant_line_start
486+ + "(?:"
487+ + "|" .join (optional_meta_keywords_list_with_semicolon )
488+ + ")"
489+ + semicolon_pattern
490+ + ")"
491+ )
465492
466493 # Meta patterns of the form "META_KEYWORD"
467494 # Ex: "Transféré par jean@gmail.com"
468495 # (pas de ":")
469496 # Ex: "------ Message transmis ------"
470497
471498 regex_weekdays = (
472- r"(?:[Ll]undi|[Ll]un\.|[Mm]ardi|[Mm]ar\.|[Mm]ercredi|[Mm]er\.|[Jj]eudi|[Jj]eu\.|" # noqa
473- r"[Vv]endredi|[Vv]en\.|[Ss]amedi|[Ss]am\.|[Dd]imanche|[Dd]im\.)" # noqa
499+ r"(?:[Ll]undi|[Ll]un\.|[Mm]ardi|[Mm]ar\.|[Mm]ercredi|[Mm]er\.|[Jj]eudi|[Jj]eu\.|"
500+ r"[Vv]endredi|[Vv]en\.|[Ss]amedi|[Ss]am\.|[Dd]imanche|[Dd]im\.)"
474501 )
475502 regex_months = (
476- r"(?:[Jj]anvier|[Ff][ée]vrier|[Mm]ars|[Aa]vril|[Mm]ai|[Jj]uin|[Jj]uillet|" # noqa
477- r"[Aa]o[ûu]t|[Ss]eptembre|[Oo]ctobre|[Nn]ovembre|[Dd][eé]cembre|" # noqa
503+ r"(?:[Jj]anvier|[Ff][ée]vrier|[Mm]ars|[Aa]vril|[Mm]ai|[Jj]uin|[Jj]uillet|"
504+ r"[Aa]o[ûu]t|[Ss]eptembre|[Oo]ctobre|[Nn]ovembre|[Dd][eé]cembre|"
478505 r"(?:janv?|f[ée]vr?|mar|avr|juil?|sept?|oct|nov|d[ée]c)\.)"
479506 )
480507
@@ -483,10 +510,10 @@ def create_segmentation_regex_list() -> Iterable[str]:
483510 # Le 02 juillet 1991 à 11:20 jane@gmail.fr a écrit :
484511 # Le mardi 31 août 2021 à 11:09, <ville@maif.fr> a écrit :
485512 (
486- rf "\bLe (?:"
487- rf"\d{{2}}/\d{{2}}/\d{{4}}|\d{{4}}-\d{{2}}-\d{{2}}|{ regex_weekdays } |" # noqa
513+ r "\bLe (?:"
514+ rf"\d{{2}}/\d{{2}}/\d{{4}}|\d{{4}}-\d{{2}}-\d{{2}}|{ regex_weekdays } |"
488515 rf"\d{{1,2}} { regex_months } )(?:.|\n)"
489- rf"{{ ,30}} \d{{2}} :\d{{2}} (?:.|\n){{ ,50}} (?:\<.{{ ,30}} \>.{{ ,5}} )?\ba [éecrit]" # noqa
516+ r"{ ,30}\d{2} :\d{2} (?:.|\n){,50}(?:\<.{,30}\>.{,5})?\ba [ée]crit"
490517 ),
491518 r"Transf[ée]r[ée] par" ,
492519 r"D[ée]but du message transf[ée]r[ée] :" ,
@@ -500,22 +527,22 @@ def create_segmentation_regex_list() -> Iterable[str]:
500527 r"Forwarded by" ,
501528 ]
502529 piped_keywords_without_semicolon = "(?:" + "|" .join (meta_keywords_list_without_semicolon ) + ")" # noqa
503- starter_pattern_without_semicolon = f"{ piped_keywords_without_semicolon } (?:[\n ]*--+)?"
504530
505- # Combine pattern with and without semicolon, et avec retour à la ligne
506- starter_pattern = (
507- rf"(?:{ starter_pattern_with_semicolon } |{ starter_pattern_with_newline } |{ starter_pattern_without_semicolon } )"
531+ mandatory_pattern_without_semicolon = (
532+ "(?:" + "(?:" + "|" .join (meta_keywords_list_without_semicolon ) + ")" + rf"{ dash_pattern } ?" + ")"
508533 )
509534
510- # Match everything until the end of the line.
511- # Match End of line "\n" and "space" characters
512- end_pattern = r".*[\n ]*"
535+ # Must match at least one mandatory pattern (ex: "De :) and any optional patterns. Exemple :
536+ # Copy : blabla (optional)
537+ # De : test_from@maif.fr (mandatory)
538+ # A : test_to@maif.fr (mandatory)
539+ # Attachments : test.pdf, blop.png (optional)
540+ # Cc : test_cc@gmail.co (mandatory)
541+ any_line = rf"(?:(?:{ optional_pattern } |{ mandatory_pattern } |{ mandatory_pattern_without_semicolon } ){ end_pattern } )"
542+ mandatory_line = rf"(?:(?:{ mandatory_pattern_without_semicolon } |{ mandatory_pattern } ){ end_pattern } )"
543+
544+ full_generic_meta_pattern = rf"{ any_line } *{ mandatory_line } { any_line } *"
513545
514- # Object / Subject pattern (These patterns are not sufficient to trigger segmentation)
515- object_line_pattern = "(?:^.{,5}(?:Objet|Subject|Sujet) ?\n ? ?: *\n ?)" + end_pattern
516- full_generic_meta_pattern = (
517- rf"(?:(?:{ object_line_pattern } )?{ starter_pattern } { end_pattern } (?:{ object_line_pattern } )*)+"
518- )
519546 pattern_list = (full_generic_meta_pattern ,)
520547 return pattern_list
521548
@@ -1233,10 +1260,15 @@ def GREETINGS(self) -> str | list[str] | re.Pattern:
12331260 r"^.{0,3}Bonne r[ée]ception.{0,3}$" ,
12341261 r"^.{0,3}votre bien d[ée]vou[ée]e?.{0,3}$" ,
12351262 r"^.{0,3}amicalement votre.{0,3}$" ,
1263+ (
1264+ r"^.{0,3}(?:Je|Nous) vous pri(?:e|ons) d'(?:agr[ée]er|accepter)(.{0,4}madame)?(.{0,4}monsieur)?"
1265+ r"(?:.{0,50}(consideration|salutations|sentiments).{0,20})?.{0,10}$"
1266+ ),
12361267 (
12371268 r"^.{,3}je vous prie de croire.{,50}"
12381269 r"(expression|assurance)?.{,50}(consideration|salutations|sentiments).{,30}$"
12391270 ),
1271+ r"^.{0,3}(expression|assurance)?.{,50}(consideration|salutations|sentiments).{,30}$" ,
12401272 # English
12411273 r"^.{0,3}regards.{0,3}$" ,
12421274 r"^.{0,3}(best|warm|kind|my) *(regards|wishes)?.{0,3}$" ,
0 commit comments