# -*- coding: utf-8 -*-
import hmac
import uuid
import base64
import datetime
import requests
import os
from hashlib import sha1
from urllib.parse import urlencode
from urllib.parse import quote
def getSignature(param, method):
utf8 = getUtf8Encoder(param)
toSign = method + "&" + quote('/', 'utf-8') + "&" + utf8
message = toSign.encode(encoding='UTF-8', errors='strict')
print("message:", message)
key = (AccessKeySecret + "&").encode(encoding='UTF-8', errors='strict')
bytes = hmac.new(key, message, sha1)
Signature = str(base64.b64encode(bytes.digest()), encoding="utf-8") # Base64-encode the signature and convert the byte type to a string.
print('Signature after Base64 encoding:' + Signature)
return Signature
def getUtf8Encoder(param):
# UTF-8 encoding.
# Replace + with %20, * with %2A, and %7E with ~ in the encoded string.
return quote(param.replace('+', '%20').replace('*', '%2A'), encoding="utf-8")
if __name__ == '__main__':
# https://dm.aliyuncs.com/?Action=SingleSendMail
# & AccountName = test @ example.com
# & AddressType = 1
# & ReceiversName = test2
# & TemplateName = test1
# & Add more parameters as needed.
# & < Common request parameters >
protocol = "https"
method = "POST"
host = "dm.aliyuncs.com"
AccessKeySecret = os.environ['ALIBABA_CLOUD_ACCESS_KEY_SECRET'] # The AccessKey secret issued by Alibaba Cloud. Replace this with your own AccessKey secret. We recommend that you retrieve it from an environment variable. For more information, see Configure AccessKey pairs in environment variables.
time1 = datetime.datetime.now()
time2 = time1 + datetime.timedelta(hours=-8)
print('Current system time: ', time1.strftime("%Y-%m-%d %H:%M:%S"), ' -8 hours, converted to UTC: ', time2.strftime("%Y-%m-%dT%H:%M:%SZ"))
params_dict = {}
# Assign values to parameters.
params_dict["AccessKeyId"] = os.environ['ALIBABA_CLOUD_ACCESS_KEY_ID'] # The AccessKey ID issued by Alibaba Cloud. Replace this with your own AccessKey ID. # Required parameter
params_dict["AccountName"] = 'test***@example.net' # The sender address configured in the console.
params_dict["Action"] = 'SingleSendMail' # A required parameter, such as SingleSendMail or BatchSendMail.
params_dict["AddressType"] = 1 # 0: random account. 1: sender address.
params_dict["Format"] = 'JSON' # The format of the return value. Valid values: JSON and XML. Default value: XML. # Required parameter
params_dict["HtmlBody"] = 'Chinese body' # The HTML body of the email.
params_dict["RegionId"] = 'cn-hangzhou' # The data center information. For other regions, see the API endpoints document.
params_dict["ReplyToAddress"] = 'true' # true: Use the reply-to address set in the console.
params_dict["SignatureMethod"] = 'HMAC-SHA1' # The signature algorithm. Only HMAC-SHA1 is supported. # Required parameter
params_dict["SignatureNonce"] = str(uuid.uuid4()) # A required parameter. A unique random number to prevent replay attacks. Use a different random number for each request. You can use a UUID or a custom string.
params_dict["SignatureVersion"] = 1.0 # A required parameter. The version of the signature algorithm. The current version is 1.0.
params_dict["Subject"] = 'Custom subject' # The email subject.
params_dict["TagName"] = 'Custom tag' # The email tag.
params_dict['Template'] = '{"TemplateData":{"username":"222"},"TemplateId":"411558"}'
params_dict["Timestamp"] = time2.strftime(
"%Y-%m-%dT%H:%M:%SZ") # A required parameter. The request timestamp. The time must be in UTC and follow the ISO 8601 standard. Format: YYYY-MM-DDThh:mm:ssZ. For example, 2015-11-23T04:00:00Z is 12:00:00 on November 23, 2015 (UTC+8).
params_dict["ToAddress"] = 'test1***@example.net' # The recipient address.
params_dict["Version"] = '2015-11-23' # Required parameter
# Version:
# The API version number in the YYYY-MM-DD format. The recommended version is 2015-11-23.
print('Initial parameters:', params_dict)
# Example of encoding the HtmlBody value:
# Initial parameter: params_dict["HtmlBody"] = 'Chinese body'
# message in the getSignature function: %25E4%25B8%25AD%25E6%2596%2587body, double URL encoded
# In the final generated URL: %E4%B8%AD%E6%96%87body
# URL-encode the initial parameter dictionary: dict-->str
# The order of parameters for signing cannot be changed.
# The code sorts the dictionary to ensure the correct parameter order for signing.
params_dict_sorted = {}
for i in sorted(params_dict):
params_dict_sorted[i] = params_dict[i]
print(params_dict_sorted)
url_dict_to_str = urlencode(params_dict_sorted)
print('After the first URL encoding:' + url_dict_to_str)# Example: %E4%B8%AD%E6%96%87body
print('Generating signature...')
params_dict["Signature"] = getSignature(url_dict_to_str, method)
print('Signature generated.')
param = urlencode(params_dict)
print('After adding Signature to the request parameters and URL-encoding again:' + param)# Example: %E4%B8%AD%E6%96%87body
# Generate the URL.
final_url = protocol + "://" + host
print('Example of the final generated URL:', protocol + "://" + host + "/?" + param)
# POST request URL
response = requests.post(final_url, data=params_dict)
# Return information. RequestId is the unique identifier generated by Alibaba Cloud for the request. Example: {"RequestId":"D0291CF2-BFDA-46F1-9DFD-6B32B5675B38","EnvId":"120414808748"}
print('Returned parameters:' + response.text)
# Print URL parameters.
# listurl = final_url.split("&")
# for i in listurl:
# print(i)For more information about how to configure an AccessKey pair in an environment variable, see Configure AccessKey pairs in environment variables.
For a list of endpoints in other regions, see API endpoints.
Example of the final request URL for the China (Hangzhou) region
https://dm.aliyuncs.com/?AccessKeyId=xxxxxxxx&AccountName=test%40t1.example.com&Action=SingleSendMail&AddressType=1&Format=JSON&HtmlBody=%E4%B8%AD%E6%96%87body&RegionId=cn-hangzhou&ReplyToAddress=true&SignatureMethod=HMAC-SHA1&SignatureNonce=a883f1bf-e415-4a4d-91ba-085ad3bc7741&SignatureVersion=1.0&Subject=%E8%87%AA%E5%AE%9A%E4%B9%89%E4%B8%BB%E9%A2%98&TagName=%E8%87%AA%E5%AE%9A%E4%B9%89%E6%A0%87%E7%AD%BE&Template=%7B%22TemplateData%22%3A%7B%22username%22%3A%22222%22%7D%2C%22TemplateId%22%3A%22411558%22%7D&Timestamp=2025-12-31T06%3A01%3A51Z&ToAddress=test%40example.com&Version=2015-11-23&Signature=%2Fapm1xqY3Ob9k9IgFbgZcrbeYrg%3D