Skip to content

Commit

Permalink
Added input report maildir connector, issue #82 (#555)
Browse files Browse the repository at this point in the history
Co-authored-by: Paolo Schiro <[email protected]>
  • Loading branch information
spaolo and Paolo Schiro authored Sep 6, 2024
1 parent b530d62 commit 7b7d20b
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 1 deletion.
4 changes: 4 additions & 0 deletions docs/source/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,10 @@ The full set of configuration options are:
- `port` - int: The port to use
- `mode` - str: The GELF transport type to use. Valid modes: `tcp`, `udp`, `tls`

- `maildir`
- `reports_folder` - str: Full path for mailbox maidir location (Default: `INBOX`)
- `maildir_create` - bool: Create maildir if not present (Default: False)

:::{warning}
It is **strongly recommended** to **not** use the `nameservers`
setting. By default, `parsedmarc` uses
Expand Down
23 changes: 22 additions & 1 deletion parsedmarc/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
parse_report_file, get_dmarc_reports_from_mbox, elastic, opensearch, \
kafkaclient, splunk, save_output, email_results, ParserError, \
__version__, InvalidDMARCReport, s3, syslog, loganalytics, gelf
from parsedmarc.mail import IMAPConnection, MSGraphConnection, GmailConnection
from parsedmarc.mail import IMAPConnection, MSGraphConnection, GmailConnection, \
MaildirConnection
from parsedmarc.mail.graph import AuthMethod

from parsedmarc.log import logger
Expand Down Expand Up @@ -504,6 +505,8 @@ def process_reports(reports_):
gmail_api_paginate_messages=True,
gmail_api_scopes=[],
gmail_api_oauth2_port=8080,
maildir_path = None,
maildir_create = False,
log_file=args.log_file,
n_procs=1,
ip_db_path=None,
Expand Down Expand Up @@ -1008,6 +1011,13 @@ def process_reports(reports_):
opts.gmail_api_oauth2_port = \
gmail_api_config.get("oauth2_port", 8080)

if "maildir" in config.sections():
maildir_api_config = config["maildir"]
opts.maildir_path = \
maildir_api_config.get("maildir_path")
opts.maildir_create = \
maildir_api_config.get("maildir_create")

if "log_analytics" in config.sections():
log_analytics_config = config["log_analytics"]
opts.la_client_id = \
Expand Down Expand Up @@ -1072,6 +1082,7 @@ def process_reports(reports_):
if opts.imap_host is None \
and opts.graph_client_id is None \
and opts.gmail_api_credentials_file is None \
and opts.maildir_path is None \
and len(opts.file_path) == 0:
logger.error("You must supply input files or a mailbox connection")
exit(1)
Expand Down Expand Up @@ -1380,6 +1391,16 @@ def process_reports(reports_):
logger.exception("Gmail API Error")
exit(1)

if opts.maildir_path:
try:
mailbox_connection = MaildirConnection(
maildir_path=opts.maildir_path,
maildir_create=opts.maildir_create,
)
except Exception:
logger.exception("Maildir Error")
exit(1)

if mailbox_connection:
try:
reports = get_dmarc_reports_from_mailbox(
Expand Down
60 changes: 60 additions & 0 deletions parsedmarc/mail/maildir.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from time import sleep

#from imapclient.exceptions import IMAPClientError
#from mailsuite.imap import IMAPClient
from socket import timeout

from parsedmarc.log import logger
from parsedmarc.mail.mailbox_connection import MailboxConnection
#import email
import mailbox
import os

class MaildirConnection(MailboxConnection):
def __init__(self,
maildir_path=None,
maildir_create=False,
):
self._maildir_path = maildir_path
self._maildir_create = maildir_create
maildir_owner=os.stat(maildir_path).st_uid
if os.getuid() != maildir_owner:
if os.getuid() == 0:
logger.warning("Switching uid to {} to access Maildir".format(maildir_owner))
os.setuid(maildir_owner)
else:
raise Exception('runtime uid {} differ from maildir {} owner {}'.format(os.getuid().maildir_path,maildir_owner))
self._client = mailbox.Maildir(maildir_path, create=maildir_create)
self._subfolder_client={}

def create_folder(self, folder_name: str):
self._subfolder_client[folder_name]=self._client.add_folder(folder_name)
self._client.add_folder(folder_name)

def fetch_messages(self, reports_folder: str, **kwargs):
return self._client.keys()

def fetch_message(self, message_id):
return self._client.get(message_id).as_string()

def delete_message(self, message_id: str):
self._client.remove(message_id)

def move_message(self, message_id: str, folder_name: str):
message_data=self._client.get(message_id)
if folder_name not in self._subfolder_client.keys():
self._subfolder_client = mailbox.Maildir(os.join(maildir_path,folder_name), create=maildir_create)
self._subfolder_client[folder_name].add(message_data)
self._client.remove(message_id)

def keepalive(self):
return

def watch(self, check_callback, check_timeout):
while True:
try:
check_callback(self)
except Exception as e:
logger.warning("Maildir init error. {0}".format(e))
sleep(check_timeout)

0 comments on commit 7b7d20b

Please sign in to comment.