mail.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. import sys
  2. import smtplib
  3. from celery.utils import get_symbol_by_name
  4. try:
  5. from email.mime.text import MIMEText
  6. except ImportError:
  7. from email.MIMEText import MIMEText # noqa
  8. supports_timeout = sys.version_info >= (2, 6)
  9. class SendmailWarning(UserWarning):
  10. """Problem happened while sending the email message."""
  11. class Message(object):
  12. def __init__(self, to=None, sender=None, subject=None, body=None,
  13. charset="us-ascii"):
  14. self.to = to
  15. self.sender = sender
  16. self.subject = subject
  17. self.body = body
  18. self.charset = charset
  19. if not isinstance(self.to, (list, tuple)):
  20. self.to = [self.to]
  21. def __repr__(self):
  22. return "<Email: To:%r Subject:%r>" % (self.to, self.subject)
  23. def __str__(self):
  24. msg = MIMEText(self.body, "plain", self.charset)
  25. msg["Subject"] = self.subject
  26. msg["From"] = self.sender
  27. msg["To"] = ", ".join(self.to)
  28. return msg.as_string()
  29. class Mailer(object):
  30. def __init__(self, host="localhost", port=0, user=None, password=None,
  31. timeout=2, use_ssl=False, use_tls=False):
  32. self.host = host
  33. self.port = port
  34. self.user = user
  35. self.password = password
  36. self.timeout = timeout
  37. self.use_ssl = use_ssl
  38. self.use_tls = use_tls
  39. def send(self, message):
  40. if supports_timeout:
  41. self._send(message, timeout=self.timeout)
  42. else:
  43. import socket
  44. old_timeout = socket.getdefaulttimeout()
  45. socket.setdefaulttimeout(self.timeout)
  46. try:
  47. self._send(message)
  48. finally:
  49. socket.setdefaulttimeout(old_timeout)
  50. def _send(self, message, **kwargs):
  51. if (self.use_ssl):
  52. client = smtplib.SMTP_SSL(self.host, self.port, **kwargs)
  53. else:
  54. client = smtplib.SMTP(self.host, self.port, **kwargs)
  55. if self.use_tls:
  56. client.ehlo()
  57. client.starttls()
  58. client.ehlo()
  59. if self.user and self.password:
  60. client.login(self.user, self.password)
  61. client.sendmail(message.sender, message.to, str(message))
  62. client.quit()
  63. class ErrorMail(object):
  64. # pep8.py borks on a inline signature separator and
  65. # says "trailing whitespace" ;)
  66. EMAIL_SIGNATURE_SEP = "-- "
  67. #: Format string used to generate error email subjects.
  68. subject = """\
  69. [celery@%(hostname)s] Error: Task %(name)s (%(id)s): %(exc)s
  70. """
  71. #: Format string used to generate error email content.
  72. body = """
  73. Task %%(name)s with id %%(id)s raised exception:\n%%(exc)r
  74. Task was called with args: %%(args)s kwargs: %%(kwargs)s.
  75. The contents of the full traceback was:
  76. %%(traceback)s
  77. %(EMAIL_SIGNATURE_SEP)s
  78. Just to let you know,
  79. celeryd at %%(hostname)s.
  80. """ % {"EMAIL_SIGNATURE_SEP": EMAIL_SIGNATURE_SEP}
  81. error_whitelist = None
  82. def __init__(self, task, **kwargs):
  83. #subject=None, body=None, error_whitelist=None
  84. self.task = task
  85. self.email_subject = kwargs.get("subject", self.subject)
  86. self.email_body = kwargs.get("body", self.body)
  87. self.error_whitelist = getattr(task, "error_whitelist")
  88. def should_send(self, context, exc):
  89. allow_classes = tuple(map(get_symbol_by_name, self.error_whitelist))
  90. return not self.error_whitelist or isinstance(exc, allow_classes)
  91. def format_subject(self, context):
  92. return self.subject.strip() % context
  93. def format_body(self, context):
  94. return self.body.strip() % context
  95. def send(self, context, exc, fail_silently=True):
  96. if self.should_send(context, exc):
  97. self.task.app.mail_admins(self.format_subject(context),
  98. self.format_body(context),
  99. fail_silently=fail_silently)