export_emails.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. # -*- coding: utf-8 -*-
  2. from __future__ import unicode_literals, print_function
  3. import sys
  4. import csv
  5. from django.conf import settings
  6. from django.contrib.auth import get_user_model
  7. from django.contrib.auth.models import Group
  8. from django.core.management.base import BaseCommand, CommandError
  9. from django_extensions.management.utils import signalcommand
  10. FORMATS = [
  11. 'address',
  12. 'emails',
  13. 'google',
  14. 'outlook',
  15. 'linkedin',
  16. 'vcard',
  17. ]
  18. def full_name(**kwargs):
  19. """Return full name or username."""
  20. first_name = kwargs.get('first_name')
  21. last_name = kwargs.get('last_name')
  22. name = " ".join(n for n in [first_name, last_name] if n)
  23. if name:
  24. return name
  25. name = kwargs.get('name')
  26. if name:
  27. return name
  28. username = kwargs.get('username')
  29. if username:
  30. return username
  31. return ""
  32. class Command(BaseCommand):
  33. help = "Export user email address list in one of a number of formats."
  34. args = "[output file]"
  35. label = 'filename to save to'
  36. can_import_settings = True
  37. encoding = 'utf-8' # RED_FLAG: add as an option -DougN
  38. def __init__(self, *args, **kwargs):
  39. super().__init__(*args, **kwargs)
  40. self.UserModel = get_user_model()
  41. def add_arguments(self, parser):
  42. super().add_arguments(parser)
  43. parser.add_argument(
  44. '--group', '-g', action='store', dest='group', default=None,
  45. help='Limit to users which are part of the supplied group name',
  46. ),
  47. parser.add_argument(
  48. '--format', '-f', action='store', dest='format', default=FORMATS[0],
  49. help="output format. May be one of %s." % ", ".join(FORMATS),
  50. )
  51. def full_name(self, **kwargs):
  52. return getattr(settings, 'EXPORT_EMAILS_FULL_NAME_FUNC', full_name)(**kwargs)
  53. @signalcommand
  54. def handle(self, *args, **options):
  55. if len(args) > 1:
  56. raise CommandError("extra arguments supplied")
  57. group = options['group']
  58. if group and not Group.objects.filter(name=group).count() == 1:
  59. names = "', '".join(g['name'] for g in Group.objects.values('name'))
  60. if names:
  61. names = "'" + names + "'."
  62. raise CommandError("Unknown group '" + group + "'. Valid group names are: " + names)
  63. UserModel = get_user_model()
  64. order_by = getattr(settings, 'EXPORT_EMAILS_ORDER_BY', ['last_name', 'first_name', 'username', 'email'])
  65. fields = getattr(settings, 'EXPORT_EMAILS_FIELDS', ['last_name', 'first_name', 'username', 'email'])
  66. qs = UserModel.objects.all().order_by(*order_by)
  67. if group:
  68. qs = qs.filter(groups__name=group).distinct()
  69. qs = qs.values(*fields)
  70. getattr(self, options['format'])(qs)
  71. def address(self, qs):
  72. """
  73. Single entry per line in the format of:
  74. "full name" <my@address.com>;
  75. """
  76. self.stdout.write("\n".join('"%s" <%s>;' % (self.full_name(**ent), ent.get('email', '')) for ent in qs))
  77. self.stdout.write("\n")
  78. def emails(self, qs):
  79. """
  80. Single entry with email only in the format of:
  81. my@address.com,
  82. """
  83. self.stdout.write(",\n".join(ent['email'] for ent in qs if ent.get('email')))
  84. self.stdout.write("\n")
  85. def google(self, qs):
  86. """CSV format suitable for importing into google GMail"""
  87. csvf = csv.writer(sys.stdout)
  88. csvf.writerow(['Name', 'Email'])
  89. for ent in qs:
  90. csvf.writerow([self.full_name(**ent), ent.get('email', '')])
  91. def linkedin(self, qs):
  92. """
  93. CSV format suitable for importing into linkedin Groups.
  94. perfect for pre-approving members of a linkedin group.
  95. """
  96. csvf = csv.writer(sys.stdout)
  97. csvf.writerow(['First Name', 'Last Name', 'Email'])
  98. for ent in qs:
  99. csvf.writerow([ent.get('first_name', ''), ent.get('last_name', ''), ent.get('email', '')])
  100. def outlook(self, qs):
  101. """CSV format suitable for importing into outlook"""
  102. csvf = csv.writer(sys.stdout)
  103. columns = ['Name', 'E-mail Address', 'Notes', 'E-mail 2 Address', 'E-mail 3 Address',
  104. 'Mobile Phone', 'Pager', 'Company', 'Job Title', 'Home Phone', 'Home Phone 2',
  105. 'Home Fax', 'Home Address', 'Business Phone', 'Business Phone 2',
  106. 'Business Fax', 'Business Address', 'Other Phone', 'Other Fax', 'Other Address']
  107. csvf.writerow(columns)
  108. empty = [''] * (len(columns) - 2)
  109. for ent in qs:
  110. csvf.writerow([self.full_name(**ent), ent.get('email', '')] + empty)
  111. def vcard(self, qs):
  112. """VCARD format."""
  113. try:
  114. import vobject
  115. except ImportError:
  116. print(self.style.ERROR("Please install vobject to use the vcard export format."))
  117. sys.exit(1)
  118. out = sys.stdout
  119. for ent in qs:
  120. card = vobject.vCard()
  121. card.add('fn').value = self.full_name(**ent)
  122. if ent.get('last_name') and ent.get('first_name'):
  123. card.add('n').value = vobject.vcard.Name(ent['last_name'], ent['first_name'])
  124. else:
  125. # fallback to fullname, if both first and lastname are not declared
  126. card.add('n').value = vobject.vcard.Name(self.full_name(**ent))
  127. if ent.get('email'):
  128. emailpart = card.add('email')
  129. emailpart.value = ent['email']
  130. emailpart.type_param = 'INTERNET'
  131. out.write(card.serialize())