SMTPSenderRefused:(530,b'5.7.0必须首先发出STARTTLS命令

2024-09-29 21:28:51 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试使用FastAPI创建用户身份验证API。我的范围是当一个新用户通过端点注册时,将发送一封电子邮件来验证JWT令牌,并且在验证后,将用户添加到数据库中。我最终面临的问题是smtplib.SMTPSenderRefused: (530, b'5.7.0 Must issue a STARTTLS command first每当控件到达Mailer类API时崩溃。我尝试在配置文件中启用TLS,但到目前为止没有成功

这是我的配置:

EMAIL_HOST_USER ='noreply@gmail.com'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_PASSWORD = 'my_password'
EMAIL_USE_TLS = True

Mailer_类:

from smtplib import SMTP
import smtplib
from email.message import EmailMessage
from core.config import Settings
 
settings = Settings()
 
 
class Mailer:
    @staticmethod
    def send_message(content: str, subject: str, mail_to: str):
        message = EmailMessage()
        message.set_content(content)
        message['Subject'] = subject
        message['From'] = settings.EMAIL_HOST_USER
        message['To'] = mail_to
        SMTP.ehlo()
        SMTP.starttls()
        SMTP.ehlo()
        SMTP.login(settings.EMAIL_HOST_USER, settings.EMAIL_HOST_PASSWORD)
        SMTP(settings.EMAIL_HOST).send_message(message)
 
 
 
    @staticmethod
    def send_confirmation_message(token: str, mail_to: str):
        confirmation_url = f'localhost:8000/registration/verify/{token}'
        message = '''Hi!
    Please confirm your registration: {}.'''.format(confirmation_url)
        Mailer.send_message(
            message,
            'Please confirm your registration',
            mail_to
        )

回溯:

INFO:     127.0.0.1:63757 - "POST /registration/?username=string&email=string%40string.com&password=srinf12 HTTP/1.1" 500 Internal Server Error
2021-07-13 22:54:04,745 INFO sqlalchemy.engine.Engine ROLLBACK
ERROR:    Exception in ASGI application
Traceback (most recent call last):
  File "c:\users\xone\desktop\fastapi-job-board\job_board\lib\site-packages\uvicorn\protocols\http\h11_impl.py", line 369, in run_asgi
    result = await app(self.scope, self.receive, self.send)
  File "c:\users\xone\desktop\fastapi-job-board\job_board\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 59, in __call__
    return await self.app(scope, receive, send)
  File "c:\users\xone\desktop\fastapi-job-board\job_board\lib\site-packages\fastapi\applications.py", line 199, in __call__
    await super().__call__(scope, receive, send)
  File "c:\users\xone\desktop\fastapi-job-board\job_board\lib\site-packages\starlette\applications.py", line 112, in __call__       
    await self.middleware_stack(scope, receive, send)
  File "c:\users\xone\desktop\fastapi-job-board\job_board\lib\site-packages\starlette\middleware\errors.py", line 181, in __call__  
    raise exc from None
  File "c:\users\xone\desktop\fastapi-job-board\job_board\lib\site-packages\starlette\middleware\errors.py", line 159, in __call__  
    await self.app(scope, receive, _send)
  File "c:\users\xone\desktop\fastapi-job-board\job_board\lib\site-packages\starlette\exceptions.py", line 82, in __call__
    raise exc from None
  File "c:\users\xone\desktop\fastapi-job-board\job_board\lib\site-packages\starlette\exceptions.py", line 71, in __call__
    await self.app(scope, receive, sender)
  File "c:\users\xone\desktop\fastapi-job-board\job_board\lib\site-packages\starlette\routing.py", line 580, in __call__
    await route.handle(scope, receive, send)
  File "c:\users\xone\desktop\fastapi-job-board\job_board\lib\site-packages\starlette\routing.py", line 241, in handle
    await self.app(scope, receive, send)
  File "c:\users\xone\desktop\fastapi-job-board\job_board\lib\site-packages\starlette\routing.py", line 52, in app
    response = await func(request)
  File "c:\users\xone\desktop\fastapi-job-board\job_board\lib\site-packages\fastapi\routing.py", line 216, in app
    raw_response = await run_endpoint_function(
  File "c:\users\xone\desktop\fastapi-job-board\job_board\lib\site-packages\fastapi\routing.py", line 149, in run_endpoint_function 
    return await dependant.call(**values)
  File ".\routes\route_user.py", line 32, in create_user
    Mailer.send_confirmation_message(confirmation["token"], form_data.email)
  File ".\core\mailer.py", line 26, in send_confirmation_message
    Mailer.send_message(
  File ".\core\mailer.py", line 17, in send_message
    SMTP(settings.EMAIL_HOST).send_message(message)
  File "C:\Python\Python38\lib\smtplib.py", line 970, in send_message
    return self.sendmail(from_addr, to_addrs, flatmsg, mail_options,
  File "C:\Python\Python38\lib\smtplib.py", line 871, in sendmail
    raise SMTPSenderRefused(code, resp, from_addr)
smtplib.SMTPSenderRefused: (530, b'5.7.0 Must issue a STARTTLS command first. r18sm11961741wrt.96 - gsmtp', 'noreply@gmail.com')

当我尝试使用较低级别的smtp功能时:

SMTP.ehlo()
SMTP.starttls()
SMTP.ehlo()
SMTP.login(settings.EMAIL_HOST_USER, settings.EMAIL_HOST_PASSWORD)

回溯:

TypeError: ehlo() missing 1 required positional argument: 'self'

Tags: inpyboardsendmessagelibpackagesline
1条回答
网友
1楼 · 发布于 2024-09-29 21:28:51

我在从FastAPI发送电子邮件时也遇到了同样的问题。这是我目前用来发送电子邮件的,希望这对我有所帮助:

import logging
import emails
from .validation import get_time_utc
from emails.template import JinjaTemplate
from fastapi import HTTPException
from models.aws_checker import Mailer
from starlette.responses import JSONResponse
from starlette.status import HTTP_406_NOT_ACCEPTABLE
from .const import (EMAIL_ACCESS_SUBJECT, EMAIL_ASSIGNED_TO,
                    EMAIL_EXCEPTION_SUBJECT, EMAIL_PASSWORD, EMAIL_SENDER)
from .aws_s3 import write_to_s3

resp_time = get_time_utc()

html_template = """
<!DOCTYPE html>
<html lang="en">
    <body>
        <p><i>(This is an automated service email)</i></p>
        <h2>
            Request Summary
        </h2>
        Requestor's Email: <b>{{ email }}</b><br/>
        Resource Name: <b>{{ resource_name }}</b><br/>
        Duration: <b>{{ duration }}</b><br/>
        Comments: <b>{{ comments }}</b><br/>
    </body>
    <h1></h1>
    <h1></h1>
    <img src="https://test.png" alt="test" style="width:10%">
    <style>
        img {
            display: block;
            margin-left: auto;
            margin-right: auto;
        }
    </style>
</html>
"""


async def send_email(environment: Mailer) -> JSONResponse:
    if environment.type == "access":
        subject = EMAIL_ACCESS_SUBJECT
        policy_path = resp_time.strftime("policy_%H_%M_%S")
        s3_path = environment.comments
        file_path = await write_to_s3(file_content=environment.comments,
                                      accountid=environment.accountid,
                                      requestors_email=environment.email)
        s3_path_hyperlink = '<a href="' + file_path + '"' + '>S3 Policy location</a>'
        print("%" * 50)
        print(s3_path_hyperlink)
        comments = s3_path_hyperlink
    elif environment.type == "notify":
        subject = EMAIL_ACCESS_SUBJECT
        comments = environment.comments
    else:
        subject = EMAIL_EXCEPTION_SUBJECT
        comments = environment.comments
    env = {
        "email": environment.email,
        "accountid": environment.accountid,
        "duration": environment.duration,
        "resource_name": environment.resource_name,
        "comments": comments
        }
    message = emails.Message(
        subject=subject,
        html=JinjaTemplate(html_template),
        mail_from=EMAIL_SENDER
    )
    smtp_options = {
        "host": 'smtp.gmail.com',
        "port": 465,
        "ssl": True,
        "user": EMAIL_SENDER,
        "password": EMAIL_PASSWORD
        }
    try:
        response = message.send(to=[EMAIL_ASSIGNED_TO, environment.email], render=env, smtp=smtp_options)
        logging.info(f"send email result: {response}")
        return JSONResponse(status_code=250, content={"message": "email has been sent"})
    except:
        raise HTTPException(status_code=HTTP_406_NOT_ACCEPTABLE)

相关问题 更多 >

    热门问题