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.

92 lines
2.5 KiB

  1. from smtplib import SMTPServerDisconnected, SMTPDataError
  2. from threading import Thread
  3. import time
  4. from django.conf import settings
  5. from django.core.mail import EmailMultiAlternatives
  6. from django.template.loader import render_to_string as render
  7. class EmailThread(Thread):
  8. MAX_TRIES = 3
  9. def __init__(self, message):
  10. Thread.__init__(self)
  11. self.message = message
  12. def run(self):
  13. for attempt in range(0, self.MAX_TRIES):
  14. try:
  15. # Make sure each retry creates a new connection:
  16. self.message.connection = None
  17. self.message.send()
  18. # No exception--great! Return from the retry loop
  19. return
  20. except (SMTPServerDisconnected, SMTPDataError) as e:
  21. if attempt + 1 == self.MAX_TRIES:
  22. # This was the last attempt and it failed:
  23. # re-raise the exception
  24. raise e
  25. # Wait 1s before retrying
  26. time.sleep(1)
  27. def make_message(name, to, ctx, headers={}):
  28. subject = render("emails/%s-subject.html" % name, ctx).strip()
  29. body = render("emails/%s-body-text.html" % name, ctx)
  30. html = render("emails/%s-body-html.html" % name, ctx)
  31. msg = EmailMultiAlternatives(subject, body, to=(to,), headers=headers)
  32. msg.attach_alternative(html, "text/html")
  33. return msg
  34. def send(msg, block=False):
  35. t = EmailThread(msg)
  36. if block or hasattr(settings, "BLOCKING_EMAILS"):
  37. # In tests, we send emails synchronously
  38. # so we can inspect the outgoing messages
  39. t.run()
  40. else:
  41. # Outside tests, we send emails on thread,
  42. # so there is no delay for the user.
  43. t.start()
  44. def login(to, ctx):
  45. send(make_message("login", to, ctx))
  46. def transfer_request(to, ctx):
  47. send(make_message("transfer-request", to, ctx))
  48. def alert(to, ctx, headers={}):
  49. send(make_message("alert", to, ctx, headers=headers))
  50. def verify_email(to, ctx):
  51. send(make_message("verify-email", to, ctx))
  52. def report(to, ctx, headers={}):
  53. m = make_message("report", to, ctx, headers=headers)
  54. send(m, block=True)
  55. def deletion_notice(to, ctx, headers={}):
  56. m = make_message("deletion-notice", to, ctx, headers=headers)
  57. send(m, block=True)
  58. def sms_limit(to, ctx):
  59. send(make_message("sms-limit", to, ctx))
  60. def call_limit(to, ctx):
  61. send(make_message("phone-call-limit", to, ctx))
  62. def sudo_code(to, ctx):
  63. send(make_message("sudo-code", to, ctx))