import argparse import smtplib from imapclient import IMAPClient from email.message import EmailMessage from email import message_from_bytes from email.utils import localtime def send_mail(args): msg = EmailMessage() # Create email body msg.set_content(args.body) # Set email headers msg['Subject'] = args.subject msg['From'] = args.from_addr msg['To'] = args.to_addr msg['Date'] = localtime() smtpObj = smtplib.SMTP_SSL(host=args.smtp_host) smtpObj.set_debuglevel(args.debug_level) smtpObj.login(args.smtp_user, args.smtp_password) smtpObj.send_message(msg) def message_list(args): imap = IMAPClient(args.imap_host) imap.login(args.imap_user, args.imap_password) imap.select_folder(args.folder, readonly=True) messages = imap.search(['FROM', '']) for uid, message_data in imap.fetch(messages, "RFC822").items(): email_message = message_from_bytes(message_data[b"RFC822"]) print(uid, email_message) imap.logout() def message_search(args): imap = IMAPClient(args.imap_host) imap.login(args.imap_user, args.imap_password) imap.select_folder(args.folder, readonly=True) messages = imap.search(args.search_string) for uid, message_data in imap.fetch(messages, "RFC822").items(): email_message = message_from_bytes(message_data[b"RFC822"]) print(uid, email_message) imap.logout() def message_delete(args): imap = IMAPClient(args.imap_host) imap.login(args.imap_user, args.imap_password) if args.dry_run == 'true': print('--dry_run is true, opening IMAP folder as readonly. No actions will be persistent') imap.select_folder(args.folder, readonly=True) else: imap.select_folder(args.folder) messages = imap.search(args.search_string) for uid, message_data in imap.fetch(messages, "RFC822").items(): email_message = message_from_bytes(message_data[b"RFC822"]) date = email_message.get("Date") from_addr = email_message.get("From") to_addr = email_message.get("To") subject = email_message.get("Subject") imap.delete_messages(uid) imap.expunge(uid) print('\nMessage with uid %s deleted:\n%s\nFrom: %s\nTo: %s\nSubject: %s' % (uid, date, from_addr, to_addr, subject)) imap.logout() # Setup CLI options and help menu global_parser = argparse.ArgumentParser(prog="pymailer", description="Simple mail client for sending emails, and checking and manipulating an inbox") subparsers = global_parser.add_subparsers(title="subcommands", help="available subcommands", dest="subcommand", required=True) send_mail_parser = subparsers.add_parser("send", help="send an email") send_mail_parser.add_argument('--smtp_host', help="SMTP server hostname", required=True) send_mail_parser.add_argument('--smtp_user', help="SMTP server logon username", required=True) send_mail_parser.add_argument('--smtp_password', help="SMTP server logon password", required=True) send_mail_parser.add_argument('--from_addr', help="Address to send email from", required=True) send_mail_parser.add_argument('--to_addr', help="Address to send email to", required=True) send_mail_parser.add_argument('--subject', help="Email subject", required=True) send_mail_parser.add_argument('--body', help="Email body", required=True) send_mail_parser.add_argument('--debug_level', help="Debug level, higher number is more verbose", type=int, choices=range(0, 3), default=0) send_mail_parser.set_defaults(func=send_mail) message_list_parser = subparsers.add_parser("message_list", help="lists all messages in an inbox via IMAP") message_list_parser.add_argument('--imap_host', help="IMAP server hostname", required=True) message_list_parser.add_argument('--imap_user', help="IMAP server logon username", required=True) message_list_parser.add_argument('--imap_password', help="IMAP server logon password", required=True) message_list_parser.add_argument('--folder', help="Inbox folder", default='INBOX') message_list_parser.set_defaults(func=message_list) message_search_parser = subparsers.add_parser("message_search", help="search an inbox for messages via IMAP") message_search_parser.add_argument('--imap_host', help="IMAP server hostname", required=True) message_search_parser.add_argument('--imap_user', help="IMAP server logon username", required=True) message_search_parser.add_argument('--imap_password', help="IMAP server logon password", required=True) message_search_parser.add_argument('--folder', help="Inbox folder", default='INBOX') message_search_parser.add_argument('--search_string', help="Search string e.g 'FROM' 'user@example.com'. Space separated", nargs='*', required=True) message_search_parser.set_defaults(func=message_search) message_delete_parser = subparsers.add_parser("message_delete", help="deletes messages in an inbox via IMAP") message_delete_parser.add_argument('--imap_host', help="IMAP server hostname", required=True) message_delete_parser.add_argument('--imap_user', help="IMAP server logon username", required=True) message_delete_parser.add_argument('--imap_password', help="IMAP server logon password", required=True) message_delete_parser.add_argument('--folder', help="Inbox folder", default='INBOX') message_delete_parser.add_argument('--search_string', help="Search string for emails that will be deleted e.g 'FROM' 'user@example.com'. Space separated", nargs='*', required=True) message_delete_parser.add_argument('--dry_run', help="List emails that will be deleted, but don't delete them", choices=('true', 'false'), default='false') message_delete_parser.set_defaults(func=message_delete) args = global_parser.parse_args() args.func(args)