mail_news.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. # Copyright 2013 The Distro Tracker Developers
  2. # See the COPYRIGHT file at the top-level directory of this distribution and
  3. # at http://deb.li/DTAuthors
  4. #
  5. # This file is part of Distro Tracker. It is subject to the license terms
  6. # in the LICENSE file found in the top-level directory of this
  7. # distribution and at http://deb.li/DTLicense. No part of Distro Tracker,
  8. # including this file, may be copied, modified, propagated, or distributed
  9. # except according to the terms contained in the LICENSE file.
  10. """
  11. Module implementing the processing of received emails which could be turned
  12. into news items.
  13. """
  14. from __future__ import unicode_literals
  15. from django.utils.html import escape
  16. from distro_tracker.core.utils import message_from_bytes
  17. from distro_tracker.core.utils import get_or_none
  18. from distro_tracker.core.models import News
  19. from distro_tracker.core.models import EmailNews
  20. from distro_tracker.core.models import PackageName
  21. from distro_tracker import vendor
  22. def create_news(message, package, create_package=False, **kwargs):
  23. """
  24. Create a news item from the given message.
  25. The created news parameters are:
  26. - title - the Subject of the message
  27. - content - the message content itself
  28. - content_type - message/rfc822
  29. :param message: A message which should be turned into a news item.
  30. :type message: :class:`email.message.Message`
  31. :param package: The package for which this news item should be created.
  32. :type package: :class:`distro_tracker.core.models.PackageName` or a string.
  33. :returns: The created news item
  34. :rtype: :class:`distro_tracker.core.models.News`
  35. """
  36. if not isinstance(package, PackageName):
  37. if create_package:
  38. package, _ = PackageName.objects.get_or_create(name=package)
  39. else:
  40. package = get_or_none(PackageName, name=package)
  41. if package is None: # Don't record news for non-existing packages
  42. return
  43. return EmailNews.objects.create_email_news(message, package, **kwargs)
  44. def process(message):
  45. """
  46. Process an incoming message which is potentially a news item.
  47. The function first tries to call the vendor-provided function
  48. :func:`create_news_from_email_message
  49. <distro_tracker.vendor.skeleton.rules.create_news_from_email_message>`.
  50. If this function does not exist a news item is created only if there is a
  51. ``X-Distro-Tracker-Package`` header set giving the name of an existing
  52. source or pseudo package.
  53. If the ``X-Distro-Tracker-Url`` is also set then the content of the message
  54. will not be the email content, rather the URL given in this header.
  55. :param message: The received message
  56. :type message: :class:`bytes`
  57. """
  58. assert isinstance(message, bytes), 'Message must be given as bytes'
  59. msg = message_from_bytes(message)
  60. # Try asking the vendor function first.
  61. created, implemented = vendor.call('create_news_from_email_message', msg)
  62. if implemented and created:
  63. return
  64. # If the message has an X-Distro-Tracker-Package header, it is
  65. # automatically made into a news item.
  66. if 'X-Distro-Tracker-Package' in msg:
  67. package_name = msg['X-Distro-Tracker-Package']
  68. package = get_or_none(PackageName, name=package_name)
  69. if not package:
  70. return
  71. if 'X-Distro-Tracker-Url' not in msg:
  72. create_news(msg, package)
  73. else:
  74. distro_tracker_url = msg['X-Distro-Tracker-Url']
  75. News.objects.create(
  76. title=distro_tracker_url,
  77. content="<a href={url}>{url}</a>".format(
  78. url=escape(distro_tracker_url)),
  79. package=package,
  80. content_type='text/html')