Skip to content

Commit 39ec9fc

Browse files
authored
enh: collector_mail_attach allow_empty (#2647)
* enh: collector_mail_attach allow_empty
1 parent d2cac08 commit 39ec9fc

File tree

7 files changed

+71
-1
lines changed

7 files changed

+71
-1
lines changed

.reuse/dep5

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,7 @@ License: AGPL-3.0-or-later
4545
Files: intelmq/tests/bots/collectors/mail/gpg_ring/**
4646
Copyright: 2025 Edvard Rejthar, CSIRT.cz <[email protected]>
4747
License: AGPL-3.0-or-later
48+
49+
Files: intelmq/tests/bots/collectors/mail/text_attachment_empty.eml
50+
Copyright: 2025 Edvard Rejthar, CSIRT.cz <[email protected]>
51+
License: AGPL-3.0-or-later

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ Please refer to the [NEWS](NEWS.md) for a list of changes which have an affect o
4444
### Bots
4545
#### Collectors
4646
- `intelmq.bots.collectors.mail.collector_mail_attach`: Decrypt GPG attachments (PR#2623 by Edvard Rejthar).
47+
- `intelmq.bots.collectors.mail.collector_mail_attach`: Allow empty attachments (PR#2647 by Edvard Rejthar).
4748
- `intelmq.bots.collectors.shodan.collector_alert`: Added a new collector to query the Shodan Alert API (PR#2618 by Sebastian Wagner and Malawi CERT).
4849
- Remove `intelmq.bots.collectors.blueliv` as it uses an unmaintained library, does not work any more and breaks other CI tests (fixes #2593, PR#2632 by Sebastian Wagner).
4950

docs/user/bots.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,10 @@ The fields can be used by parsers to identify the feed and are not automatically
494494

495495
(optional, string) The OpenPGP private key passhrase.
496496

497+
**`allow_empty`**
498+
499+
(optional, boolean) Allow the attachment to be empty. If False (default), an error is raised and bot stays stopped.
500+
497501
**`gpg_home`**
498502

499503
(optional, string) Change the GPG home directory.

intelmq/bots/collectors/mail/collector_mail_attach.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ class MailAttachCollectorBot(MailCollectorBot):
3939
gpg_home: str = ""
4040
""" Change the GPG home directory """
4141

42+
allow_empty: bool = False
43+
""" Allow the attachment to be empty. If False, an error is raised and bot stays stopped. """
44+
4245
def init(self):
4346
super().init()
4447
if self.attach_regex is None:
@@ -88,6 +91,11 @@ def process_message(self, uid, message):
8891
else:
8992
self.logger.error('Could not decrypt attachment %s: %s.', file_name, gpg.status)
9093
continue
94+
95+
if not raw_report and self.allow_empty:
96+
self.logger.info("Empty email report ignored.")
97+
return True
98+
9199
report = self.new_report()
92100
report.add("raw", raw_report)
93101
if file_name:

intelmq/tests/bots/collectors/mail/lib.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
EMAIL_FAKE_ATTACHMENT = parse_email((Path(__file__).parent / 'fake_attachment.eml').read_text())
2020
EMAIL_TEXT_ATTACHMENT = parse_email((Path(__file__).parent / 'text_attachment.eml').read_text())
2121
EMAIL_GPG_ATTACHMENT = parse_email((Path(__file__).parent / 'gpg_attachment.eml').read_text())
22+
EMAIL_TEXT_ATTACHMENT_EMPTY = parse_email((Path(__file__).parent / 'text_attachment_empty.eml').read_text())
2223

2324

2425
class MockedImbox():
@@ -59,3 +60,7 @@ def messages(self, *args, **kwargs):
5960
class MockedGpgAttachmentImbox(MockedImbox):
6061
def messages(self, *args, **kwargs):
6162
yield 0, deepcopy(EMAIL_GPG_ATTACHMENT)
63+
64+
class MockedEmptyTextAttachmentImbox(MockedImbox):
65+
def messages(self, *args, **kwargs):
66+
yield 0, deepcopy(EMAIL_TEXT_ATTACHMENT_EMPTY)

intelmq/tests/bots/collectors/mail/test_collector_attach.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@
1616

1717
from intelmq.bots.collectors.mail.collector_mail_attach import MailAttachCollectorBot
1818
from intelmq.lib.utils import base64_encode
19+
from intelmq.lib.exceptions import PipelineError
1920
if os.getenv('INTELMQ_TEST_EXOTIC'):
20-
from .lib import MockedZipImbox, MockedBadAttachmentImbox, MockedTextAttachmentImbox, MockedGpgAttachmentImbox
21+
from .lib import MockedZipImbox, MockedBadAttachmentImbox, MockedTextAttachmentImbox, MockedGpgAttachmentImbox, MockedEmptyTextAttachmentImbox
2122

2223
REPORT_FOOBARZIP = {
2324
'__type': 'Report',
@@ -82,6 +83,19 @@ def test_text_attachment(self):
8283
'extract_files': False})
8384
self.assertMessageEqual(0, REPORT_FOOBARTXT)
8485

86+
def test_text_attachment_empty(self):
87+
# without allow_empty, the parsing fails
88+
with mock.patch('imbox.Imbox', new=MockedEmptyTextAttachmentImbox), self.assertRaises(PipelineError):
89+
self.run_bot(parameters={'attach_regex': '.*.txt$',
90+
'extract_files': False,
91+
'allow_empty': False})
92+
93+
with mock.patch('imbox.Imbox', new=MockedEmptyTextAttachmentImbox):
94+
self.run_bot(parameters={'attach_regex': '.*.txt$',
95+
'extract_files': False,
96+
'allow_empty': True})
97+
self.assertOutputQueueLen(0)
98+
8599

86100
def _make_ring(self):
87101
temp_gnupg_dir = mkdtemp(prefix="gnupg-temp-")
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
2+
From: Sebastian Wagner <[email protected]>
3+
Subject: foobar zip
4+
Message-ID: <[email protected]>
5+
Date: Tue, 3 Sep 2019 16:57:40 +0200
6+
MIME-Version: 1.0
7+
Content-Type: multipart/mixed;
8+
boundary="------------1D845FBEEAAC1F68B4B45905"
9+
Content-Language: en-US
10+
11+
This is a multi-part message in MIME format.
12+
--------------1D845FBEEAAC1F68B4B45905
13+
Content-Type: text/html; charset=utf-8
14+
Content-Transfer-Encoding: 8bit
15+
16+
<html>
17+
<head>
18+
19+
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
20+
</head>
21+
<body text="#000000" bgcolor="#FFFFFF">
22+
Please look at the attachment<br>
23+
</body>
24+
</html>
25+
26+
--------------1D845FBEEAAC1F68B4B45905
27+
Content-Type: text/plain; charset=UTF-8;
28+
name="foobar.txt"
29+
Content-Transfer-Encoding: base64
30+
Content-Disposition: attachment;
31+
filename="foobar.txt"
32+
33+
34+
--------------1D845FBEEAAC1F68B4B45905--

0 commit comments

Comments
 (0)