Django中/admin/montly_email/的SMTPRecipientsRefused错误

1 投票
1 回答
947 浏览
提问于 2025-04-18 18:09

我有一个包含超过1000个电子邮件地址的csv文件,Django需要向这些地址发送邮件。但是,当我上传这个超过1000条记录的csv文件时,出现了下面的错误

File "/user/Envs/project/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 112, in get_response
  response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/user/Envs/project/local/lib/python2.7/site-packages/django/contrib/admin/views/decorators.py", line 17, in _checklogin
  return view_func(request, *args, **kwargs)
File "/user/apps/project_webapp/appy/customadmin/views.py", line 1131, in send_monthly_email
  connection.send_messages(emails)
File "/user/apps/project_webapp/appy/mailer/backend.py", line 57, in send_messages
  sent = self._send(message)
File "/user/Envs/project/local/lib/python2.7/site-packages/django/core/mail/backends/smtp.py", line 110, in _send
  self.connection.sendmail(from_email, recipients, message.as_bytes())
File "/usr/lib/python2.7/smtplib.py", line 735, in sendmail
  raise SMTPRecipientsRefused(senderrs)

但是当我用只包含10个电子邮件的同一个csv文件时,它就没有任何错误,顺利发送了

以下是我的代码

settings.py

EMAIL_BACKEND = "mailer.backend.DbBackend"
EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.sendgrid.net' #'smtp.gmail.com'
EMAIL_HOST_USER = 'xxxxx'
EMAIL_HOST_PASSWORD = 'xxxxxx'
EMAIL_PORT = '587'
EMAIL_SUBJECT_PREFIX = 'xxxxxxxxx'
DEFAULT_FROM_EMAIL = 'some@example.com'

我想在Django发送邮件之前,把要发送的消息保存到我的数据库里,所以我写了一个自定义的邮件后端

DbBackend.py

from django.core.mail.backends.smtp import EmailBackend
from mailer.models import Message
from django.conf import settings

class DbBackend(EmailBackend):
    def __init__(self, host=None, port=None, username=None, password=None,
                 use_tls=None, fail_silently=False, **kwargs):
        super(EmailBackend, self).__init__(fail_silently=fail_silently)
        self.host = host or settings.EMAIL_HOST
        self.port = port or settings.EMAIL_PORT
        if username is None:
            self.username = settings.EMAIL_HOST_USER
        else:
            self.username = username
        if password is None:
            self.password = settings.EMAIL_HOST_PASSWORD
        else:
            self.password = password
        if use_tls is None:
            self.use_tls = settings.EMAIL_USE_TLS
        else:
            self.use_tls = use_tls
        self.connection = None

        #By default Django has this self._lock variable active, we have to deactivate it in 
        #order to save the messages in our database, without deactivating the message objects
        #will be locked and django doesn't allow to save the locked objects  

        # self._lock = threading.RLock()

    def send_messages(self, email_messages):
        """
        Sends one or more EmailMessage objects and returns the number of email
        messages sent.
        """
        if not email_messages:
            return

        # Save the messages to your database
        for message in email_messages:
            msg = Message()
            msg.email = message
            msg.save()
        # with self._lock:
        new_conn_created = self.open()
        if not self.connection:
            # We failed silently on open().
            # Trying to send would be pointless.
            return
        num_sent = 0
        for message in email_messages:
            sent = self._send(message)
            if sent:
                num_sent += 1
        if new_conn_created:
            self.close()
        return num_sent

views.py

from django.core import mail

def send_monthly_email(request):
    if request.method == "POST":
        form = MonthlyEmailForm(request.POST, request.FILES)
        if form.is_valid():
            subject = request.POST.get('subject')
            message = request.POST.get('message')
            from_email = 'orders@example.com'
            recipient_list = request.FILES.get('recipient_list')
            input_file = csv.DictReader(recipient_list)
            connection = mail.get_connection()
            emails = []
            for row in input_file:
                 recipient = row.get('%s Recipients' % state).strip()
                 email = mail.EmailMessage(subject, message, from_email, [recipient,])
                 email.content_subtype = "html"
                 emails.append(email)
            connection.open()
            connection.send_messages(emails)
            connection.close()
            return HttpResponseRedirect('/admin/')
        else:
            response = RequestContext(request, {"form": form})
            return render_to_response('customadmin/monthly_email_form.html', response)
   data = {.................}
   form = MonthlyEmailForm(initial=data)
   response = RequestContext(request, {"form": form})
   return render_to_response('customadmin/monthly_email_form.html', response)

所以根据我上面的代码,当我尝试向1000个电子邮件发送消息时,出现了之前提到的错误。我想可能是我的DbBackend.py文件有问题,于是把设置从 EMAIL_BACKEND = "mailer.backend.DbBackend" 改成了 EMAIL_BACKEND = django.core.mail.backends.smtp.EmailBackend,也就是Django的默认后端,但即便如此,我还是收到了同样的错误

我在网上查了很多帖子,但还是没能解决这个问题,有人能帮我解决这个错误吗?为什么在尝试同时向1000个邮箱发送邮件时会出错,而向10个邮箱发送时却能成功呢?

提前谢谢大家

1 个回答

0

试试用 as_string(),不要用 as_bytes()

撰写回答