This commit is contained in:
Shelvacu
2024-12-15 23:13:24 -08:00
committed by Shelvacu on fw
parent ee5f299d21
commit b5ab4d6fc7
4 changed files with 150 additions and 27 deletions

View File

@@ -96,9 +96,20 @@
namespace {
separator = .
inbox = yes
mailbox MagicRefilter {
auto = create
}
}
# mail_debug = yes
mail_debug = yes
mail_plugins = $mail_plugins notify mail_log
plugin {
sieve_trace_debug = yes
mail_log_events = delete undelete expunge save copy mailbox_create mailbox_delete mailbox_rename flag_change
mail_log_fields = uid box msgid size from
}
'';
};
}

View File

@@ -141,9 +141,60 @@ let
"variables",
"date",
"index",
"envelope",
"ihave"
];
if ihave "vnd.dovecot.debug" {
debug_log "debug log is available";
if environment :matches "location" "*" {
debug_log "environment ''${1}";
}
if environment :matches "phase" "*" {
debug_log "phase ''${1}";
}
}
if ihave "imapsieve" {
if ihave "vnd.dovecot.debug" {
debug_log "do have imapsieve";
}
if environment :matches "imap.cause" "*" {
set "imap_cause" "''${1}";
} else {
set "imap_cause" "notexist";
}
if environment :matches "imap.mailbox" "*" {
set "imap_mailbox" "''${1}";
} else {
set "imap_mailbox" "notexist";
}
if ihave "vnd.dovecot.debug" {
debug_log "imap_cause is ''${imap_cause}";
debug_log "imap_mailbox is ''${imap_mailbox}";
}
if allof(
environment :is "imap.cause" ["APPEND", "COPY", ""],
environment :is "imap.mailbox" ["MagicRefilter", ""]
) {
if ihave "vnd.dovecot.debug" {
debug_log "doing something";
}
} else {
if ihave "vnd.dovecot.debug" {
debug_log "NOT doing anything cuz imap.cause and/or imap.mailbox isn't right";
}
# the correct way to not do nothing depends on whether we're imap-triggered or message-delivery-triggered
if allof(
environment :is "location" "MS",
environment :is "phase" "post"
) {
discard;
}
stop;
}
} else {
if ihave "vnd.dovecot.debug" {
debug_log "dont have imapsieve (again)";
}
}
${set_envelope}
${set_var_from_environment "location" "env_location"}
@@ -158,9 +209,30 @@ let
if currentdate :matches "iso8601" "*" {
set "datetime" "''${1}";
}
addheader "X-Vacu-Sieved" "at ''${datetime} by ${config.vacu.versionId} loc ''${env_location} phase ''${env_phase} user ''${env_imap_user} email ''${env_imap_email} cause ''${env_imap_cause} mailbox ''${env_imap_mailbox} changedflags ''${env_imap_changedflags} envelope ${interp dest}";
set "sieved_message" "at ''${datetime} by ${config.vacu.versionId} loc ''${env_location} phase ''${env_phase} user ''${env_imap_user} email ''${env_imap_email} cause ''${env_imap_cause} mailbox ''${env_imap_mailbox} changedflags ''${env_imap_changedflags} envelope ${interp dest}";
if ihave "vnd.dovecot.debug" {
debug_log "X-Vacu-Sieved: ''${sieved_message}";
}
if envelope :all :is "to" "shelvacu@liam.dis8.net" {
if ihave "envelope" {
if envelope :all :matches "to" "*@*" {
set "userfor" "''${1}";
} else {
error "i dunno what to do, theres no envelope";
}
}
elsif ihave "imapsieve" {
set "userfor" "''${env_imap_user}";
}
else {
error "dont have envelope or imapsieve, dunno what to do";
}
if string :is "''${userfor}" "shelvacu" {
addheader "X-Vacu-Sieved" "''${sieved_message}";
if ihave "imapsieve" {
discard;
}
if allof(
${envelope_is "amznbsns@shelvacu.com"},
header :contains "Subject" "Your Amazon.com order has shipped"
@@ -200,6 +272,9 @@ let
}
${concatStrings email_filters}
${concatStrings domain_filters}
else {
fileinto "INBOX";
}
}
# disable any sieve scripts that might want to run after this one
stop;
@@ -226,6 +301,8 @@ in
"-c" config.services.dovecot2.configFile
"-C" # force compilation
"-D" # enable sieve debugging
"-f" "some-rando@example.com"
"-a" "shelvacu@liam.dis8.net"
config.services.dovecot2.sieve.scripts.before
"/dev/null"
]}
@@ -238,6 +315,7 @@ in
"fileinto"
"mailbox"
"editheader"
"vnd.dovecot.debug"
];
scripts.before = pkgs.writeText "mainsieve" sieve_text;
};

View File

@@ -196,12 +196,8 @@ in
}
''
# flake8: noqa
# #!${pkgs.python311}/bin/python
import sys
sys.argv.insert(1, "${nodes.liam.networking.primaryIPAddress}")
#sys.path.append("${pkgs.python311Packages.imap-tools}/lib/python3.11/site-packages")
#sys.path.append("${pkgs.python311Packages.urllib3}/lib/python3.11/site-packages")
#sys.path.append("${pkgs.python311Packages.requests}/lib/python3.11/site-packages")
${builtins.readFile ./mailtest.py}
''
)
@@ -222,11 +218,23 @@ in
}")
checker.succeed("wget http://liam.dis8.net/.well-known/acme-challenge/test")
liam.wait_for_unit("postfix.service")
liam.wait_for_unit("dovecot2.service")
# workaround a bug in dovecot where moving to a not-yet-created but set-to-autocreate mailbox doesn't work
liam.succeed("doveadm mailbox create -A INBOX")
liam.succeed("doveadm mailbox create -A MagicRefilter")
liam.wait_for_unit("postfix.service")
relay.wait_for_unit("mailpit.service")
checks = """
# refilter doesnt activate on other folders
--mailfrom whoeve2@example.com --rcptto sieve2est@shelvacu.com --username shelvacu --imap-move-to INBOX --imap-dir INBOX
# test the sieve script is working
--mailfrom whoever@example.com --rcptto sievetest@shelvacu.com --username shelvacu --imap-dir com.shelvacu
# test refilter
--mailfrom whoeve2@example.com --rcptto sieve2est@shelvacu.com --username shelvacu --imap-move-to MagicRefilter --imap-dir com.shelvacu
# refilter doesnt activate on julie's
--mailfrom blarg@example.com --rcptto julie@shelvacu.com --username julie --imap-move-to MagicRefilter --imap-dir MagicRefilter
--mailfrom asshole-spammer@example.com --rcptto whatever@shelvacu.com --header "List-unsubscribe: whatver" --username shelvacu --expect-flag spamish --imap-dir "com.shelvacu.#spamish"
--mailfrom shipment-tracking@amazon.com --rcptto amznbsns@shelvacu.com --subject "Your Amazon.com order has shipped (#123-1234)" --username shelvacu --imap-dir com.shelvacu --expect-flag \\\\Seen --expect-flag auto-marked-read --expect-flag auto-amazon-ignore
@@ -239,8 +247,7 @@ in
--rcptto julie@shelvacu.com --username julie --imap-dir INBOX
--rcptto julie+stuff@shelvacu.com --username julie --imap-dir INBOX
# test the sieve script is working
--mailfrom whoever@example.com --rcptto sievetest@shelvacu.com --username shelvacu --imap-dir com.shelvacu
--rcptto shelvacu@shelvacu.com --username shelvacu
--rcptto julie@shelvacu.com --username julie

View File

@@ -6,6 +6,7 @@ import ssl
import argparse
import uuid
import requests
from typing import NamedTuple
parser = argparse.ArgumentParser()
parser.add_argument('host', type = str)
@@ -16,6 +17,7 @@ parser.add_argument('--header', action = 'append', default = [])
parser.add_argument('--submission', default = False, action='store_true')
parser.add_argument('--smtp-starttls', default = None, action='store_true')
parser.add_argument('--imap-insecure', default = False, action = 'store_true')
parser.add_argument('--imap-move-to')
parser.add_argument('--imap-dir', default = None)
parser.add_argument('--username')
parser.add_argument('--password')
@@ -96,37 +98,62 @@ if args.mailpit_url is not None:
else:
assert not found_message, "Message was received by the mailpit server when it wasn't supposed to be"
MessageInFolder = NamedTuple('MessageInFolder', [('message', imap_tools.message.MailMessage), ('folder', str)])
if args.expect == 'received' or args.expect == 'imap_error':
time.sleep(5)
print(f"looking for {msg_magic}")
try:
with imap_tools.MailBox(args.host, ssl_context = mk_ctx()).login(username, password) as mailbox:
def connection() -> imap_tools.MailBox:
return imap_tools.MailBox(args.host, ssl_context = mk_ctx()).login(username, password)
def find_messages(mailbox: imap_tools.MailBox) -> list[MessageInFolder]:
matching_messages = []
if args.imap_dir is None:
directories = [d.name for d in mailbox.folder.list()]
else:
directories = [args.imap_dir]
directories = []
for d in mailbox.folder.list():
if '\\Noselect' not in d.flags:
directories.append(d.name)
# print(f"directories is {directories!r}")
for imap_dir in directories:
print(f"checking in {imap_dir!r}")
# for d in mailbox.folder.list(imap_dir):
# if d.name != imap_dir:
# directories.append(d.name)
try:
mailbox.folder.set(imap_dir)
except imap_tools.errors.MailboxFolderSelectError as e:
# print(f"failed to select folder {e!r}")
continue
for msg in mailbox.fetch():
mailbox.folder.set(imap_dir)
# except imap_tools.errors.MailboxFolderSelectError as e:
# # print(f"failed to select folder {e!r}")
# continue
for msg in mailbox.fetch(mark_seen=False):
# print(f"found message {msg.uid!r} with text {msg.text!r} in folder {imap_dir!r}")
msg_str = msg.obj.as_string()
print(f"{msg_str}")
if msg_magic == msg.text.strip():
matching_messages.append(msg)
in_folder = MessageInFolder(message = msg, folder = imap_dir)
matching_messages.append(in_folder)
return matching_messages
if args.imap_move_to is not None:
with connection() as mailbox:
print("prefind")
prefind = find_messages(mailbox)
assert len(prefind) > 0, "Could not find message to move anywhere"
assert len(prefind) == 1, "Found duplicate messages"
msg = prefind[0].message
time.sleep(2)
print(f"about to move {msg.uid} to {args.imap_move_to}")
mailbox.move(msg.uid, args.imap_move_to)
print("done moving")
time.sleep(2)
print("hopefully the other side is done moving by now")
with connection() as mailbox:
matching_messages = find_messages(mailbox)
if args.expect == 'received':
# print(f"{matching_messages!r}")
assert len(matching_messages) > 0, "Could not find the message in the mailbox"
assert len(matching_messages) == 1, f"Multiple messages matching message magic {msg_magic}"
matching_message = matching_messages[0]
matching_mif = matching_messages[0]
if args.imap_dir is not None:
expected_dir = args.imap_dir
actual_dir = matching_mif.folder
assert expected_dir == actual_dir, f"Expected to find message in {expected_dir}, found it in {actual_dir} instead"
matching_message = matching_mif.message
for expected_flag in args.expect_flag:
assert expected_flag in matching_message.flags, f"Flag {expected_flag} not found, message flags: {matching_message.flags!r}"