Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 
 

209 linhas
6.7 KiB

  1. # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
  2. # MIT License. See license.txt
  3. from __future__ import unicode_literals
  4. import frappe
  5. import smtplib
  6. import email.utils
  7. import _socket, sys
  8. from frappe.utils import cint
  9. from frappe import _
  10. def send(email, append_to=None, retry=1):
  11. """send the message or add it to Outbox Email"""
  12. if frappe.flags.in_test:
  13. frappe.flags.sent_mail = email.as_string()
  14. return
  15. if frappe.are_emails_muted():
  16. frappe.msgprint(_("Emails are muted"))
  17. return
  18. def _send(retry):
  19. try:
  20. smtpserver = SMTPServer(append_to=append_to)
  21. # validate is called in as_string
  22. email_body = email.as_string()
  23. smtpserver.sess.sendmail(email.sender, email.recipients + (email.cc or []), email_body)
  24. except smtplib.SMTPSenderRefused:
  25. frappe.throw(_("Invalid login or password"), title='Email Failed')
  26. raise
  27. except smtplib.SMTPRecipientsRefused:
  28. frappe.msgprint(_("Invalid recipient address"), title='Email Failed')
  29. raise
  30. except (smtplib.SMTPServerDisconnected, smtplib.SMTPAuthenticationError):
  31. if not retry:
  32. raise
  33. else:
  34. retry = retry - 1
  35. _send(retry)
  36. _send(retry)
  37. def get_outgoing_email_account(raise_exception_not_set=True, append_to=None):
  38. """Returns outgoing email account based on `append_to` or the default
  39. outgoing account. If default outgoing account is not found, it will
  40. try getting settings from `site_config.json`."""
  41. if not getattr(frappe.local, "outgoing_email_account", None):
  42. frappe.local.outgoing_email_account = {}
  43. if not frappe.local.outgoing_email_account.get(append_to or "default"):
  44. email_account = None
  45. if append_to:
  46. # append_to is only valid when enable_incoming is checked
  47. email_account = _get_email_account({"enable_outgoing": 1, "enable_incoming": 1, "append_to": append_to})
  48. if not email_account:
  49. email_account = get_default_outgoing_email_account(raise_exception_not_set=raise_exception_not_set)
  50. if not email_account and raise_exception_not_set:
  51. frappe.throw(_("Please setup default Email Account from Setup > Email > Email Account"),
  52. frappe.OutgoingEmailError)
  53. if email_account:
  54. if email_account.enable_outgoing and not getattr(email_account, 'from_site_config', False):
  55. email_account.password = email_account.get_password()
  56. email_account.default_sender = email.utils.formataddr((email_account.name, email_account.get("email_id")))
  57. frappe.local.outgoing_email_account[append_to or "default"] = email_account
  58. return frappe.local.outgoing_email_account[append_to or "default"]
  59. def get_default_outgoing_email_account(raise_exception_not_set=True):
  60. '''conf should be like:
  61. {
  62. "mail_server": "smtp.example.com",
  63. "mail_port": 587,
  64. "use_ssl": 1,
  65. "mail_login": "emails@example.com",
  66. "mail_password": "Super.Secret.Password",
  67. "auto_email_id": "emails@example.com",
  68. "email_sender_name": "Example Notifications",
  69. "always_use_account_email_id_as_sender": 0
  70. }
  71. '''
  72. email_account = _get_email_account({"enable_outgoing": 1, "default_outgoing": 1})
  73. if email_account:
  74. email_account.password = email_account.get_password()
  75. if not email_account and frappe.conf.get("mail_server"):
  76. # from site_config.json
  77. email_account = frappe.new_doc("Email Account")
  78. email_account.update({
  79. "smtp_server": frappe.conf.get("mail_server"),
  80. "smtp_port": frappe.conf.get("mail_port"),
  81. "use_tls": cint(frappe.conf.get("use_ssl") or 0),
  82. "login_id": frappe.conf.get("mail_login"),
  83. "email_id": frappe.conf.get("auto_email_id") or frappe.conf.get("mail_login") or 'notifications@example.com',
  84. "password": frappe.conf.get("mail_password"),
  85. "always_use_account_email_id_as_sender": frappe.conf.get("always_use_account_email_id_as_sender", 0)
  86. })
  87. email_account.from_site_config = True
  88. email_account.name = frappe.conf.get("email_sender_name") or "Frappe"
  89. if not email_account and not raise_exception_not_set:
  90. return None
  91. if frappe.are_emails_muted():
  92. # create a stub
  93. email_account = frappe.new_doc("Email Account")
  94. email_account.update({
  95. "email_id": "notifications@example.com"
  96. })
  97. return email_account
  98. def _get_email_account(filters):
  99. name = frappe.db.get_value("Email Account", filters)
  100. return frappe.get_doc("Email Account", name) if name else None
  101. class SMTPServer:
  102. def __init__(self, login=None, password=None, server=None, port=None, use_ssl=None, append_to=None):
  103. # get defaults from mail settings
  104. self._sess = None
  105. self.email_account = None
  106. self.server = None
  107. if server:
  108. self.server = server
  109. self.port = port
  110. self.use_ssl = cint(use_ssl)
  111. self.login = login
  112. self.password = password
  113. else:
  114. self.setup_email_account(append_to)
  115. def setup_email_account(self, append_to=None):
  116. self.email_account = get_outgoing_email_account(raise_exception_not_set=False, append_to=append_to)
  117. if self.email_account:
  118. self.server = self.email_account.smtp_server
  119. self.login = getattr(self.email_account, "login_id", None) or self.email_account.email_id
  120. self.password = self.email_account.password
  121. self.port = self.email_account.smtp_port
  122. self.use_ssl = self.email_account.use_tls
  123. self.sender = self.email_account.email_id
  124. self.always_use_account_email_id_as_sender = cint(self.email_account.get("always_use_account_email_id_as_sender"))
  125. @property
  126. def sess(self):
  127. """get session"""
  128. if self._sess:
  129. return self._sess
  130. # check if email server specified
  131. if not getattr(self, 'server'):
  132. err_msg = _('Email Account not setup. Please create a new Email Account from Setup > Email > Email Account')
  133. frappe.msgprint(err_msg)
  134. raise frappe.OutgoingEmailError, err_msg
  135. try:
  136. if self.use_ssl and not self.port:
  137. self.port = 587
  138. self._sess = smtplib.SMTP((self.server or "").encode('utf-8'),
  139. cint(self.port) or None)
  140. if not self._sess:
  141. err_msg = _('Could not connect to outgoing email server')
  142. frappe.msgprint(err_msg)
  143. raise frappe.OutgoingEmailError, err_msg
  144. if self.use_ssl:
  145. self._sess.ehlo()
  146. self._sess.starttls()
  147. self._sess.ehlo()
  148. if self.login and self.password:
  149. ret = self._sess.login((self.login or "").encode('utf-8'),
  150. (self.password or "").encode('utf-8'))
  151. # check if logged correctly
  152. if ret[0]!=235:
  153. frappe.msgprint(ret[1])
  154. raise frappe.OutgoingEmailError, ret[1]
  155. return self._sess
  156. except _socket.error, e:
  157. # Invalid mail server -- due to refusing connection
  158. frappe.msgprint(_('Invalid Outgoing Mail Server or Port'))
  159. type, value, traceback = sys.exc_info()
  160. raise frappe.ValidationError, e, traceback
  161. except smtplib.SMTPAuthenticationError, e:
  162. frappe.msgprint(_("Invalid login or password"))
  163. type, value, traceback = sys.exc_info()
  164. raise frappe.ValidationError, e, traceback
  165. except smtplib.SMTPException:
  166. frappe.msgprint(_('Unable to send emails at this time'))
  167. raise