amazon-web-services - Boto3 SES 抛出 TypeError: sequence item 0: expected str instance, tuple found
问题描述
我正在尝试将亚马逊简单电子邮件服务集成到我的应用程序中。我的应用程序是一个 python3 烧瓶应用程序。
我正在使用boto3。我目前在尝试发送原始电子邮件时遇到错误。
我创建了一个单独的路由,我在其中调用此类并获取发送“SendEmail”方法。
我有一个示例数据 json,必须在评论中的 SendEmail 中传递
我也提供了下面的错误日志
class SES():
def __init__(self, **kwargs):
"""Create template emails that can be used in the code.
The template emails will be stored in the brokerportal
will then get used by the aws ses boto3 client
When sending template emails:
1. Check if the template is part of the listed templates
2. Call the necessary template to build the message
3. Send it to the parties using send email """
self.region = 'ap-south-1'
self.aws_access_key_id = current_app.config['ses_access_key_id'],
self.aws_secret_access_key = current_app.config['ses_secret_access_key']
self.ses = boto3.client('ses', region_name = self.region,
aws_access_key_id = self.aws_access_key_id,
aws_secret_access_key = self.aws_secret_access_key)
def SendEmail(self, data, **kwargs):
"""takes the data and transforms the data into the appropriate frmat
before sending the email
data should have the following:
data = {
'toList':['s@domain.com'],
'ccList':['b@domain.com'],
'bccList':['p@domain.com'],
'TemplateData':{vars},
'Attachment':True,
'fileKey':'<S3path>',
'bucketName': <Amazon s3 bucket name>
'Subject': 'This is a subject',
'TemplateName':'TemplateName'
}"""
CHARSET = "utf-8"
Destination = {
'ToAddresses':data['toList'],
'CcAddresses':data['ccList'],
'BccAddresses':data['bccList']
}
# ReplyToAddresses = [current_app.config['MAIL_USERNAME']],
ReplyToAddresses = ["a@domain.com"],
msg = MIMEMultipart('mixed')
msg['Subject'] = data['Subject']
msg['From'] = "a@domain.com"
if Destination['ToAddresses']:
msg['To'] = ', '.join(str(v) for v in Destination['ToAddresses'])
if Destination['CcAddresses']:
msg['Cc'] = ', '.join(str(v) for v in Destination['CcAddresses'])
if Destination['BccAddresses']:
msg['Bcc'] = ', '.join(str(v) for v in Destination['BccAddresses'])
msg_body = MIMEMultipart('alternative')
#Obtain the template details
# v = current_app.config['db'].view('_design/Email/_view/templates')
v = current_app.config['db'].view('_design/Email/_view/templates')
for row in v[data['TemplateName']]:
Tmplte = Jinja2Template(row.value['HtmlPart'])
HtmlPart = Tmplte.render(data = data['TemplateData'])
htmlpart = MIMEText(HtmlPart)
msg_body.attach(htmlpart)
msg.attach(msg_body)
#Attachment
if data['Attachment']:
filehelper = FileHelper(bucketName=data['bucketName'])
att = MIMEApplication(filehelper.load(data['fileKey']))
att.add_header('Content-Disposition','attachment',filename=fileKey)
msg.attach(att)
else:
pass
try:
current_app.logger.debug(msg)
print(msg)
response = self.ses.send_raw_email(
RawMessage = {
'Data': msg.as_string()
})
return msg
except ClientError as e:
current_app.logger.debug(e.response['Error']['Message'])
return ""
错误:
File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1997, in __call__
return self.wsgi_app(environ, start_response) File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1985, in wsgi_app
response = self.handle_exception(e) File "/usr/local/lib/python3.6/dist-packages/flask_cors/extension.py", line 161, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs))) File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1540, in handle_exception
reraise(exc_type, exc_value, tb) File "/usr/local/lib/python3.6/dist-packages/flask/_compat.py", line 33, in reraise
raise value File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request() File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e) File "/usr/local/lib/python3.6/dist-packages/flask_cors/extension.py", line 161, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs))) File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb) File "/usr/local/lib/python3.6/dist-packages/flask/_compat.py", line 33, in reraise
raise value File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request() File "/usr/local/lib/python3.6/dist-packages/flask/app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args) File "/home/sunil/perilwise/brokerportalbe/main.py", line 522, in sesmailcheck
response = ses.SendEmail(data = data) File "/home/sunil/perilwise/brokerportalbe/repository/sesRepository.py", line 117, in SendEmail
'Data': msg.as_string() File "/usr/local/lib/python3.6/dist-packages/botocore/client.py", line 312, in _api_call
return self._make_api_call(operation_name, kwargs) File "/usr/local/lib/python3.6/dist-packages/botocore/client.py", line 592, in _make_api_call
operation_model, request_dict) File "/usr/local/lib/python3.6/dist-packages/botocore/endpoint.py", line 141, in make_request
return self._send_request(request_dict, operation_model) File "/usr/local/lib/python3.6/dist-packages/botocore/endpoint.py", line 166, in _send_request
request = self.create_request(request_dict, operation_model) File "/usr/local/lib/python3.6/dist-packages/botocore/endpoint.py", line 150, in create_request
operation_name=operation_model.name) File "/usr/local/lib/python3.6/dist-packages/botocore/hooks.py", line 227, in emit
return self._emit(event_name, kwargs) File "/usr/local/lib/python3.6/dist-packages/botocore/hooks.py", line 210, in _emit
response = handler(**kwargs) File "/usr/local/lib/python3.6/dist-packages/botocore/signers.py", line 90, in handler
return self.sign(operation_name, request) File "/usr/local/lib/python3.6/dist-packages/botocore/signers.py", line 154, in sign
auth.add_auth(request) File "/usr/local/lib/python3.6/dist-packages/botocore/auth.py", line 366, in add_auth
self._inject_signature_to_request(request, signature) File "/usr/local/lib/python3.6/dist-packages/botocore/auth.py", line 369, in _inject_signature_to_request
l = ['AWS4-HMAC-SHA256 Credential=%s' % self.scope(request)] File "/usr/local/lib/python3.6/dist-packages/botocore/auth.py", line 319, in scope
return '/'.join(scope) TypeError: sequence item 0: expected str instance, tuple found
解决方案
我通过使 SES() 像一个可以从 main.py 调用的模块来解决这个问题(我给出了下面的代码):
class SES(object):
def __init__(self, app = None):
"""Create template emails that can be used in the code.
The template emails will be stored in the brokerportal
will then get used by the aws ses boto3 client
When sending template emails:
1. Check if the template is part of the listed templates
2. Call the necessary template to build the message
3. Send it to the parties using send email """
if app is not None:
self.init_app(app)
def init_app(self, app):
self.region = app.config.get('ap-south-1')
self.aws_access_key_id = app.config.get('ses_access_key_id')
self.aws_secret_access_key = app.config.get('ses_secret_access_key')
self.ses = self._connect()
def _connect():
clt = boto3.client('ses', region_name = self.region,
aws_access_key_id = self.aws_access_key_id,
aws_secret_access_key = self.aws_secret_access_key)
return clt
def SendEmail(self, data, **kwargs):
"""takes the data and transforms the data into the appropriate frmat
before sending the email
data should have the following:
data = {
'toList':['s@domain.com'],
'ccList':['b@domain.com'],
'bccList':['p@domain.com'],
'TemplateData':{vars},
'Attachment':True,
'fileKey':'<S3path>',
'bucketName': <Amazon s3 bucket name>
'Subject': 'This is a subject',
'TemplateName':'TemplateName'
}"""
CHARSET = "utf-8"
Destination = {
'ToAddresses':data['toList'],
'CcAddresses':data['ccList'],
'BccAddresses':data['bccList']
}
# ReplyToAddresses = [current_app.config['MAIL_USERNAME']],
ReplyToAddresses = ["a@domain.com"],
msg = MIMEMultipart('mixed')
msg['Subject'] = data['Subject']
msg['From'] = "a@domain.com"
if Destination['ToAddresses']:
msg['To'] = ', '.join(str(v) for v in Destination['ToAddresses'])
if Destination['CcAddresses']:
msg['Cc'] = ', '.join(str(v) for v in Destination['CcAddresses'])
if Destination['BccAddresses']:
msg['Bcc'] = ', '.join(str(v) for v in Destination['BccAddresses'])
msg_body = MIMEMultipart('alternative')
#Obtain the template details
# v = current_app.config['db'].view('_design/Email/_view/templates')
v = current_app.config['db'].view('_design/Email/_view/templates')
for row in v[data['TemplateName']]:
Tmplte = Jinja2Template(row.value['HtmlPart'])
HtmlPart = Tmplte.render(data = data['TemplateData'])
htmlpart = MIMEText(HtmlPart)
msg_body.attach(htmlpart)
msg.attach(msg_body)
#Attachment
if data['Attachment']:
filehelper = FileHelper(bucketName=data['bucketName'])
att = MIMEApplication(filehelper.load(data['fileKey']))
att.add_header('Content-Disposition','attachment',filename=fileKey)
msg.attach(att)
else:
pass
try:
current_app.logger.debug(msg)
print(msg)
response = self.ses.send_raw_email(
RawMessage = {
'Data': msg.as_string()
})
return msg
except ClientError as e:
current_app.logger.debug(e.response['Error']['Message'])
return ""
然后我在 main.py 路由中调用 ses = SES(app) 并像函数一样调用 ses
这解决了我的问题
推荐阅读
- android - Android Room FOREIGN KEY 约束失败(代码 787)
- data-structures - 我们是否需要在不相交的集合数据结构中同时进行路径压缩和按等级联合?
- asp.net-web-api - 使用 AAD 的安全 Web api - 此请求的授权已被拒绝
- google-apps-script - Google Apps 脚本:Google 表格分组
- python - 如何围绕可以通过 pip 安装的 C 库创建 Python 包包装器?
- prestashop - 在 prestashop 上手动创建新用户帐户
- linux - 在 linux 的 windows 子系统上安装 g++
- asp.net-mvc - MVC中的多个HTML元素相同的ID
- python - 将包含列表的列拆分为熊猫中的不同行
- javascript - 在 JavaScript 中使用 reduce 添加集合对象的属性值