Массовая отправка электронных писем в Django с одним и тем же вложением

#python #django #email #bulk-email

#python #django #Адрес электронной почты #массовая отправка электронной почты

Вопрос:

Я хочу отправлять электронные письма пользователям моего сайта, которые должны присутствовать на собрании (т. Е. гости), каждый с (одинаковым) вложением PDF. Я делаю это с помощью встроенной в Django функции массовой отправки электронной почты в connection.send_messages(messages) . На данный момент я делаю это:

 guests = Guest.objects.all()
connection = mail.get_connection()
connection.open()
messages = []
for guest in guests:
    msg = EmailMultiAlternatives(title, text_content, from_address, [guest.email], connection=connection)
    msg.attach_alternative(html_content, 'text/html')
    pdf_data = open(os.path.join(settings.MEDIA_ROOT, 'uploads/flyer.pdf'))
    msg.attach('Invitation Card.pdf', pdf_data.read(), 'application/pdf')
    pdf_data.close()
    messages.append(msg)
connection.send_messages(messages)
connection.close()
  

Теперь, когда я делаю это следующим образом, один и тот же PDF-файл будет загружен для каждого электронного письма, прикреплен отдельно, а затем отправлен отдельно для каждого электронного письма, как если бы это были разные PDF-файлы. Если размер файла составляет 10 МБ, эти 10 МБ будут загружены на мой почтовый сервер для каждого отдельного гостя, где это могло быть только один раз.

Итак, вопрос в том, можно ли прикрепить файл ко всем электронным письмам сразу, тем самым загрузив его только один раз? Или я просто делаю это неправильно?

Обновить:

Если я изменю строку прикрепления на следующую:

 msg.attach_file(os.path.join(settings.MEDIA_ROOT, 'uploads/flyer.pdf'))
  

решит ли это мою проблему?

Ответ №1:

Глядя на django/core/mail/message.py reveals attach_file — это просто удобная функция, которая открывает файл для вас перед вызовом attach :

 def attach_file(self, path, mimetype=None):
    """Attaches a file from the filesystem."""
    filename = os.path.basename(path)
    content = open(path, 'rb').read()
    self.attach(filename, content, mimetype)
  

Вы могли бы избежать многократного открытия вложения и чтения его в память, если вы создадите подкласс EmailMultiAlternatives и переопределите attach метод. Вам следует изучить возможность использования для этого очереди заданий, такой как celery.

Комментарии:

1. Хм, хорошо. Спасибо, что посмотрели, мне просто было лень открывать это самому 🙂 Можете ли вы придумать какой-нибудь способ обойти эту проблему?

2. Нет, но вы можете рассмотреть возможность использования ссылки, а не фактического вложения.

3. Да, в данном случае это не совсем вариант : (

4. Вам следует подумать об использовании celery, его интеграция с django действительно великолепна. Было бы легко развернуть пакетную рассылку электронной почты как задачу и выполнять ее асинхронно на рабочем компьютере (или разбить ее и использовать несколько рабочих компьютеров).

5. Ммм, да, хорошая идея. В прошлом у меня были проблемы с тем, чтобы заставить celery работать над Webfaction (и в конечном итоге я использовал потоки python там, где это было необходимо), но, возможно, сейчас как раз то время, когда мне нужно, наконец, сесть и разобраться. Либо это, либо, по-видимому, написать какую-то пользовательскую функциональность электронной почты.