wip
This commit is contained in:
@@ -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
|
||||
}
|
||||
'';
|
||||
};
|
||||
}
|
||||
|
@@ -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;
|
||||
};
|
||||
|
@@ -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
|
||||
|
@@ -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}"
|
||||
|
||||
|
Reference in New Issue
Block a user