sendreportmail 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #!/usr/bin/env python3
  2. import os
  3. import sys
  4. import smtplib
  5. import ssl
  6. from email.message import EmailMessage
  7. from configparser import ConfigParser
  8. PACKAGE_TYPES = "arch"
  9. def get_xdg_dir(env_var: str, fallback_dir: str) -> str:
  10. xdg_dir = os.getenv(env_var)
  11. if xdg_dir is None or xdg_dir == "":
  12. xdg_dir = "{}/{}".format(get_home(), fallback_dir)
  13. return xdg_dir
  14. def get_home() -> str:
  15. home = os.getenv("HOME")
  16. if home is None or home == "":
  17. print("Error: $HOME not accessible")
  18. sys.exit(1)
  19. return home
  20. class ConfigFile:
  21. def __init__(self, path: str):
  22. config_parser = self.get_config_parser(path)
  23. try:
  24. self.smtp_server = config_parser["dummy_section"]["smtp_server"]
  25. self.smtp_port = int(config_parser["dummy_section"]["smtp_port"])
  26. self.smtp_connection = config_parser["dummy_section"][
  27. "smtp_connection"
  28. ]
  29. if self.smtp_connection not in ("ssl", "starttls"):
  30. print(
  31. "Error: 'smtp_connection' must be either 'ssl' or 'starttls'"
  32. )
  33. sys.exit(1)
  34. self.from_address = config_parser["dummy_section"]["from_address"]
  35. self.password = config_parser["dummy_section"]["password"]
  36. self.to_address = config_parser["dummy_section"]["to_address"]
  37. self.log_file = config_parser["dummy_section"]["log_file"]
  38. self.tail_value = int(config_parser["dummy_section"]["tail_value"])
  39. self.package_type = config_parser["dummy_section"]["package_type"]
  40. if self.package_type not in [PACKAGE_TYPES]:
  41. print(
  42. "Error: use one of the supported packges types: {}".format(
  43. PACKAGE_TYPES
  44. )
  45. )
  46. sys.exit(1)
  47. except KeyError as missing_entry:
  48. print("Error: needed config entry missing {}".format(missing_entry))
  49. sys.exit(1)
  50. except ValueError as wrong_value:
  51. print("Error: {}".format(wrong_value))
  52. sys.exit(1)
  53. def get_config_parser(self, config_path) -> ConfigParser:
  54. try:
  55. with open(config_path, "r", encoding="utf-8") as config_reader:
  56. config_string = "[dummy_section]\n" + config_reader.read()
  57. except (FileNotFoundError, PermissionError, IOError):
  58. print("Error: could not access config at '{}'".format(config_path))
  59. sys.exit(1)
  60. config_parser = ConfigParser()
  61. config_parser.read_string(config_string)
  62. return config_parser
  63. def set_subject(
  64. message: EmailMessage, package: str, body: str, config_file: ConfigFile
  65. ) -> None:
  66. if config_file.package_type == "arch":
  67. if "Finished making: " in body:
  68. message["Subject"] = "BUILD SUCCESS: '{}'".format(package)
  69. print("BUILD SUCCESS")
  70. else:
  71. message["Subject"] = "BUILD FAILURE: '{}'".format(package)
  72. def set_addresses(conf: ConfigFile, message: EmailMessage) -> None:
  73. message["From"] = conf.from_address
  74. message["To"] = conf.to_address
  75. def get_pkgname() -> str:
  76. cwd = os.getcwd()
  77. return cwd[cwd.rfind("/") + 1 :]
  78. def get_log_from_file(conf: ConfigFile) -> str:
  79. if conf.tail_value < 1:
  80. print("Error: tailvalue cannot be smaller than 1")
  81. sys.exit(1)
  82. try:
  83. with open(conf.log_file, "r", encoding="utf-8") as log_file_reader:
  84. log = log_file_reader.readlines()
  85. except (FileNotFoundError, PermissionError, IOError):
  86. print("Error: could not access log at '{}'".format(conf.log_file))
  87. sys.exit(1)
  88. log.reverse()
  89. tail_lines = []
  90. tail_index = 1
  91. for line in log:
  92. if tail_index == conf.tail_value:
  93. break
  94. tail_lines.append(line)
  95. tail_index += 1
  96. tail_lines.reverse()
  97. tail_lines[-1] = tail_lines[-1][:-1]
  98. mail_text = "".join(tail_lines)
  99. return mail_text
  100. def send_email_via_smtp(conf: ConfigFile, message: EmailMessage) -> None:
  101. context = ssl.create_default_context()
  102. if conf.smtp_connection == "starttls":
  103. with smtplib.SMTP_SSL(conf.smtp_server, conf.smtp_port) as server:
  104. server.starttls(context=context)
  105. server.login(conf.from_address, conf.password)
  106. server.send_message(message)
  107. else:
  108. with smtplib.SMTP_SSL(
  109. conf.smtp_server, conf.smtp_port, context=context
  110. ) as server:
  111. server.login(conf.from_address, conf.password)
  112. server.send_message(message)
  113. def main() -> None:
  114. config_file_path = os.path.join(
  115. get_xdg_dir("XDG_CONFIG_HOME", ".config"), "sendreportmail", "config"
  116. )
  117. config = ConfigFile(config_file_path)
  118. msg = EmailMessage()
  119. email_body = get_log_from_file(config)
  120. msg.set_content(email_body)
  121. pkgname = get_pkgname()
  122. set_subject(msg, pkgname, email_body, config)
  123. set_addresses(config, msg)
  124. send_email_via_smtp(config, msg)
  125. if __name__ == "__main__":
  126. main()