如何让Python2生成与Python3一致的AWS SES SMTP凭证?
兼容Python2和Python3的AWS SES SMTP凭证生成脚本
以下是修改后的脚本,可同时在Python2和Python3环境中生成一致且有效的AWS SES SMTP凭证:
#!/usr/bin/env python # 兼容Python2和Python3 import hmac import hashlib import base64 import sys import boto3 import json from botocore.exceptions import ClientError def get_secretmanager(): secret_name = "test" region_name = "us-west-2" session = boto3.session.Session() client = session.client( service_name='secretsmanager', region_name=region_name ) try: get_secret_value_response = client.get_secret_value( SecretId=secret_name ) except ClientError as e: raise e # 解密并解析密钥 secret = get_secret_value_response['SecretString'] response = json.loads(secret) # 兼容Python2的unicode转str access_key = str(response['Access Key Id']) if sys.version_info[0] == 2 else response['Access Key Id'] secret_key = str(response['Secret Access Key']) if sys.version_info[0] == 2 else response['Secret Access Key'] return access_key, secret_key SMTP_REGIONS = [ 'us-east-2', # US East (Ohio) 'us-east-1', # US East (N. Virginia) 'us-west-2', # US West (Oregon) 'ap-south-1', # Asia Pacific (Mumbai) 'ap-northeast-2', # Asia Pacific (Seoul) 'ap-southeast-1', # Asia Pacific (Singapore) 'ap-southeast-2', # Asia Pacific (Sydney) 'ap-northeast-1', # Asia Pacific (Tokyo) 'ca-central-1', # Canada (Central) 'eu-central-1', # Europe (Frankfurt) 'eu-west-1', # Europe (Ireland) 'eu-west-2', # Europe (London) 'sa-east-1', # South America (Sao Paulo) 'us-gov-west-1', # AWS GovCloud (US) ] # 签名计算固定参数,请勿修改 DATE = "11111111" SERVICE = "ses" MESSAGE = "SendRawEmail" TERMINAL = "aws4_request" VERSION = 0x04 def sign(key, msg): # 处理Python2/3的字符串/字节差异 if sys.version_info[0] == 2: return hmac.new(key, msg, hashlib.sha256).digest() else: return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest() def calculate_key(secret_access_key, region): if region not in SMTP_REGIONS: raise ValueError("The " + region+ " Region doesn't have an SMTP endpoint.") # 初始密钥编码兼容 initial_key = "AWS4" + secret_access_key if sys.version_info[0] == 2 else ("AWS4" + secret_access_key).encode('utf-8') signature = sign(initial_key, DATE) signature = sign(signature, region) signature = sign(signature, SERVICE) signature = sign(signature, TERMINAL) signature = sign(signature, MESSAGE) # 版本字节生成兼容 if sys.version_info[0] == 2: version_byte = chr(VERSION) signature_and_version = version_byte + signature else: signature_and_version = bytes([VERSION]) + signature smtp_password = base64.b64encode(signature_and_version) # Base64结果解码兼容 return smtp_password if sys.version_info[0] == 2 else smtp_password.decode('utf-8') def get_keys(): accesskey, secretkey = get_secretmanager() mailsecret = calculate_key(secretkey, "us-west-2") return accesskey, mailsecret print(get_keys())
关键修改说明:
字符串与字节编码适配:
- Python2中
str与字节无区分,直接传入hmac.new;Python3中需将字符串转为UTF-8字节。 - 初始密钥
AWS4 + secret_access_key在两个版本中分别以字符串和字节形式传入签名函数。
- Python2中
版本字节生成:
- Python2使用
chr(VERSION)生成单字节字符,Python3使用bytes([VERSION])生成字节对象,确保签名前的版本标识一致。
- Python2使用
Base64结果处理:
- Python2中
base64.b64encode直接返回字符串,Python3中返回字节对象,需解码为字符串后返回。
- Python2中
Secrets Manager返回值处理:
- Python2中
json.loads返回unicode类型,转换为str避免后续编码冲突。
- Python2中
内容的提问来源于stack exchange,提问作者Tony Frank
相关产品推荐
相关产品推荐

