libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

test_mbox.c (9170B)


      1 /*
      2      This file is part of libextractor.
      3      Copyright (C) 2026 Vidyut Samanta and Christian Grothoff
      4 
      5      libextractor is free software; you can redistribute it and/or modify
      6      it under the terms of the GNU General Public License as published
      7      by the Free Software Foundation; either version 3, or (at your
      8      option) any later version.
      9 
     10      libextractor is distributed in the hope that it will be useful, but
     11      WITHOUT ANY WARRANTY; without even the implied warranty of
     12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13      General Public License for more details.
     14 
     15      You should have received a copy of the GNU General Public License
     16      along with libextractor; see the file COPYING.  If not, write to the
     17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18      Boston, MA 02110-1301, USA.
     19 */
     20 /**
     21  * @file plugins/test_mbox.c
     22  * @brief testcase for the mbox plugin
     23  * @author Christian Grothoff
     24  */
     25 #include "platform.h"
     26 #include "test_lib.h"
     27 
     28 
     29 /**
     30  * Main function for the mbox testcase.
     31  *
     32  * The mailbox comes from `contrib/gen_mbox_testdata.sh'.  The
     33  * assertions that matter are the ones a lazier parser would get wrong:
     34  * the RFC 2047 subject (base64 UTF-8 and quoted-printable ISO-8859-1 in
     35  * one field, with the white space between the two encoded words
     36  * removed), the RFC 5322 date converted from +0100 to UTC, the three
     37  * IP literals out of the Received chain plus the one from
     38  * X-Originating-IP, the DKIM signing domain, and the attachment name
     39  * that only exists as two RFC 2231 continuation segments.
     40  *
     41  * @param argc number of arguments (ignored)
     42  * @param argv arguments (ignored)
     43  * @return 0 on success
     44  */
     45 int
     46 main (int argc, char *argv[])
     47 {
     48   struct SolutionData mbox_sol[] = {
     49     {
     50       EXTRACTOR_METATYPE_MIMETYPE,
     51       EXTRACTOR_METAFORMAT_UTF8,
     52       "text/plain",
     53       "application/mbox",
     54       strlen ("application/mbox") + 1,
     55       0
     56     },
     57     /* the route, most recent hop first, cut at the receiving MTA's
     58        timestamp but otherwise untouched */
     59     {
     60       EXTRACTOR_METATYPE_RECEIVED_FROM,
     61       EXTRACTOR_METAFORMAT_UTF8,
     62       "text/plain",
     63       "from mx1.example.net (mx1.example.net [198.51.100.24])"
     64       " by mail.example.org (Postfix) with ESMTPS id 4B7f2Z1qJz3xYm"
     65       " for <bob@example.org>",
     66       strlen ("from mx1.example.net (mx1.example.net [198.51.100.24])"
     67               " by mail.example.org (Postfix) with ESMTPS id"
     68               " 4B7f2Z1qJz3xYm for <bob@example.org>") + 1,
     69       0
     70     },
     71     {
     72       EXTRACTOR_METATYPE_RECEIVED_FROM,
     73       EXTRACTOR_METAFORMAT_UTF8,
     74       "text/plain",
     75       "from smtp6.example.net (smtp6.example.net"
     76       " [IPv6:2001:db8:1234::a5]) by mx1.example.net (Postfix) with"
     77       " ESMTPS id 77aa88bb99cc for <bob@example.org>",
     78       strlen ("from smtp6.example.net (smtp6.example.net"
     79               " [IPv6:2001:db8:1234::a5]) by mx1.example.net (Postfix)"
     80               " with ESMTPS id 77aa88bb99cc for <bob@example.org>") + 1,
     81       0
     82     },
     83     {
     84       EXTRACTOR_METATYPE_RECEIVED_FROM,
     85       EXTRACTOR_METAFORMAT_UTF8,
     86       "text/plain",
     87       "from wsbeta.corp.example.com (unknown [203.0.113.77])"
     88       " by mx1.example.net (Postfix) with ESMTPSA id 9C1a4F0d7b"
     89       " for <bob@example.org>",
     90       strlen ("from wsbeta.corp.example.com (unknown [203.0.113.77])"
     91               " by mx1.example.net (Postfix) with ESMTPSA id 9C1a4F0d7b"
     92               " for <bob@example.org>") + 1,
     93       0
     94     },
     95     /* =?UTF-8?B?QW5uYSBNw7xsbGVy?= */
     96     {
     97       EXTRACTOR_METATYPE_AUTHOR_NAME,
     98       EXTRACTOR_METAFORMAT_UTF8,
     99       "text/plain",
    100       "Anna M\xc3\xbcller",
    101       strlen ("Anna M\xc3\xbcller") + 1,
    102       0
    103     },
    104     {
    105       EXTRACTOR_METATYPE_AUTHOR_EMAIL,
    106       EXTRACTOR_METAFORMAT_UTF8,
    107       "text/plain",
    108       "anna.mueller@example.com",
    109       strlen ("anna.mueller@example.com") + 1,
    110       0
    111     },
    112     {
    113       EXTRACTOR_METATYPE_RECIPIENT,
    114       EXTRACTOR_METAFORMAT_UTF8,
    115       "text/plain",
    116       "Bob Jones <bob@example.org>",
    117       strlen ("Bob Jones <bob@example.org>") + 1,
    118       0
    119     },
    120     {
    121       EXTRACTOR_METATYPE_RECIPIENT,
    122       EXTRACTOR_METAFORMAT_UTF8,
    123       "text/plain",
    124       "carol@example.org",
    125       strlen ("carol@example.org") + 1,
    126       0
    127     },
    128     /* from Cc: */
    129     {
    130       EXTRACTOR_METATYPE_RECIPIENT,
    131       EXTRACTOR_METAFORMAT_UTF8,
    132       "text/plain",
    133       "dave@example.org",
    134       strlen ("dave@example.org") + 1,
    135       0
    136     },
    137     /* base64/UTF-8 word, then a quoted-printable ISO-8859-1 word; the
    138        white space between the two must have been dropped */
    139     {
    140       EXTRACTOR_METATYPE_SUBJECT,
    141       EXTRACTOR_METAFORMAT_UTF8,
    142       "text/plain",
    143       "\xc3\x9c" "berweisung M\xc3\xa4rz 2024 Beleg",
    144       strlen ("\xc3\x9c" "berweisung M\xc3\xa4rz 2024 Beleg") + 1,
    145       0
    146     },
    147     {
    148       EXTRACTOR_METATYPE_TITLE,
    149       EXTRACTOR_METAFORMAT_UTF8,
    150       "text/plain",
    151       "\xc3\x9c" "berweisung M\xc3\xa4rz 2024 Beleg",
    152       strlen ("\xc3\x9c" "berweisung M\xc3\xa4rz 2024 Beleg") + 1,
    153       0
    154     },
    155     /* Date: Tue, 12 Mar 2024 09:41:07 +0100 */
    156     {
    157       EXTRACTOR_METATYPE_CREATION_DATE,
    158       EXTRACTOR_METAFORMAT_UTF8,
    159       "text/plain",
    160       "2024-03-12T08:41:07Z",
    161       strlen ("2024-03-12T08:41:07Z") + 1,
    162       0
    163     },
    164     /* the right-hand side is the composing workstation's name */
    165     {
    166       EXTRACTOR_METATYPE_MESSAGE_ID,
    167       EXTRACTOR_METAFORMAT_UTF8,
    168       "text/plain",
    169       "20240312084107.9C1a4F0d7b@wsbeta.corp.example.com",
    170       strlen ("20240312084107.9C1a4F0d7b@wsbeta.corp.example.com") + 1,
    171       0
    172     },
    173     {
    174       EXTRACTOR_METATYPE_IN_REPLY_TO,
    175       EXTRACTOR_METAFORMAT_UTF8,
    176       "text/plain",
    177       "20240311150122.A1B2C3@mail.example.net",
    178       strlen ("20240311150122.A1B2C3@mail.example.net") + 1,
    179       0
    180     },
    181     {
    182       EXTRACTOR_METATYPE_IP_ADDRESS,
    183       EXTRACTOR_METAFORMAT_UTF8,
    184       "text/plain",
    185       "198.51.100.24",
    186       strlen ("198.51.100.24") + 1,
    187       0
    188     },
    189     /* out of an `[IPv6:...]' literal */
    190     {
    191       EXTRACTOR_METATYPE_IP_ADDRESS,
    192       EXTRACTOR_METAFORMAT_UTF8,
    193       "text/plain",
    194       "2001:db8:1234::a5",
    195       strlen ("2001:db8:1234::a5") + 1,
    196       0
    197     },
    198     {
    199       EXTRACTOR_METATYPE_IP_ADDRESS,
    200       EXTRACTOR_METAFORMAT_UTF8,
    201       "text/plain",
    202       "203.0.113.77",
    203       strlen ("203.0.113.77") + 1,
    204       0
    205     },
    206     /* out of X-Originating-IP, which is not bracketed the same way */
    207     {
    208       EXTRACTOR_METATYPE_IP_ADDRESS,
    209       EXTRACTOR_METAFORMAT_UTF8,
    210       "text/plain",
    211       "192.0.2.153",
    212       strlen ("192.0.2.153") + 1,
    213       0
    214     },
    215     {
    216       EXTRACTOR_METATYPE_CREATED_BY_SOFTWARE,
    217       EXTRACTOR_METAFORMAT_UTF8,
    218       "text/plain",
    219       "Microsoft Outlook 16.0",
    220       strlen ("Microsoft Outlook 16.0") + 1,
    221       0
    222     },
    223     /* the `d=' tag of the DKIM-Signature */
    224     {
    225       EXTRACTOR_METATYPE_SIGNER,
    226       EXTRACTOR_METAFORMAT_UTF8,
    227       "text/plain",
    228       "example.com",
    229       strlen ("example.com") + 1,
    230       0
    231     },
    232     {
    233       EXTRACTOR_METATYPE_COMMENT,
    234       EXTRACTOR_METAFORMAT_UTF8,
    235       "text/plain",
    236       "Authentication-Results: mail.example.org; dkim=pass"
    237       " header.d=example.com; spf=pass smtp.mailfrom=example.com",
    238       strlen ("Authentication-Results: mail.example.org; dkim=pass"
    239               " header.d=example.com; spf=pass"
    240               " smtp.mailfrom=example.com") + 1,
    241       0
    242     },
    243     {
    244       EXTRACTOR_METATYPE_ORGANIZATION,
    245       EXTRACTOR_METAFORMAT_UTF8,
    246       "text/plain",
    247       "Example GmbH",
    248       strlen ("Example GmbH") + 1,
    249       0
    250     },
    251     {
    252       EXTRACTOR_METATYPE_FORMAT,
    253       EXTRACTOR_METAFORMAT_UTF8,
    254       "text/plain",
    255       "multipart/mixed",
    256       strlen ("multipart/mixed") + 1,
    257       0
    258     },
    259     {
    260       EXTRACTOR_METATYPE_COMMENT,
    261       EXTRACTOR_METAFORMAT_UTF8,
    262       "text/plain",
    263       "MIME boundary: =_boundary_42",
    264       strlen ("MIME boundary: =_boundary_42") + 1,
    265       0
    266     },
    267     {
    268       EXTRACTOR_METATYPE_FILENAME,
    269       EXTRACTOR_METAFORMAT_UTF8,
    270       "text/plain",
    271       "Kontoauszug_2024-03.pdf",
    272       strlen ("Kontoauszug_2024-03.pdf") + 1,
    273       0
    274     },
    275     /* only present as `filename*0=' + `filename*1=' */
    276     {
    277       EXTRACTOR_METATYPE_FILENAME,
    278       EXTRACTOR_METAFORMAT_UTF8,
    279       "text/plain",
    280       "Reisekosten.xlsx",
    281       strlen ("Reisekosten.xlsx") + 1,
    282       0
    283     },
    284     /* the message is multipart, so the charset comes from its first
    285        part rather than from its own Content-Type */
    286     {
    287       EXTRACTOR_METATYPE_CHARACTER_SET,
    288       EXTRACTOR_METAFORMAT_UTF8,
    289       "text/plain",
    290       "ISO-8859-15",
    291       strlen ("ISO-8859-15") + 1,
    292       0
    293     },
    294     /* three messages: the `>From ' line in the third message's body is
    295        the mboxo escaping and must not have been counted */
    296     {
    297       EXTRACTOR_METATYPE_ENTRY_COUNT,
    298       EXTRACTOR_METAFORMAT_UTF8,
    299       "text/plain",
    300       "3",
    301       strlen ("3") + 1,
    302       0
    303     },
    304     { 0, 0, NULL, NULL, 0, -1 }
    305   };
    306   struct ProblemSet ps[] = {
    307     { "testdata/mbox_test.mbox",
    308       mbox_sol },
    309     { NULL, NULL }
    310   };
    311 
    312   (void) argc;
    313   (void) argv;
    314   return ET_main ("mbox", ps);
    315 }
    316 
    317 
    318 /* end of test_mbox.c */