Warm tip: This article is reproduced from serverfault.com, please click

python-无法在生产环境中发送电子邮件

(python - Can't send email in production)

发布于 2020-12-04 10:06:05

我正在开发网上商店,并且在本地计算机上一切正常。客户将商品添加到购物车,输入他的凭据,然后单击“下订单”,然后将订单确认发送到他的电子邮件中。即使使用redis + celery,它也可以正常工作,但是由于我将项目部署到服务器(linode.com)后,订单确认不起作用。工人承担了任务,但从不执行。我以为是芹菜引起的,所以我决定不使用任务管理器和队列就发送电子邮件。但这没有帮助。

我在服务器中使用UFW防火墙:

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       Anywhere                  
80/tcp                     ALLOW       Anywhere                  
Anywhere                   ALLOW       96.126.119.66             
443                        ALLOW       Anywhere                  
22/tcp (v6)                ALLOW       Anywhere (v6)             
80/tcp (v6)                ALLOW       Anywhere (v6)             
443 (v6)                   ALLOW       Anywhere (v6)  

我收到这样的错误:

[Errno 110]连接超时

希望你能帮助我理解这个问题

追溯:

Environment:


Request Method: POST
Request URL: https://bauerdress.ru/orders/create/

Django Version: 3.1
Python Version: 3.8.5
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.sites',
 'django.contrib.staticfiles',
 'shop.apps.ShopConfig',
 'cart.apps.CartConfig',
 'orders.apps.OrdersConfig',
 'wishlist.apps.WishlistConfig',
 'widget_tweaks',
 'crispy_forms',
 'information.apps.InformationConfig',
 'promotion.apps.PromotionConfig',
 'django_filters',
 'email_sub.apps.EmailSubConfig',
 'django_simple_coupons',
 'ckeditor',
 'flower',
 'allauth',
 'allauth.account',
 'allauth.socialaccount']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback (most recent call last):
  File "/home/kirill/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/home/kirill/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 179, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/kirill/bauer_dress/orders/views.py", line 46, in order_create
    order_created(order.id)
  File "/home/kirill/bauer_dress/orders/tasks.py", line 22, in order_created
    mail_sent = send_mail(subject, None, settings.EMAIL_HOST_USER, [order.email, settings.MAIL], html_message=html)
  File "/home/kirill/venv/lib/python3.8/site-packages/django/core/mail/__init__.py", line 61, in send_mail
    return mail.send()
  File "/home/kirill/venv/lib/python3.8/site-packages/django/core/mail/message.py", line 284, in send
    return self.get_connection(fail_silently).send_messages([self])
  File "/home/kirill/venv/lib/python3.8/site-packages/django/core/mail/backends/smtp.py", line 102, in send_messages
    new_conn_created = self.open()
  File "/home/kirill/venv/lib/python3.8/site-packages/django/core/mail/backends/smtp.py", line 62, in open
    self.connection = self.connection_class(self.host, self.port, **connection_params)
  File "/usr/lib/python3.8/smtplib.py", line 253, in __init__
    (code, msg) = self.connect(host, port)
  File "/usr/lib/python3.8/smtplib.py", line 339, in connect
    self.sock = self._get_socket(host, port, self.timeout)
  File "/usr/lib/python3.8/smtplib.py", line 308, in _get_socket
    return socket.create_connection((host, port), timeout,
  File "/usr/lib/python3.8/socket.py", line 808, in create_connection
    raise err
  File "/usr/lib/python3.8/socket.py", line 796, in create_connection
    sock.connect(sa)

Exception Type: TimeoutError at /orders/create/
Exception Value: [Errno 110] Connection timed out

views.py

from django.conf import settings
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse
from cart.cart import Cart
from .models import OrderItem, Order
from .forms import OrderCreateForm
from shop.models import Product
from django.contrib.admin.views.decorators import staff_member_required
from django_simple_coupons.forms import CouponApplyForm
import weasyprint
from django.template import loader
from django.core.mail import send_mail
from email_sub.models import Subscription
from django.core.exceptions import ObjectDoesNotExist
from .tasks import order_created




 def order_create(request):
    cart = Cart(request)
    coupon_apply_form = CouponApplyForm()
    if request.method == 'POST':
        form = OrderCreateForm(request.POST)
        if form.is_valid():
            order = form.save(commit=False)
            if cart.coupon:
                order.coupon = cart.coupon
                order.discount = cart.coupon.discount.value
            order.save()
            for item in cart:
                OrderItem.objects.create(
                    order=order,
                    product=item['product'],
                    product_set=item['product_set'],
                    price=item['product_set'].price,
                    quantity=item['quantity'],
                    size = item['product_set'].size_set,
                    color = item['color']
                )
            try:
                Subscription.objects.get(email=order.email)
            except ObjectDoesNotExist:
                Subscription.objects.create(name=order.first_name, surname=order.last_name, email=order.email)
            
            order_created(order.id) # <--- order confirmation email 
            cart.clear()
            if cart.coupon:
                cart.clear_coupon()
            return render(request, 'orders/order/created.html', {'order': order})
    else:
        form = OrderCreateForm()
    return render(request, 'orders/order/create_v2.html', {
        'cart': cart,
        'form': form,
        'coupon_apply_form': coupon_apply_form})

task.py

def order_created(order_id):
    """
    Task for sending mail if order created
    """
    order = Order.objects.get(id=order_id)
    subject = 'Заказ #{}'.format(order.id)
    html = loader.render_to_string('orders/order/mail2.html', context={'order': order})
    send_mail = send_mail(subject, None, settings.EMAIL_HOST_USER, [order.email, settings.MAIL], html_message=html)
    return send_mail

settings.py(smtp设置的一部分)

#smtp
EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'myuser@gmail.com' #real data used in production
EMAIL_HOST_PASSWORD = '1234'
EMAIL_PORT = 587
Questioner
Kirill Bauer
Viewed
11
Kirill Bauer 2020-12-07 19:58:36

问题是我使用Linode和linode阻止端口,偶然发现它,因为我读过GoDaddy也做同样的事情

需要从你的Linode发送邮件吗?默认情况下,新的Linode帐户的端口25、465和587被阻止。要删除这些限制,请查看本指南,然后在创建Linode后打开支持通知单。

为了打击垃圾邮件,Linode限制了2019年11月5日之后创建的新帐户在所有Linode的端口25、465和587上的出站连接。