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.

200 lines
6.2 KiB

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