sender-cli.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. import smtplib
  2. import json
  3. from cmd import Cmd
  4. from typing import Optional
  5. from sender.email import Email
  6. from sender.smtp import Sender
  7. class CLManager(Cmd):
  8. intro = 'Welcome to the HuanMail (SMTP).'
  9. prompt = 'HuanMail>'
  10. file = None
  11. def __init__(self):
  12. super(CLManager, self).__init__()
  13. self.sender: Optional[Sender] = None
  14. self.email: Optional[Email] = None
  15. def do_load(self, path):
  16. """Load setting from file."""
  17. try:
  18. with open(path, "r", encoding="utf-8") as f:
  19. try:
  20. conf = json.load(f)
  21. sender = conf.get("sender")
  22. if sender:
  23. self.sender = Sender(
  24. user=sender["user"],
  25. passwd=sender["passwd"],
  26. host=sender.get("host", "localhost"),
  27. port=sender.get("port", 465),
  28. debug=sender.get("debug", False),
  29. ssl=sender.get("ssl", True),
  30. start_ssl=sender.get("start_ssl", False)
  31. )
  32. email = conf.get("email", {})
  33. if input("Load email?[Yes/No]") == "Yes" and email:
  34. self.email = Email(
  35. from_addr=(email["from_name"], email["from_addr"]),
  36. subject=input("Title:")
  37. )
  38. except smtplib.SMTPAuthenticationError:
  39. print("Sorry, SMTP Authentication error. Please check your user and password.")
  40. except smtplib.SMTPException:
  41. print("Sorry, SMTP error.")
  42. except KeyError:
  43. print("Key error.")
  44. except Exception:
  45. print("Sorry, Unknown error.")
  46. else:
  47. print("Okay.")
  48. except FileNotFoundError:
  49. print("File not fount.")
  50. except IOError:
  51. print("IO error.")
  52. def do_save(self, arg):
  53. """Save setting to file."""
  54. conf = {}
  55. if self.sender:
  56. conf["sender"] = {}
  57. conf["sender"]["user"] = self.sender.user
  58. conf["sender"]["passwd"] = self.sender.passwd
  59. conf["sender"]["host"] = self.sender.host
  60. conf["sender"]["port"] = self.sender.port
  61. conf["sender"]["debug"] = self.sender.debug
  62. conf["sender"]["ssl"] = self.sender.ssl
  63. conf["sender"]["start_ssl"] = self.sender.start_ssl
  64. if input("Save email?[Yes/No]") == "Yes" and self.email:
  65. conf["email"] = {}
  66. conf["email"]["from_name"], conf["email"]["from_addr"] = self.email.from_addr
  67. try:
  68. with open(arg, "w", encoding="utf-8") as f:
  69. f.write(json.dumps(conf))
  70. except FileNotFoundError:
  71. print("File not found.")
  72. except IOError:
  73. print("IO error.")
  74. else:
  75. print("Okay.")
  76. def do_sender(self, arg):
  77. """sender setting -- setting the sender.
  78. sender show -- show sender info.
  79. sender delete -- delete the sender."""
  80. if arg == "setting":
  81. self.sender_setting()
  82. elif arg == "show":
  83. self.sender_show()
  84. elif arg == "delete":
  85. self.sender_delete()
  86. else:
  87. print(f"Bad syntax.")
  88. return
  89. def sender_show(self):
  90. print(f"""Host: {self.sender.host}:{self.sender.port}
  91. User: {self.sender.user}
  92. Passwd: {self.sender.passwd}""")
  93. def sender_setting(self):
  94. user = input("User:")
  95. passwd = input("Passwd:")
  96. host = input("Host[localhost]:")
  97. port = input("Port[465]:")
  98. debug = input("Debug[n]:")
  99. ssl = input("SSL[y]:")
  100. if len(host) == 0:
  101. host = "localhost"
  102. if len(port) == 0:
  103. port = 465
  104. else:
  105. try:
  106. port = int(port)
  107. except (ValueError, TypeError):
  108. print("Port must be number")
  109. return
  110. if len(debug) == 0 or debug == "n":
  111. debug = False
  112. else:
  113. debug = True
  114. if len(ssl) == 0 or ssl == "y":
  115. ssl = True
  116. else:
  117. ssl = False
  118. print(f"""Setting sender
  119. Host: {host}:{port}
  120. User: {user}
  121. Passwd: {passwd}
  122. Debug: {debug}
  123. SSL: {ssl}
  124. Sure? [Yes/No]""")
  125. if input() == "No":
  126. print("Stop.")
  127. return
  128. try:
  129. self.sender = Sender(user, passwd, host=host, port=port, debug=debug, ssl=ssl)
  130. except smtplib.SMTPAuthenticationError:
  131. print("Sorry, SMTP Authentication error. Please check your user and password.")
  132. except smtplib.SMTPException:
  133. print("Sorry, SMTP error.")
  134. except Exception:
  135. print("Sorry, Unknown error.")
  136. else:
  137. print("Okay.")
  138. def sender_delete(self):
  139. if input("Sure?[Yes/No]") == "No":
  140. print("Stop.")
  141. return
  142. self.sender = None
  143. print("Sender has been delete.")
  144. def do_email(self, arg):
  145. """email new -- create a new email.
  146. email delete -- delete the email.
  147. email text -- add test to email.
  148. email text-file -- add text from file to email.
  149. email html -- add html to email.
  150. email html-file -- add html from file to email.
  151. email file -- add a file to email.
  152. email show -- show the email info."""
  153. if arg == "new":
  154. self.email_new()
  155. else:
  156. if not self.email:
  157. print("Please create email first.")
  158. return
  159. if arg == "delete":
  160. self.email_delete()
  161. elif arg == "text":
  162. self.email_text()
  163. elif arg == "text-file":
  164. self.email_text_file()
  165. elif arg == "html":
  166. self.email_html()
  167. elif arg == "html-file":
  168. self.email_html_file()
  169. elif arg == "file":
  170. self.email_file()
  171. elif arg == "show":
  172. self.email_show()
  173. else:
  174. print(f"Bad syntax.")
  175. def email_new(self):
  176. if self.email and input("Sure?[Yes/No]") == "No":
  177. print("Stop.")
  178. return
  179. from_addr = input("From email address:")
  180. from_name = input("From name:")
  181. subject = input("Title:")
  182. self.email = Email((from_name, from_addr), subject)
  183. print("Okay.")
  184. def email_delete(self):
  185. if input("Sure?[Yes/No]") == "No":
  186. print("Stop.")
  187. return
  188. self.email = None
  189. print("Okay.")
  190. def email_text(self):
  191. self.email.add_text(self.get_text())
  192. print("Okay.")
  193. def email_text_file(self):
  194. try:
  195. self.email.add_text_from_file(input("Path:"))
  196. except FileNotFoundError:
  197. print("File not fount.")
  198. except IOError:
  199. print("IO error.")
  200. else:
  201. print("Okay.")
  202. def email_html(self):
  203. self.email.add_html(self.get_text())
  204. print("Okay.")
  205. def email_html_file(self):
  206. try:
  207. self.email.add_html_from_file(input("Path:"))
  208. except FileNotFoundError:
  209. print("File not fount.")
  210. except IOError:
  211. print("IO error.")
  212. else:
  213. print("Okay.")
  214. def email_file(self):
  215. filename = input("Filename:")
  216. path = input("Path:")
  217. try:
  218. self.email.add_from_file(filename, path)
  219. except FileNotFoundError:
  220. print("File not fount.")
  221. except IOError:
  222. print("IO error.")
  223. else:
  224. print("Okay.")
  225. def email_show(self):
  226. print(f"From: {self.email.from_addr[0]} <{self.email.from_addr[1]}>")
  227. print(f"Title: {self.email.subject}")
  228. print("* Text: ")
  229. for i in self.email.text:
  230. print(i)
  231. print("-" * 5)
  232. print("* HTML: ")
  233. for i in self.email.html:
  234. print(i)
  235. print("-" * 5)
  236. print("* File: ")
  237. for i in self.email.file:
  238. print(i[0])
  239. @staticmethod
  240. def get_text():
  241. end = input("End:")
  242. text = ""
  243. while True:
  244. get = input(">>> ")
  245. if get == end:
  246. return text[:-1]
  247. text += get + "\n"
  248. def do_rc(self, arg):
  249. """rc add-to -- add recipient.
  250. rc add-cc -- add CC person.
  251. rc add-bcc -- add BCC person.
  252. rc show -- show recipient, CC person, BCC person."""
  253. if not self.email:
  254. print("Please create email first.")
  255. return
  256. if arg == "add-to":
  257. self.rc_add_to()
  258. elif arg == "add-cc":
  259. self.rc_add_cc()
  260. elif arg == "add-bcc":
  261. self.rc_add_bcc()
  262. elif arg == "show":
  263. self.rc_show()
  264. else:
  265. print(f"Bad syntax.")
  266. def rc_add_to(self):
  267. name = input("Name:")
  268. email = input("Email:")
  269. self.email.add_to_addr(name, email)
  270. print("Okay.")
  271. def rc_add_cc(self):
  272. name = input("Name:")
  273. email = input("Email:")
  274. self.email.add_cc_addr(name, email)
  275. print("Okay.")
  276. def rc_add_bcc(self):
  277. name = input("Name:")
  278. email = input("Email:")
  279. self.email.add_bcc_addr(name, email)
  280. print("Okay.")
  281. def rc_show(self):
  282. print("* Recipient:")
  283. for name, email in self.email.to_addr:
  284. print(f"{name} <{email}>")
  285. print("* CC Person:")
  286. for name, email in self.email.cc_addr:
  287. print(f"{name} <{email}>")
  288. print("* BCC Person:")
  289. for name, email in self.email.bcc_addr:
  290. print(f"{name} <{email}>")
  291. def do_send(self, arg):
  292. """Send email"""
  293. if len(arg) != 0:
  294. print(f"Bad syntax for '{arg}'.")
  295. return
  296. if not self.email:
  297. print("Please create email first.")
  298. return
  299. if not self.sender:
  300. print("Please create sender first.")
  301. return
  302. try:
  303. self.sender.send(self.email)
  304. except smtplib.SMTPException:
  305. print("SMTP error.")
  306. else:
  307. print("Okay.")
  308. def do_quit(self, _):
  309. """Exit HuanMail."""
  310. print("Bye~")
  311. if self.file:
  312. self.file.close()
  313. self.file = None
  314. return True
  315. if __name__ == '__main__':
  316. manager = CLManager()
  317. try:
  318. manager.cmdloop()
  319. except KeyboardInterrupt:
  320. print("\nBye~")
  321. quit(0)