Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 
 
 

127 řádky
3.6 KiB

  1. # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
  2. # MIT License. See license.txt
  3. import frappe
  4. import smtplib
  5. import email.utils
  6. import _socket, sys
  7. from frappe import _
  8. from frappe.utils import cint, cstr, parse_addr
  9. CONNECTION_FAILED = _('Could not connect to outgoing email server')
  10. AUTH_ERROR_TITLE = _("Invalid Credentials")
  11. AUTH_ERROR = _("Incorrect email or password. Please check your login credentials.")
  12. SOCKET_ERROR_TITLE = _("Incorrect Configuration")
  13. SOCKET_ERROR = _("Invalid Outgoing Mail Server or Port")
  14. SEND_MAIL_FAILED = _("Unable to send emails at this time")
  15. EMAIL_ACCOUNT_MISSING = _('Email Account not setup. Please create a new Email Account from Setup > Email > Email Account')
  16. class InvalidEmailCredentials(frappe.ValidationError):
  17. pass
  18. def send(email, append_to=None, retry=1):
  19. """Deprecated: Send the message or add it to Outbox Email"""
  20. def _send(retry):
  21. from frappe.email.doctype.email_account.email_account import EmailAccount
  22. try:
  23. email_account = EmailAccount.find_outgoing(match_by_doctype=append_to)
  24. smtpserver = email_account.get_smtp_server()
  25. # validate is called in as_string
  26. email_body = email.as_string()
  27. smtpserver.sess.sendmail(email.sender, email.recipients + (email.cc or []), email_body)
  28. except smtplib.SMTPSenderRefused:
  29. frappe.throw(_("Invalid login or password"), title='Email Failed')
  30. raise
  31. except smtplib.SMTPRecipientsRefused:
  32. frappe.msgprint(_("Invalid recipient address"), title='Email Failed')
  33. raise
  34. except (smtplib.SMTPServerDisconnected, smtplib.SMTPAuthenticationError):
  35. if not retry:
  36. raise
  37. else:
  38. retry = retry - 1
  39. _send(retry)
  40. _send(retry)
  41. class SMTPServer:
  42. def __init__(self, server, login=None, password=None, port=None, use_tls=None, use_ssl=None):
  43. self.login = login
  44. self.password = password
  45. self._server = server
  46. self._port = port
  47. self.use_tls = use_tls
  48. self.use_ssl = use_ssl
  49. self._session = None
  50. if not self.server:
  51. frappe.msgprint(EMAIL_ACCOUNT_MISSING, raise_exception=frappe.OutgoingEmailError)
  52. @property
  53. def port(self):
  54. port = self._port or (self.use_ssl and 465) or (self.use_tls and 587)
  55. return cint(port)
  56. @property
  57. def server(self):
  58. return cstr(self._server or "")
  59. def secure_session(self, conn):
  60. """Secure the connection incase of TLS.
  61. """
  62. if self.use_tls:
  63. conn.ehlo()
  64. conn.starttls()
  65. conn.ehlo()
  66. @property
  67. def session(self):
  68. if self.is_session_active():
  69. return self._session
  70. SMTP = smtplib.SMTP_SSL if self.use_ssl else smtplib.SMTP
  71. try:
  72. _session = SMTP(self.server, self.port)
  73. if not _session:
  74. frappe.msgprint(CONNECTION_FAILED, raise_exception=frappe.OutgoingEmailError)
  75. self.secure_session(_session)
  76. if self.login and self.password:
  77. res = _session.login(str(self.login or ""), str(self.password or ""))
  78. # check if logged correctly
  79. if res[0]!=235:
  80. frappe.msgprint(res[1], raise_exception=frappe.OutgoingEmailError)
  81. self._session = _session
  82. return self._session
  83. except smtplib.SMTPAuthenticationError as e:
  84. self.throw_invalid_credentials_exception()
  85. except _socket.error as e:
  86. # Invalid mail server -- due to refusing connection
  87. frappe.throw(SOCKET_ERROR, title=SOCKET_ERROR_TITLE)
  88. except smtplib.SMTPException:
  89. frappe.msgprint(SEND_MAIL_FAILED)
  90. raise
  91. def is_session_active(self):
  92. if self._session:
  93. try:
  94. return self._session.noop()[0] == 250
  95. except Exception:
  96. return False
  97. def quit(self):
  98. if self.is_session_active():
  99. self._session.quit()
  100. @classmethod
  101. def throw_invalid_credentials_exception(cls):
  102. frappe.throw(AUTH_ERROR, title=AUTH_ERROR_TITLE, exc=InvalidEmailCredentials)