123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- import json
- import imaplib
- from cmd import Cmd
- from typing import Optional
- import os
- from time import strftime, localtime, strptime
- from mailbox.email import Mail
- from mailbox.imap import Imap
- class CLManager(Cmd):
- intro = 'Welcome to the HuanMail (IMAP).'
- prompt = 'HuanMail>'
- file = None
- def __init__(self):
- super(CLManager, self).__init__()
- self.imap: Optional[Imap] = None
- def do_load(self, path):
- """Load setting from file."""
- try:
- with open(path, "r", encoding="utf-8") as f:
- try:
- conf = json.load(f)
- imap = conf.get("imap")
- if imap:
- self.imap = Imap(
- user=imap["user"],
- passwd=imap["passwd"],
- host=imap.get("host", "localhost"),
- port=imap.get("port", 465),
- ssl=imap.get("ssl", True),
- start_ssl=imap.get("start_ssl", False)
- )
- self.imap.connect()
- self.imap.disconnect()
- self.imap.inbox = imap.get("inbox", "INBOX")
- mailbox = imap.get("mailbox", {})
- for num in imap.get("mailbox", {}):
- byte: str = mailbox[num]
- self.imap.add_mail(num, byte.encode("utf-8"))
- except KeyError:
- print("Key error.")
- except imaplib.IMAP4.error:
- print("Sorry, IMAP Authentication error. Please check your user and password.")
- except Exception:
- print("Sorry, Unknown error.")
- else:
- print("Okay.")
- except FileNotFoundError:
- print("File not fount.")
- except IOError:
- print("IO error.")
- def do_save(self, path):
- """Save setting to file."""
- conf = {}
- if self.imap:
- conf["imap"] = {}
- conf["imap"]["user"] = self.imap.user
- conf["imap"]["passwd"] = self.imap.passwd
- conf["imap"]["host"] = self.imap.host
- conf["imap"]["port"] = self.imap.port
- conf["imap"]["ssl"] = self.imap.ssl
- conf["imap"]["start_ssl"] = self.imap.start_ssl
- conf["imap"]["inbox"] = self.imap.inbox
-
- mailbox = {}
- for i in self.imap.mailbox:
- byte: bytes = i.byte
- mailbox[i.num] = byte.decode("utf-8")
- conf["imap"]["mailbox"] = mailbox
- try:
- with open(path, "w", encoding="utf-8") as f:
- f.write(json.dumps(conf))
- except FileNotFoundError:
- print("File not found.")
- except IOError:
- print("IO error.")
- else:
- print("Okay.")
- def do_login(self, arg):
- """Login imap server."""
- if len(arg) != 0:
- print("Bad syntax.")
- return
- user = input("User:")
- passwd = input("Passwd:")
- host = input("Host[localhost]:")
- port = input("Port[993]:")
- ssl = input("SSL[y]:")
- if len(host) == 0:
- host = "localhost"
- if len(port) == 0:
- port = 993
- else:
- try:
- port = int(port)
- except (ValueError, TypeError):
- print("Port must be number")
- return
- if len(ssl) == 0 or ssl == "y":
- ssl = True
- else:
- ssl = False
- print(f"""Login imap
- Host: {host}:{port}
- User: {user}
- Passwd: {passwd}
- SSL: {ssl}
- Sure? [Yes/No]""")
- if input() == "No":
- print("Stop.")
- return
- try:
- self.imap = Imap(user, passwd, host=host, port=port, ssl=ssl)
- self.imap.connect()
- self.imap.disconnect()
- except imaplib.IMAP4.error:
- print("Sorry, IMAP Authentication error. Please check your user and password.")
- except Exception:
- print("Sorry, Unknown error.")
- else:
- print("Okay.")
- def do_logout(self, arg):
- """Logout imap server."""
- if len(arg) != 0:
- print("Bad syntax.")
- return
- if input("Sure?[Yes/No]") == "No":
- print("Stop.")
- return
- self.imap = None
- print("Okay.")
- def do_info(self, arg):
- """Show imap info."""
- if len(arg) != 0:
- print("Bad syntax.")
- return
- if self.imap:
- print(f"""Host: {self.imap.host}:{self.imap.port}
- User: {self.imap.user}
- Passwd: {self.imap.passwd}
- SSL: {self.imap.ssl}
- MailBox: {self.imap.inbox}""")
- else:
- print("Not login.")
- def do_get(self, arg):
- """Get mail from mailbox."""
- if not self.imap:
- print("Please login first.")
- return
- if arg == "ALL":
- pass
- elif arg == "TODAY":
- arg = "ON " + strftime('%d-%b-%Y', localtime())
- else:
- try:
- arg = "ON " + strftime('%d-%b-%Y', strptime(arg, "%Y-%m-%d"))
- except ValueError:
- print("Bad syntax.")
- return
- print("Please wait...")
- try:
- self.imap.fetch_all(arg)
- except imaplib.IMAP4.error:
- print("IMAP4 error, please check setting.")
- else:
- print("Okay.")
- def do_show(self, arg):
- """Show Mail List"""
- try:
- start, step = arg.split()
- start = int(start)
- step = int(step)
- except (TypeError, ValueError):
- print("Bad syntax.")
- return
- if not self.imap:
- print("Please login first.")
- return
- try:
- mailbox = self.imap.mailbox[start:]
- count = 0
- for i in mailbox:
- print(f"* {i}")
- count += 1
- if count == step:
- break
- except IndexError:
- print("Bad index.")
- else:
- print("Okay.")
- def do_check(self, arg):
- """check --- check mail text.
- check save --- check mail text and save.
- check source --- check mail source and save.
- check file --- check mail file and save."""
- if not self.imap:
- print("Please login first.")
- return
- num = input("Mail number:")
- mail = self.imap.fetch(num)
- if len(arg) == 0:
- self.check(mail)
- elif arg == "save":
- self.check_save(mail)
- elif arg == "source":
- self.check_source(mail)
- elif arg == "file":
- self.check_file(mail)
- else:
- print(f"Bad syntax.")
- @staticmethod
- def __print_check(mail: Mail):
- print(f"Title: {mail.title}")
- print(f"From: {mail.from_addr}")
- print(f"Date: {mail.date}")
- @staticmethod
- def check(mail: Mail):
- CLManager.__print_check(mail)
- print(f"\n{mail.body}\n")
- @staticmethod
- def check_save(mail: Mail):
- CLManager.__print_check(mail)
- path = input("Path:")
- try:
- with open(path, "w", encoding="utf-8") as f:
- f.write(mail.body)
- except IOError:
- print("IO error.")
- else:
- print("Okay.")
- @staticmethod
- def check_source(mail: Mail):
- CLManager.__print_check(mail)
- path = input("Path:")
- try:
- with open(path, "wb") as f:
- f.write(mail.byte)
- except IOError:
- print("IO error.")
- else:
- print("Okay.")
- def check_file(self, mail: Mail):
- path = input("Path:")
- os.makedirs(path, exist_ok=True)
- try:
- mail.save_file(path)
- except IOError:
- print("IO error.")
- else:
- print("Okay.")
- def do_mailbox(self, arg):
- """mail show --- show all mailbox.
- mail setting --- select a mailbox."""
- if not self.imap:
- print("Please login first.")
- return
- if arg == "show":
- for i in self.imap.list():
- print(f"* {i}")
- print("Okay")
- elif arg == "setting":
- mailbox = input("Mailbox:")
- try:
- self.imap.inbox = mailbox
- except imaplib.IMAP4.error:
- print("Bad mailbox.")
- else:
- print("Okay")
- else:
- print("Bad syntax.")
- def do_quit(self, _):
- """Exit HuanMail."""
- print("Bye~")
- if self.file:
- self.file.close()
- self.file = None
- return True
- if __name__ == '__main__':
- manager = CLManager()
- try:
- manager.cmdloop()
- except KeyboardInterrupt:
- print("\nBye~")
- quit(0)
|