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 */