0

我正在尝试将 Cookiecutter Django 项目部署到 AWS(EC2)。拥有此凭证的 AWS 用户拥有完整的 S3、SES 和 SNS 策略。EC2 服务器还具有具有完整 SES/S3 策略的角色。

在 envs 的生产文件中,我有这样设置的密钥。

DJANGO_AWS_ACCESS_KEY_ID=xxxxxxxxx
DJANGO_AWS_SECRET_ACCESS_KEY=xxxxxxxxxx
DJANGO_AWS_STORAGE_BUCKET_NAME=xxxxxxxxxx 

在我的设置中

AWS_S3_REGION_NAME = env("DJANGO_AWS_S3_REGION_NAME", default=None)
AWS_ACCESS_KEY_ID = env("DJANGO_AWS_ACCESS_KEY_ID")
AWS_SECRET_ACCESS_KEY = env("DJANGO_AWS_SECRET_ACCESS_KEY")
AWS_STORAGE_BUCKET_NAME = env("DJANGO_AWS_STORAGE_BUCKET_NAME")
EMAIL_BACKEND = "anymail.backends.amazon_ses.EmailBackend"
ANYMAIL = {}

一切都很好,直到项目尝试使用 SES 发送电子邮件并崩溃并出现以下错误。

到目前为止,我已经尝试过:

  • 将 DJANGO_AWS_S3_REGION_NAME 添加到环境中的生产文件中 - 没有结果
  • 使用 aws cli 在 aws config 中添加区域 - 无结果
  • 使用凭据和区域覆盖 ANYMAIL ={} 中的设置 - 没有结果
  • 制作一个空白项目,只需添加 aws 凭据而不更改其他任何内容 - 没有结果
  • 在另一个项目上手动创建具有相同凭据的 boto3.session.client 并发送邮件 - 它可以工作

这是错误。'NoneType' 对象的第二部分没有属性 'send_raw_email' 在此之后重复了很多。

django_1    | [2021-08-13 13:58:14 +0000] [12] [ERROR] Error handling request /accounts/signup/
django_1    | Traceback (most recent call last):
django_1    |   File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
django_1    |     response = get_response(request)
django_1    |   File "/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
django_1    |     response = wrapped_callback(request, *callback_args, **callback_kwargs)
django_1    |   File "/usr/local/lib/python3.9/contextlib.py", line 79, in inner
django_1    |     return func(*args, **kwds)
django_1    |   File "/usr/local/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view
django_1    |     return self.dispatch(request, *args, **kwargs)
django_1    |   File "/usr/local/lib/python3.9/site-packages/django/utils/decorators.py", line 43, in _wrapper
django_1    |     return bound_method(*args, **kwargs)
django_1    |   File "/usr/local/lib/python3.9/site-packages/django/views/decorators/debug.py", line 89, in sensitive_post_parameters_wrapper
django_1    |     return view(request, *args, **kwargs)
django_1    |   File "/usr/local/lib/python3.9/site-packages/allauth/account/views.py", line 230, in dispatch
django_1    |     return super(SignupView, self).dispatch(request, *args, **kwargs)
django_1    |   File "/usr/local/lib/python3.9/site-packages/allauth/account/views.py", line 74, in dispatch
django_1    |     response = super(RedirectAuthenticatedUserMixin, self).dispatch(
django_1    |   File "/usr/local/lib/python3.9/site-packages/allauth/account/views.py", line 204, in dispatch
django_1    |     return super(CloseableSignupMixin, self).dispatch(request, *args, **kwargs)
django_1    |   File "/usr/local/lib/python3.9/site-packages/django/views/generic/base.py", line 98, in dispatch
django_1    |     return handler(request, *args, **kwargs)
django_1    |   File "/usr/local/lib/python3.9/site-packages/allauth/account/views.py", line 102, in post
django_1    |     response = self.form_valid(form)
django_1    |   File "/usr/local/lib/python3.9/site-packages/allauth/account/views.py", line 248, in form_valid
django_1    |     return complete_signup(
django_1    |   File "/usr/local/lib/python3.9/site-packages/allauth/account/utils.py", line 209, in complete_signup
django_1    |     return perform_login(
django_1    |   File "/usr/local/lib/python3.9/site-packages/allauth/account/utils.py", line 175, in perform_login
django_1    |     send_email_confirmation(request, user, signup=signup, email=email)
django_1    |   File "/usr/local/lib/python3.9/site-packages/allauth/account/utils.py", line 346, in send_email_confirmation
django_1    |     email_address.send_confirmation(request, signup=signup)
django_1    |   File "/usr/local/lib/python3.9/site-packages/allauth/account/models.py", line 62, in send_confirmation
django_1    |     confirmation.send(request, signup=signup)
django_1    |   File "/usr/local/lib/python3.9/site-packages/allauth/account/models.py", line 169, in send
django_1    |     get_adapter(request).send_confirmation_mail(request, self, signup)
django_1    |   File "/usr/local/lib/python3.9/site-packages/allauth/account/adapter.py", line 464, in send_confirmation_mail
django_1    |     self.send_mail(email_template, emailconfirmation.email_address.email, ctx)
django_1    |   File "/usr/local/lib/python3.9/site-packages/allauth/account/adapter.py", line 136, in send_mail
django_1    |     msg.send()
django_1    |   File "/usr/local/lib/python3.9/site-packages/django/core/mail/message.py", line 284, in send
django_1    |     return self.get_connection(fail_silently).send_messages([self])
django_1    |   File "/usr/local/lib/python3.9/site-packages/anymail/backends/base.py", line 89, in send_messages
django_1    |     created_session = self.open()
django_1    |   File "/usr/local/lib/python3.9/site-packages/anymail/backends/amazon_ses.py", line 44, in open
django_1    |     self.client = boto3.session.Session(**self.session_params).client("ses", **self.client_params)
django_1    |   File "/usr/local/lib/python3.9/site-packages/boto3/session.py", line 258, in client
django_1    |     return self._session.create_client(
django_1    |   File "/usr/local/lib/python3.9/site-packages/botocore/session.py", line 847, in create_client
django_1    |     client = client_creator.create_client(
django_1    |   File "/usr/local/lib/python3.9/site-packages/botocore/client.py", line 86, in create_client
django_1    |     client_args = self._get_client_args(
django_1    |   File "/usr/local/lib/python3.9/site-packages/botocore/client.py", line 355, in _get_client_args
django_1    |     return args_creator.get_client_args(
django_1    |   File "/usr/local/lib/python3.9/site-packages/botocore/args.py", line 71, in get_client_args
django_1    |     final_args = self.compute_client_args(
django_1    |   File "/usr/local/lib/python3.9/site-packages/botocore/args.py", line 148, in compute_client_args
django_1    |     endpoint_config = self._compute_endpoint_config(
django_1    |   File "/usr/local/lib/python3.9/site-packages/botocore/args.py", line 220, in _compute_endpoint_config
django_1    |     return self._resolve_endpoint(**resolve_endpoint_kwargs)
django_1    |   File "/usr/local/lib/python3.9/site-packages/botocore/args.py", line 302, in _resolve_endpoint
django_1    |     return endpoint_bridge.resolve(
django_1    |   File "/usr/local/lib/python3.9/site-packages/botocore/client.py", line 430, in resolve
django_1    |     resolved = self.endpoint_resolver.construct_endpoint(
django_1    |   File "/usr/local/lib/python3.9/site-packages/botocore/regions.py", line 133, in construct_endpoint
django_1    |     result = self._endpoint_for_partition(
django_1    |   File "/usr/local/lib/python3.9/site-packages/botocore/regions.py", line 148, in _endpoint_for_partition
django_1    |     raise NoRegionError()
django_1    | botocore.exceptions.NoRegionError: You must specify a region.
django_1    |
django_1    | During handling of the above exception, another exception occurred:
django_1    |
django_1    | Traceback (most recent call last):
django_1    |   File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
django_1    |     response = get_response(request)
django_1    |   File "/usr/local/lib/python3.9/site-packages/django/utils/deprecation.py", line 114, in __call__
django_1    |     response = response or self.get_response(request)
django_1    |   File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 49, in inner
django_1    |     response = response_for_exception(request, exc)
django_1    |   File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 104, in response_for_exception
django_1    |     log_response(
django_1    |   File "/usr/local/lib/python3.9/site-packages/django/utils/log.py", line 224, in log_response
django_1    |     getattr(logger, level)(
django_1    |   File "/usr/local/lib/python3.9/logging/__init__.py", line 1475, in error
django_1    |     self._log(ERROR, msg, args, **kwargs)
django_1    |   File "/usr/local/lib/python3.9/logging/__init__.py", line 1589, in _log
django_1    |     self.handle(record)
django_1    |   File "/usr/local/lib/python3.9/logging/__init__.py", line 1599, in handle
django_1    |     self.callHandlers(record)
django_1    |   File "/usr/local/lib/python3.9/logging/__init__.py", line 1661, in callHandlers
django_1    |     hdlr.handle(record)
django_1    |   File "/usr/local/lib/python3.9/logging/__init__.py", line 952, in handle
django_1    |     self.emit(record)
django_1    |   File "/usr/local/lib/python3.9/site-packages/django/utils/log.py", line 122, in emit
django_1    |     self.send_mail(subject, message, fail_silently=True, html_message=html_message)
django_1    |   File "/usr/local/lib/python3.9/site-packages/django/utils/log.py", line 125, in send_mail
django_1    |     mail.mail_admins(subject, message, *args, connection=self.connection(), **kwargs)
django_1    |   File "/usr/local/lib/python3.9/site-packages/django/core/mail/__init__.py", line 104, in mail_admins
django_1    |     mail.send(fail_silently=fail_silently)
django_1    |   File "/usr/local/lib/python3.9/site-packages/django/core/mail/message.py", line 284, in send
django_1    |     return self.get_connection(fail_silently).send_messages([self])
django_1    |   File "/usr/local/lib/python3.9/site-packages/anymail/backends/base.py", line 94, in send_messages
django_1    |     sent = self._send(message)
django_1    |   File "/usr/local/lib/python3.9/site-packages/anymail/backends/base.py", line 124, in _send
django_1    |     response = self.post_to_esp(payload, message)
django_1    |   File "/usr/local/lib/python3.9/site-packages/anymail/backends/amazon_ses.py", line 67, in post_to_esp
django_1    |     response = payload.call_send_api(self.client)
django_1    |   File "/usr/local/lib/python3.9/site-packages/anymail/backends/amazon_ses.py", line 127, in call_send_api
django_1    |     return ses_client.send_raw_email(**self.params)
django_1    | AttributeError: 'NoneType' object has no attribute 'send_raw_email'

我会很感激任何意见。我没主意了。谢谢!

4

1 回答 1

0

您可能已经知道,问题在于 boto3 不知道您要在哪个 AWS 区域运行:

botocore.exceptions.NoRegionError: You must specify a region.

区域名称来自 boto3 配置。来自Anymail 的 SES 文档

您必须确保为 boto3 配置了具有必要 IAM 权限的 AWS 凭证。做这件事有很多种方法; 有关选项,请参阅Boto 文档中的凭据。通常,适用于 EC2 实例、标准 Boto 环境变量或共享 AWS 凭证文件的 IAM 角色将是合适的。对于更复杂的情况,使用 Anymail 的AMAZON_SES_CLIENT_PARAMS设置来自定义 Boto 会话。

似乎您可能会尝试混合使用一些“几种方式”来提供 boto3 凭据,这可能会导致混淆。

请注意,您的AWS_*Django 设置不起作用。boto3 不知道 Django 设置。Anymail 的 SES 设置文档描述了 Anymail 将传递给 boto3 的 Django 设置。(而且AWS_S3_REGION_NAME无论如何都不会相关,因为 S3 与 SES 的服务不同。我猜这些AWS_*Django 设置可能适用于其他一些应用程序,也许是 django-storages。)

如果您想在 settings.py 中专门为 Anymail 提供 AWS 凭证,您可以使用 Anymail 的AMAZON_SES_CLIENT_PARAMS设置来实现。例如:

# (Be sure to add DJANGO_AWS_REGION_NAME to your env to use this example)
ANYMAIL = {
    "AMAZON_SES_CLIENT_PARAMS": {
        "aws_access_key_id": env("DJANGO_AWS_ACCESS_KEY_ID"),
        "aws_secret_access_key": env("DJANGO_AWS_SECRET_ACCESS_KEY"),
        "region_name": env("DJANGO_AWS_REGION_NAME"),
    },
}
于 2021-08-13T17:54:57.537 回答