diff options
author | Antoine Eiche <lewo@abesis.fr> | 2020-09-28 20:51:32 +0200 |
---|---|---|
committer | Antoine Eiche <lewo@abesis.fr> | 2020-09-28 20:51:32 +0200 |
commit | c813f1205f0da413ec532cca868f57a57b7f8448 (patch) | |
tree | 0fccb230aeb3ce5b227740d037a2bac7caec0c60 /scripts | |
parent | 24600377afa853cb31654b1987530bbf2f0add79 (diff) |
Add multiple.nix test
This test is used to test feature requiring several mail domains, such
as the `forwards` option.
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/mail-check.py | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/scripts/mail-check.py b/scripts/mail-check.py new file mode 100644 index 0000000..47629fb --- /dev/null +++ b/scripts/mail-check.py @@ -0,0 +1,187 @@ +import smtplib, sys +import argparse +import os +import uuid +import imaplib +from datetime import datetime, timedelta +import email +import time + +RETRY = 100 + +def _send_mail(smtp_host, smtp_port, from_addr, from_pwd, to_addr, subject, starttls): + print("Sending mail with subject '{}'".format(subject)) + message = "\n".join([ + "From: {from_addr}", + "To: {to_addr}", + "Subject: {subject}", + "", + "This validates our mail server can send to Gmail :/"]).format( + from_addr=from_addr, + to_addr=to_addr, + subject=subject) + + + retry = RETRY + while True: + with smtplib.SMTP(smtp_host, port=smtp_port) as smtp: + if starttls: + smtp.starttls() + if from_pwd is not None: + smtp.login(from_addr, from_pwd) + try: + smtp.sendmail(from_addr, [to_addr], message) + return + except smtplib.SMTPResponseException as e: + # This is a service unavailable error + # In this situation, we want to retry. + if e.smtp_code == 451: + if retry > 0: + retry = retry - 1 + time.sleep(1) + continue + else: + print("Error while sending mail: %s" % e) + exit(5) + except Exception as e: + print("Error while sending mail: %s" % e) + exit(4) + +def _read_mail( + imap_host, + imap_port, + imap_username, + to_pwd, + subject, + ignore_dkim_spf, + show_body=False, + delete=True): + print("Reading mail from %s" % imap_username) + + message = None + + obj = imaplib.IMAP4_SSL(imap_host, imap_port) + obj.login(imap_username, to_pwd) + obj.select() + + today = datetime.today() + cutoff = today - timedelta(days=1) + dt = cutoff.strftime('%d-%b-%Y') + for _ in range(0, RETRY): + print("Retrying") + obj.select() + typ, data = obj.search(None, '(SINCE %s) (SUBJECT "%s")'%(dt, subject)) + if data == [b'']: + time.sleep(1) + continue + + uids = data[0].decode("utf-8").split(" ") + if len(uids) != 1: + print("Warning: %d messages have been found with subject containing %s " % (len(uids), subject)) + + # FIXME: we only consider the first matching message... + uid = uids[0] + _, raw = obj.fetch(uid, '(RFC822)') + if delete: + obj.store(uid, '+FLAGS', '\\Deleted') + obj.expunge() + message = email.message_from_bytes(raw[0][1]) + print("Message with subject '%s' has been found" % message['subject']) + if show_body: + for m in message.get_payload(): + if m.get_content_type() == 'text/plain': + print("Body:\n%s" % m.get_payload(decode=True).decode('utf-8')) + break + + if message is None: + print("Error: no message with subject '%s' has been found in INBOX of %s" % (subject, imap_username)) + exit(1) + + if ignore_dkim_spf: + return + + # gmail set this standardized header + if 'ARC-Authentication-Results' in message: + if "dkim=pass" in message['ARC-Authentication-Results']: + print("DKIM ok") + else: + print("Error: no DKIM validation found in message:") + print(message.as_string()) + exit(2) + if "spf=pass" in message['ARC-Authentication-Results']: + print("SPF ok") + else: + print("Error: no SPF validation found in message:") + print(message.as_string()) + exit(3) + else: + print("DKIM and SPF verification failed") + exit(4) + +def send_and_read(args): + src_pwd = None + if args.src_password_file is not None: + src_pwd = args.src_password_file.readline().rstrip() + dst_pwd = args.dst_password_file.readline().rstrip() + + if args.imap_username != '': + imap_username = args.imap_username + else: + imap_username = args.to_addr + + subject = "{}".format(uuid.uuid4()) + + _send_mail(smtp_host=args.smtp_host, + smtp_port=args.smtp_port, + from_addr=args.from_addr, + from_pwd=src_pwd, + to_addr=args.to_addr, + subject=subject, + starttls=args.smtp_starttls) + + _read_mail(imap_host=args.imap_host, + imap_port=args.imap_port, + imap_username=imap_username, + to_pwd=dst_pwd, + subject=subject, + ignore_dkim_spf=args.ignore_dkim_spf) + +def read(args): + _read_mail(imap_host=args.imap_host, + imap_port=args.imap_port, + to_addr=args.imap_username, + to_pwd=args.imap_password, + subject=args.subject, + ignore_dkim_spf=args.ignore_dkim_spf, + show_body=args.show_body, + delete=False) + +parser = argparse.ArgumentParser() +subparsers = parser.add_subparsers() + +parser_send_and_read = subparsers.add_parser('send-and-read', description="Send a email with a subject containing a random UUID and then try to read this email from the recipient INBOX.") +parser_send_and_read.add_argument('--smtp-host', type=str) +parser_send_and_read.add_argument('--smtp-port', type=str, default=25) +parser_send_and_read.add_argument('--smtp-starttls', action='store_true') +parser_send_and_read.add_argument('--from-addr', type=str) +parser_send_and_read.add_argument('--imap-host', required=True, type=str) +parser_send_and_read.add_argument('--imap-port', type=str, default=993) +parser_send_and_read.add_argument('--to-addr', type=str, required=True) +parser_send_and_read.add_argument('--imap-username', type=str, default='', help="username used for imap login. If not specified, the to-addr value is used") +parser_send_and_read.add_argument('--src-password-file', type=argparse.FileType('r')) +parser_send_and_read.add_argument('--dst-password-file', required=True, type=argparse.FileType('r')) +parser_send_and_read.add_argument('--ignore-dkim-spf', action='store_true', help="to ignore the dkim and spf verification on the read mail") +parser_send_and_read.set_defaults(func=send_and_read) + +parser_read = subparsers.add_parser('read', description="Search for an email with a subject containing 'subject' in the INBOX.") +parser_read.add_argument('--imap-host', type=str, default="localhost") +parser_read.add_argument('--imap-port', type=str, default=993) +parser_read.add_argument('--imap-username', required=True, type=str) +parser_read.add_argument('--imap-password', required=True, type=str) +parser_read.add_argument('--ignore-dkim-spf', action='store_true', help="to ignore the dkim and spf verification on the read mail") +parser_read.add_argument('--show-body', action='store_true', help="print mail text/plain payload") +parser_read.add_argument('subject', type=str) +parser_read.set_defaults(func=read) + +args = parser.parse_args() +args.func(args) |