Django send_mail 方法导致邮件发送速度极慢

103 阅读2分钟

在使用 Django 1.5.2 发送邮件时,出现了邮件发送速度极慢的问题。通常,发送大约 100 封邮件需要 2/3 分钟;但是,在最近,发送相同的数量邮件有时需要长达 2 个小时。

在发送邮件时,使用最多 5 个线程来尝试发送邮件,使用 send_mail 方法(docs.djangoproject.com/en/dev/topi…

使用 Postfix 和 Gmail 帐户作为邮件服务器。在发送单封邮件时(在 Django Shell 中或当一个线程在另一个小时发送单封邮件时),没有出现问题(邮件会立即发送)。每次 send_mail 调用都会向大约 4 个收件人发送邮件,因此总共大约需要发送 100 * 4 * 25 封邮件。

在查看 mail.info 日志时,每个日志都会在实际发送邮件的时间附近加上时间戳,这表明问题可能出在 Django 中。

该问题难点在于,不知道如何调试,应该从哪里入手,以及问题是来自 Django 还是 Gmail。

  1. 解决方案

  2. 使用 Celery 替换线程

    可以考虑使用 Celery 来替换线程。Celery 是一个分布式任务队列,可以用来管理和执行任务。通过使用 Celery,可以在多个服务器上并行发送邮件,从而提高邮件发送速度。

  3. 使用电子邮件服务

    可以使用电子邮件服务,例如 SendGrid,来发送邮件。电子邮件服务可以提供可靠的邮件发送服务,并且可以轻松集成到 Django 中。

  4. 代码示例

    使用 Celery 发送邮件的代码示例如下:

from celery import Celery

app = Celery('tasks', broker='amqp://localhost//')

@app.task
def send_email(subject, message, recipients):
    """
    发送邮件的任务。

    Args:
        subject: 邮件主题。
        message: 邮件内容。
        recipients: 邮件收件人列表。
    """

    # 发送邮件。
    send_mail(
        subject,
        message,
        'from@example.com',
        recipients
    )

在 Django 中集成 Celery 的代码示例如下:

# settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # Celery.
    'djcelery',
]

CELERY_BROKER_URL = 'amqp://localhost//'

在 Django 中使用 Celery 发送邮件的代码示例如下:

# views.py
from celery_tasks.tasks import send_email

def send_mail_view(request):
    """
    发送邮件的视图。
    """

    # 发送邮件。
    send_email.delay('Subject', 'Message', ['recipient1@example.com', 'recipient2@example.com'])

    return HttpResponse('邮件已发送。')

使用电子邮件服务 SendGrid 的代码示例如下:

# settings.py
EMAIL_BACKEND = 'sgbackend.SendGridBackend'

SENDGRID_API_KEY = 'YOUR_SENDGRID_API_KEY'

在 Django 中使用 SendGrid 发送邮件的代码示例如下:

# views.py
from django.core.mail import send_mail

def send_mail_view(request):
    """
    发送邮件的视图。
    """

    # 发送邮件。
    send_mail(
        'Subject',
        'Message',
        'from@example.com',
        ['recipient1@example.com', 'recipient2@example.com']
    )

    return HttpResponse('邮件已发送。')