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.

197 lines
6.1 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. _saveaccountconf_mutable SMTP_FROM "$SMTP_FROM"
  71. _saveaccountconf_mutable SMTP_TO "$SMTP_TO"
  72. _saveaccountconf_mutable SMTP_HOST "$SMTP_HOST"
  73. _saveaccountconf_mutable SMTP_PORT "$SMTP_PORT"
  74. _saveaccountconf_mutable SMTP_SECURE "$SMTP_SECURE"
  75. _saveaccountconf_mutable SMTP_USERNAME "$SMTP_USERNAME"
  76. _saveaccountconf_mutable SMTP_PASSWORD "$SMTP_PASSWORD"
  77. _saveaccountconf_mutable SMTP_TIMEOUT "$SMTP_TIMEOUT"
  78. # Send the message:
  79. if ! _smtp_send "$@"; then
  80. _err "$smtp_send_output"
  81. return 1
  82. fi
  83. return 0
  84. }
  85. # _send subject content statuscode
  86. # Send the message via Python using SMTP_* settings
  87. _smtp_send() {
  88. _subject="$1"
  89. _content="$2"
  90. _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
  91. _debug "_subject" "$_subject"
  92. _debug "_content" "$_content"
  93. _debug "_statusCode" "$_statusCode"
  94. _debug "SMTP_FROM" "$SMTP_FROM"
  95. _debug "SMTP_TO" "$SMTP_TO"
  96. _debug "SMTP_HOST" "$SMTP_HOST"
  97. _debug "SMTP_PORT" "$SMTP_PORT"
  98. _debug "SMTP_DEFAULT_PORT" "$SMTP_DEFAULT_PORT"
  99. _debug "SMTP_SECURE" "$SMTP_SECURE"
  100. _debug "SMTP_USERNAME" "$SMTP_USERNAME"
  101. _secure_debug "SMTP_PASSWORD" "$SMTP_PASSWORD"
  102. _debug "SMTP_TIMEOUT" "$SMTP_TIMEOUT"
  103. _debug "SMTP_DEFAULT_TIMEOUT" "$SMTP_DEFAULT_TIMEOUT"
  104. if [ "${DEBUG:-$DEBUG_LEVEL_NONE}" -ge "$DEBUG_LEVEL_2" ]; then
  105. # Output the SMTP server dialogue. (Note this will include SMTP_PASSWORD!)
  106. smtp_debug="True"
  107. else
  108. smtp_debug=""
  109. fi
  110. # language=Python
  111. smtp_send_output="$(
  112. $SMTP_PYTHON <<EOF
  113. # This code is meant to work with either Python 2.7.x or Python 3.4+.
  114. try:
  115. try:
  116. from email.message import EmailMessage
  117. except ImportError:
  118. from email.mime.text import MIMEText as EmailMessage # Python 2
  119. from smtplib import SMTP, SMTP_SSL, SMTPException
  120. from socket import error as SocketError
  121. except ImportError as err:
  122. print("A required Python standard package is missing. This system may have"
  123. " a reduced version of Python unsuitable for sending mail: %s" % err)
  124. exit(1)
  125. smtp_debug = """$smtp_debug""" == "True"
  126. smtp_host = """$SMTP_HOST"""
  127. smtp_port = int("""${SMTP_PORT:-$SMTP_DEFAULT_PORT}""")
  128. smtp_secure = """$SMTP_SECURE"""
  129. username = """$SMTP_USERNAME"""
  130. password = """$SMTP_PASSWORD"""
  131. timeout=int("""${SMTP_TIMEOUT:-$SMTP_DEFAULT_TIMEOUT}""") # seconds
  132. from_email="""$SMTP_FROM"""
  133. to_emails="""$SMTP_TO""" # can be comma-separated
  134. subject="""$_subject"""
  135. content="""$_content"""
  136. try:
  137. msg = EmailMessage()
  138. msg.set_content(content)
  139. except (AttributeError, TypeError):
  140. # Python 2 MIMEText
  141. msg = EmailMessage(content)
  142. msg["Subject"] = subject
  143. msg["From"] = from_email
  144. msg["To"] = to_emails
  145. smtp = None
  146. try:
  147. if smtp_secure == "ssl":
  148. smtp = SMTP_SSL(smtp_host, smtp_port, timeout=timeout)
  149. else:
  150. smtp = SMTP(smtp_host, smtp_port, timeout=timeout)
  151. smtp.set_debuglevel(smtp_debug)
  152. if smtp_secure == "tls":
  153. smtp.starttls()
  154. if username or password:
  155. smtp.login(username, password)
  156. smtp.sendmail(msg["From"], msg["To"].split(","), msg.as_string())
  157. except SMTPException as err:
  158. # Output just the error (skip the Python stack trace) for SMTP errors
  159. print("Error sending: %r" % err)
  160. exit(1)
  161. except SocketError as err:
  162. print("Error connecting to %s:%d: %r" % (smtp_host, smtp_port, err))
  163. exit(1)
  164. finally:
  165. if smtp is not None:
  166. smtp.quit()
  167. EOF
  168. )"
  169. _ret=$?
  170. _debug "smtp_send_output" "$smtp_send_output"
  171. return "$_ret"
  172. }