当前位置: 首页 > 知识库问答 >
问题:

为什么亚马逊SES接受我的get请求,但拒绝我类似结构的帖子请求?

范承望
2023-03-14

这是我目前用来通过亚马逊的简单电子邮件服务发送电子邮件的获取请求的代码

import datetime
import hashlib
import hmac
import urllib.parse
import requests


def sign(key, msg):
    return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()


def getSignatureKey(key, dateStamp, regionName, serviceName):
    kDate = sign(('AWS4' + key).encode('utf-8'), dateStamp)
    kRegion = sign(kDate, regionName)
    kService = sign(kRegion, serviceName)
    kSigning = sign(kService, 'aws4_request')
    return kSigning


method = 'GET'
service = 'ses'
host = 'email.us-east-1.amazonaws.com'
region = 'us-east-1'
endpoint = 'https://email.us-east-1.amazonaws.com/'
access_key = 'my_access_key'
secret_key = 'my_secret_key'
my_email = 'my_email_address'

t = datetime.datetime.utcnow()
amz_date = t.strftime('%Y%m%dT%H%M%SZ')
datestamp = t.strftime('%Y%m%d')
canonical_uri = '/'
canonical_headers = 'host:' + host + '\n'
signed_headers = 'host'
algorithm = 'AWS4-HMAC-SHA256'
credential_scope = datestamp + '/' + region + '/' + service + '/' + 'aws4_request'

canonical_querystring_part1 = 'Action=SendEmail' \
                              '&Destination.ToAddresses.member.1={}' \
                              '&Message.Body.Html.Charset=UTF-8' \
                              '&Message.Body.Html.Data={}' \
                              '&Message.Body.Text.Charset=UTF-8' \
                              '&Message.Body.Text.Data={}' \
                              '&Message.Subject.Charset=UTF-8' \
                              '&Message.Subject.Data={}' \
                              '&Source={}'.format(urllib.parse.quote(my_email, safe=''), 
                                                  urllib.parse.quote('<b>Html Hello.</b>', safe=''), 
                                                  urllib.parse.quote('Non Html hello.', safe=''),
                                                  urllib.parse.quote('Asyncio Subject line.', safe=''), 
                                                  urllib.parse.quote(my_email, safe=''))
canonical_querystring_part2 = '&X-Amz-Algorithm=AWS4-HMAC-SHA256'
canonical_querystring_part2 += '&X-Amz-Credential=' + urllib.parse.quote_plus(access_key + '/' + credential_scope)
canonical_querystring_part2 += '&X-Amz-Date=' + amz_date
canonical_querystring_part2 += '&X-Amz-Expires=30'
canonical_querystring_part2 += '&X-Amz-SignedHeaders=' + signed_headers
canonical_querystring = canonical_querystring_part1 + canonical_querystring_part2

payload_hash = hashlib.sha256(''.encode('utf-8')).hexdigest()
canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash
string_to_sign = algorithm + '\n' + amz_date + '\n' + credential_scope + '\n' + hashlib.sha256(canonical_request.encode('utf-8')).hexdigest()

signing_key = getSignatureKey(secret_key, datestamp, region, service)
signature = hmac.new(signing_key, string_to_sign.encode('utf-8'), hashlib.sha256).hexdigest()

canonical_querystring += '&X-Amz-Signature=' + signature
request_url = endpoint + "?" + canonical_querystring


r = requests.get(request_url)

它有点长,但运行良好。这是我试图做同样的事情,但是有一个帖子请求:

import datetime
import hashlib
import hmac
import requests


def sign(key, msg):
    return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()


def getSignatureKey(key, dateStamp, regionName, serviceName):
    kDate = sign(('AWS4' + key).encode('utf-8'), dateStamp)
    kRegion = sign(kDate, regionName)
    kService = sign(kRegion, serviceName)
    kSigning = sign(kService, 'aws4_request')
    return kSigning


method = 'POST'
service = 'ses'
host = 'email.us-east-1.amazonaws.com'
region = 'us-east-1'
endpoint = 'https://email.us-east-1.amazonaws.com/'
access_key = 'my_access_key'
secret_key = 'my_secret_key'
my_email = 'my_email_address'


content_type = 'application/x-www-form-urlencoded; charset=utf-8'


# Request parameters for CreateTable--passed in a JSON block.
request_parameters = '{'
request_parameters += "'body': {'Action': 'SendEmail', 'Destination.ToAddresses.member.1': '%s', 'Message.Body.Html.Charset': 'UTF-8', " \
                      "'Message.Body.Html.Data': 'HTMLMESSAGE', 'Message.Body.Text.Charset': 'UTF-8', 'Message.Body.Text.Data': 'nonHTMLmessage', 'Message.Subject.Charset': 'UTF-8', " \
                      "'Message.Subject.Data': 'subject','Source': '%s'}, " % (my_email, my_email)
request_parameters += "'Content-Type': '%s', " % content_type
request_parameters += "'context': {'client_region': 'us-east-1'}"
request_parameters += '}'


t = datetime.datetime.utcnow()
amz_date = t.strftime('%Y%m%dT%H%M%SZ')
date_stamp = t.strftime('%Y%m%d')


canonical_uri = '/'
canonical_querystring = ''
canonical_headers = 'content-type:' + content_type + '\n' + 'host:' + host + '\n' + 'x-amz-date:' + amz_date + '\n'
signed_headers = 'content-type;host;x-amz-date'

payload_hash = hashlib.sha256(request_parameters.encode('utf-8')).hexdigest()

canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash
algorithm = 'AWS4-HMAC-SHA256'
credential_scope = date_stamp + '/' + region + '/' + service + '/' + 'aws4_request'

string_to_sign = algorithm + '\n' + amz_date + '\n' + credential_scope + '\n' + hashlib.sha256(canonical_request.encode('utf-8')).hexdigest()
signing_key = getSignatureKey(secret_key, date_stamp, region, service)
signature = hmac.new(signing_key, string_to_sign.encode('utf-8'), hashlib.sha256).hexdigest()

authorization_header = algorithm + ' ' + 'Credential=' + access_key + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + signature
headers = {'Content-Type': content_type, 'X-Amz-Date': amz_date, 'Authorization': authorization_header}


r = requests.post(endpoint, params=request_parameters, headers=headers)

我将尽我所能遵循Amazon关于v4签名过程的文档:https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html

我还使用完整的获取和发布请求的例子,他们有SES在这里找到:https://docs.aws.amazon.com/ses/latest/DeveloperGuide/query-interface-examples.html

由于某种原因,它不起作用。我尝试将post请求中的kwarg从params改为json再改为data。

r = requests.post(endpoint, params=request_parameters, headers=headers)
<IncompleteSignatureException>
  <Message>When Content-Type:application/x-www-form-urlencoded, URL cannot include query-string parameters (after '?'): '/?%7B'body':%20%7B'Action':%20'SendEmail',%20'Destination.ToAddresses.member.1':%20'ArbiBushka717@gmail.com',%20'Message.Body.Html.Charset':%20'UTF-8',%20'Message.Body.Html.Data':%20'HTMLMESSAGE',%20'Message.Body.Text.Charset':%20'UTF-8',%20'Message.Body.Text.Data':%20'nonHTMLmessage',%20'Message.Subject.Charset':%20'UTF-8',%20'Message.Subject.Data':%20'subject','Source':%20'ArbiBushka717@gmail.com'%7D,%20'Content-Type':%20'application/x-www-form-urlencoded;%20charset=utf-8',%20'context':%20%7B'client_region':%20'us-east-1'%7D%7D'</Message>
</IncompleteSignatureException>

r = requests.post(endpoint, data=request_parameters, headers=headers)
<AccessDeniedException/>


r = requests.post(endpoint, json=request_parameters, headers=headers)
<InvalidSignatureException>
  <Message>The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.</Message>
</InvalidSignatureException>

每种形式的发布请求都会给出不同的错误。任何有组织发布请求(或对亚马逊应用编程接口的请求)经验的人都知道我做错了什么吗?

在任何人写“使用他们的Python SDK”之前我不能。他们的SDK是阻塞的,我必须异步地这样做。我计划从请求转移到aiohttp。我现在正试图在请求中得到这个,因为问这个问题更简单。

如果可以请帮忙,谢谢你的阅读。

共有1个答案

孔逸春
2023-03-14

等待nvm我得。要在请求中指定正文,请使用“数据”kwarg。

此外,我的变量request_参数的格式必须为param1=This

哇,真头疼。

 类似资料:
  • 我正在使用PARSE API发出GET请求。我收到一个“414请求URI太大”错误,但我不明白为什么。这是我请求的代码:

  • http://maps.googleapis.com/maps/api/directions/json?origin=Central香港 在没有mode=transit参数的情况下,请求可以正常工作,但结果只包括驾驶方向。添加最后一个参数后,我得到: "状况":"INVALID_REQUEST" 我能做些什么来使这个工作?有明确的交通选项,它们列在谷歌地图上。

  • 我试图通过我的vue应用程序向Firebase发出发布请求,我不断收到此错误图像 我正在运行一个webpack服务器,网站在localhost:8080上,但是我也有一个在hostinger上托管的live版本,这是http://arestate.online/网站,当我点击添加新博客,在填写详细信息并点击post后,它也抛出了CORS错误。 我添加并修改了一个. htAccess文件,以包含这个

  • 我正在尝试将图像上传到我的AWS存储桶,我创建了一个新用户授予他完整的控制权 但是,在上传时,我收到以下错误: 05-27 07:09:47.219: W/System.err(20594):com.amazonaws.services.s3.model.Amazon S3异常:访问被拒绝(服务:Amazon S3;状态代码:403;错误代码:访问被拒绝;请求ID:),S3扩展请求ID:/=

  • 当我试图用WebClient发送GET请求时,我响应错误io.netty.channel.AbstractChannel$annotatedConnectException:Connection Delection:localhost/ *WebClient初始化*

  • 我已经在我的服务器上配置了postfix,只发送@gmail。com邮件至亚马逊SES: 此外,我在AmazonSES控制台中配置了使用AmazonSNS接收邮件的反弹和投诉。问题是,如果我向一个不存在的gmail地址发送邮件,我不会收到回音。 如果从邮件发送邮件。谷歌。com到地址dsadaerwer。拉拉乐队很烂。贾斯汀是一个-beaver@gmail.com我收到: 但是如果从PHP脚本发送