You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

198 lines
6.2 KiB

  1. #!/usr/bin/env sh
  2. # support smtp
  3. # This implementation uses Python (2 or 3), which is available in many environments.
  4. # If you don't have Python, try "mail" notification instead of "smtp".
  5. # SMTP_FROM="from@example.com" # required
  6. # SMTP_TO="to@example.com" # required
  7. # SMTP_HOST="smtp.example.com" # required
  8. # SMTP_PORT="25" # defaults to 25, 465 or 587 depending on SMTP_SECURE
  9. # SMTP_SECURE="none" # one of "none", "ssl" (implicit TLS, TLS Wrapper), "tls" (explicit TLS, STARTTLS)
  10. # SMTP_USERNAME="" # set if SMTP server requires login
  11. # SMTP_PASSWORD="" # set if SMTP server requires login
  12. # SMTP_TIMEOUT="15" # seconds for SMTP operations to timeout
  13. # SMTP_PYTHON="/path/to/python" # defaults to system python3 or python
  14. smtp_send() {
  15. # Find a Python interpreter:
  16. SMTP_PYTHON="${SMTP_PYTHON:-$(_readaccountconf_mutable SMTP_PYTHON)}"
  17. if [ "$SMTP_PYTHON" ]; then
  18. if _exists "$SMTP_PYTHON"; then
  19. _saveaccountconf_mutable SMTP_PYTHON "$SMTP_PYTHON"
  20. else
  21. _err "SMTP_PYTHON '$SMTP_PYTHON' does not exist."
  22. return 1
  23. fi
  24. else
  25. # No SMTP_PYTHON setting; try to run default Python.
  26. # (This is not saved with the conf.)
  27. if _exists python3; then
  28. SMTP_PYTHON="python3"
  29. elif _exists python; then
  30. SMTP_PYTHON="python"
  31. else
  32. _err "Can't locate Python interpreter; please define SMTP_PYTHON."
  33. return 1
  34. fi
  35. fi
  36. _debug "SMTP_PYTHON" "$SMTP_PYTHON"
  37. _debug "Python version" "$($SMTP_PYTHON --version 2>&1)"
  38. # Validate other settings:
  39. SMTP_FROM="${SMTP_FROM:-$(_readaccountconf_mutable SMTP_FROM)}"
  40. if [ -z "$SMTP_FROM" ]; then
  41. _err "You must define SMTP_FROM as the sender email address."
  42. return 1
  43. fi
  44. SMTP_TO="${SMTP_TO:-$(_readaccountconf_mutable SMTP_TO)}"
  45. if [ -z "$SMTP_TO" ]; then
  46. _err "You must define SMTP_TO as the recipient email address."
  47. return 1
  48. fi
  49. SMTP_HOST="${SMTP_HOST:-$(_readaccountconf_mutable SMTP_HOST)}"
  50. if [ -z "$SMTP_HOST" ]; then
  51. _err "You must define SMTP_HOST as the SMTP server hostname."
  52. return 1
  53. fi
  54. SMTP_PORT="${SMTP_PORT:-$(_readaccountconf_mutable SMTP_PORT)}"
  55. SMTP_SECURE="${SMTP_SECURE:-$(_readaccountconf_mutable SMTP_SECURE)}"
  56. SMTP_SECURE="${SMTP_SECURE:-none}"
  57. case "$SMTP_SECURE" in
  58. "none") SMTP_DEFAULT_PORT="25" ;;
  59. "ssl") SMTP_DEFAULT_PORT="465" ;;
  60. "tls") SMTP_DEFAULT_PORT="587" ;;
  61. *)
  62. _err "Invalid SMTP_SECURE='$SMTP_SECURE'. It must be 'ssl', 'tls' or 'none'."
  63. return 1
  64. ;;
  65. esac
  66. SMTP_USERNAME="${SMTP_USERNAME:-$(_readaccountconf_mutable SMTP_USERNAME)}"
  67. SMTP_PASSWORD="${SMTP_PASSWORD:-$(_readaccountconf_mutable SMTP_PASSWORD)}"
  68. SMTP_TIMEOUT="${SMTP_TIMEOUT:-$(_readaccountconf_mutable SMTP_TIMEOUT)}"
  69. SMTP_DEFAULT_TIMEOUT="15"
  70. # Send the message:
  71. if ! _smtp_send "$@"; then
  72. _err "$smtp_send_output"
  73. return 1
  74. fi
  75. # Save remaining config if successful. (SMTP_PYTHON is saved earlier.)
  76. _saveaccountconf_mutable SMTP_FROM "$SMTP_FROM"
  77. _saveaccountconf_mutable SMTP_TO "$SMTP_TO"
  78. _saveaccountconf_mutable SMTP_HOST "$SMTP_HOST"
  79. _saveaccountconf_mutable SMTP_PORT "$SMTP_PORT"
  80. _saveaccountconf_mutable SMTP_SECURE "$SMTP_SECURE"
  81. _saveaccountconf_mutable SMTP_USERNAME "$SMTP_USERNAME"
  82. _saveaccountconf_mutable SMTP_PASSWORD "$SMTP_PASSWORD"
  83. _saveaccountconf_mutable SMTP_TIMEOUT "$SMTP_TIMEOUT"
  84. return 0
  85. }
  86. # _send subject content statuscode
  87. # Send the message via Python using SMTP_* settings
  88. _smtp_send() {
  89. _subject="$1"
  90. _content="$2"
  91. _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
  92. _debug "_subject" "$_subject"
  93. _debug "_content" "$_content"
  94. _debug "_statusCode" "$_statusCode"
  95. _debug "SMTP_FROM" "$SMTP_FROM"
  96. _debug "SMTP_TO" "$SMTP_TO"
  97. _debug "SMTP_HOST" "$SMTP_HOST"
  98. _debug "SMTP_PORT" "$SMTP_PORT"
  99. _debug "SMTP_DEFAULT_PORT" "$SMTP_DEFAULT_PORT"
  100. _debug "SMTP_SECURE" "$SMTP_SECURE"
  101. _debug "SMTP_USERNAME" "$SMTP_USERNAME"
  102. _secure_debug "SMTP_PASSWORD" "$SMTP_PASSWORD"
  103. _debug "SMTP_TIMEOUT" "$SMTP_TIMEOUT"
  104. _debug "SMTP_DEFAULT_TIMEOUT" "$SMTP_DEFAULT_TIMEOUT"
  105. if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then
  106. # Output the SMTP server dialogue. (Note this will include SMTP_PASSWORD!)
  107. smtp_debug="True"
  108. else
  109. smtp_debug=""
  110. fi
  111. # language=Python
  112. smtp_send_output="$(
  113. $SMTP_PYTHON <<EOF
  114. # This code is meant to work with either Python 2.7.x or Python 3.4+.
  115. try:
  116. try:
  117. from email.message import EmailMessage
  118. except ImportError:
  119. from email.mime.text import MIMEText as EmailMessage # Python 2
  120. from smtplib import SMTP, SMTP_SSL, SMTPException
  121. from socket import error as SocketError
  122. except ImportError as err:
  123. print("A required Python standard package is missing. This system may have"
  124. " a reduced version of Python unsuitable for sending mail: %s" % err)
  125. exit(1)
  126. smtp_debug = """$smtp_debug""" == "True"
  127. smtp_host = """$SMTP_HOST"""
  128. smtp_port = int("""${SMTP_PORT:-$SMTP_DEFAULT_PORT}""")
  129. smtp_secure = """$SMTP_SECURE"""
  130. username = """$SMTP_USERNAME"""
  131. password = """$SMTP_PASSWORD"""
  132. timeout=int("""${SMTP_TIMEOUT:-$SMTP_DEFAULT_TIMEOUT}""") # seconds
  133. from_email="""$SMTP_FROM"""
  134. to_emails="""$SMTP_TO""" # can be comma-separated
  135. subject="""$_subject"""
  136. content="""$_content"""
  137. try:
  138. msg = EmailMessage()
  139. msg.set_content(content)
  140. except (AttributeError, TypeError):
  141. # Python 2 MIMEText
  142. msg = EmailMessage(content)
  143. msg["Subject"] = subject
  144. msg["From"] = from_email
  145. msg["To"] = to_emails
  146. smtp = None
  147. try:
  148. if smtp_secure == "ssl":
  149. smtp = SMTP_SSL(smtp_host, smtp_port, timeout=timeout)
  150. else:
  151. smtp = SMTP(smtp_host, smtp_port, timeout=timeout)
  152. smtp.set_debuglevel(smtp_debug)
  153. if smtp_secure == "tls":
  154. smtp.starttls()
  155. if username or password:
  156. smtp.login(username, password)
  157. smtp.sendmail(msg["From"], msg["To"].split(","), msg.as_string())
  158. except SMTPException as err:
  159. # Output just the error (skip the Python stack trace) for SMTP errors
  160. print("Error sending: %r" % err)
  161. exit(1)
  162. except SocketError as err:
  163. print("Error connecting to %s:%d: %r" % (smtp_host, smtp_port, err))
  164. exit(1)
  165. finally:
  166. if smtp is not None:
  167. smtp.quit()
  168. EOF
  169. )"
  170. _ret=$?
  171. _debug "smtp_send_output" "$smtp_send_output"
  172. return "$_ret"
  173. }