This time, we will explore ** Direct Mail ** of ** Alibaba Cloud DevOps ** using ** REST API ** with ** Python **.
Alibaba Cloud Tech Share, author John Hanley. Tech Share encourages sharing of technical knowledge and best practices within the cloud community Alibaba Cloud Incentive program.
My favorite language for learning rapid prototyping and new cloud services is Python. With Python, most tasks are so simple that you can test your new API in minutes. This allows you to focus on learning without having to worry about the details of how the API works in a particular language. But I'm using C ++ for enterprise-level code that can cost millions of dollars if I make a mistake.
Alibaba's DirectMail does not support Python. PHP, Java and C # are supported. A very common use case for DirectMail is to email dynamic and static websites. Is to deliver. For dynamic websites, PHP is the best choice. For static websites, DirectMail and [Function Compute](https://www.alibabacloud.com/ Integrating product / function-compute? Spm = a2c65.11461447.0.0.38ad725bFhEjCQ) is perfect. However, Function Compute does not support PHP. This means developing in one language on the desktop and in another on the cloud.
So I came up with the idea of using DirectMail's REST API. That means you can use Python to learn how to use the REST API and especially how to create less documented signatures.
DirectMail supports three different interfaces (not all languages are supported).
1、Alibaba REST API 2、Alibaba Cloud SDK 3、Alibaba SMTP Interface In the previous article, I introduced an example of using SDK (Function Compute) in Python. This time, I will focus on the DirectMail REST API and show an example of how it works in Python.
There are several reasons to use the REST API.
REST API requirements
This is a link to Alibaba Documentation for DirectMail Public Parameters.
name | type | Is it mandatory | Explanation |
---|---|---|---|
Format | String | No | The type of response value. JSON and XML are supported. XML is the default format. This example uses JSON. |
Version | String | Yes | API version number. The format is YYYY-MM-It is DD. RegionID is cn-For hangzhou, the version number is 2015-11-twenty three. RegionID is cn-If it is not hangzhou, the version number is ap-southeast-2017 for 1 etc.-06-It's 22. In the example 2017-06-Use 22. |
AccessKeyId | String | Yes | AccessKeyId issued by Alibaba Cloud to users to access the service. |
SecurityToken | String | Depends | This parameter is not required if you are using the access key defined for the user. If you are using roles, context.A security token passed to the function as part of the credentials object. |
Signature | String | Yes | The character string of the signature result. For details on how to calculate the signature, see "Signature"Please refer to. |
SignatureMethod | String | Yes | Signing method. HMAC-SHA1 is currently supported. |
Timestamp | String | Yes | Request time stamp. The date format isISO8601ItconformstothestandardandadoptsUTCtime.Theformatisasfollows.YYYY-MM-DDThh:mm:ssZ.Example:2015-11-23T04:00:00Z(BeijingTimeNovember23,201512:00:For00). |
SignatureVersion | String | Yes | The version of the signature algorithm. Current version is 1.It is 0. |
SignatureNonce | String | Yes | Unique random number. Used to prevent replay attacks. You must use a different random number for each request. |
RegionId | String | Yes | Data center information. cn-hangzhou、ap-southeast-1、ap-southeast-2 is currently supported. |
Comments on the above parameters:
** SignatureNonce **: This parameter has been annoying for some time. At first I thought this was the salt value used when signing HMAC_SHA1. However, it turns out that this is a string generated by uuid.uuid4 () and contained in the header. Repeating the value of this string in a subsequent command will reject the command.
** AccessKeyId **: Creates a new RAM user with DirectMail-only permissions. In this case, you will need both an Access Key and an Access Key Secret for the REST API.
** Timestamp **: It is important that the system date and time are correct. If this time is different from Alibaba's service, the request will be rejected. If possible, use a time service such as NTP for your system.
This is a link to Alibaba documentation on DirectMail Request parameters.
name | type | Is it mandatory | Explanation |
---|---|---|---|
Action | String | Required | Operation interface name and system required parameters. Specify the value. Single Send Mail. |
AccountName | String | Required | The sender address configured in the console. |
ReplyToAddress | Boolean | Required | The reply address configured in the console (status must be "verified"). |
AddressType | Number | Required | Range of values: 0-1. 0 indicates a random account and 1 indicates the sender address. |
ToAddress | String | Required | Recipient's address. Multiple addresses can be separated by commas and support up to 100 addresses. |
FromAlias | String | option | Sender's nickname. Nicknames must be 15 characters or less in length. For example, the sender's nickname is set to Daisy and the sender's address is [email protected] is com. The recipient is Daisy[email protected]Refer to the address of. |
Subject | String | Optional | Subject (Recommendation)。 |
HtmlBody | String | Optional | Display the email body in HTML. |
TextBody | String | Optional | Display the body of the email as text. |
ClickTrace | String | Optional | Range of values. 0-1. 1 indicates that recipient tracking is enabled. 0 indicates that recipient tracking is not enabled. The default value for this parameter is 0. |
# Correctly formatted date and time
now = datetime.datetime.utcnow()
# Date used by the HTTP "Date" header
date = now.strftime("%a, %d %b %Y %H:%M:%S GMT")
# Date used by the API parameter "Timestamp"
utc = now.isoformat(timespec='seconds') + 'Z'
# HTTP Host header
host = "dm.ap-southeast-1.aliyuncs.com"
# URL for POST
url = "https://dm.ap-southeast-1.aliyuncs.com/"
parameters = {}
# Add the DirectMail public request parameters
parameters["Format"] = "json"
parameters["AccessKeyId"] = credentials['AccessKey']
parameters["SignatureMethod"] = "HMAC-SHA1"
parameters["SignatureType"] = ""
parameters["SignatureVersion"] = "1.0"
parameters["SignatureNonce"] = get_uuid()
parameters["Timestamp"] = utc
parameters["Version"] = "2017-06-22"
parameters["RegionId"] = "ap-southeast-1"
# Add parameters that are always set
parameters["Action"] = "SingleSendMail"
parameters["AddressType"] = "1"
parameters["ReplyToAddress"] = "true"
# Add the DirectMail API parameters
parameters["AccountName"] = dm_account
parameters["FromAlias"] = dm_alias
parameters["ToAddress"] = to_list
parameters["Subject"] = subject
parameters["HtmlBody"] = body
parameters["textBody"] = body_text
def build_request_string(table):
""" Build canonical list """
items = sorted(iter(table.items()), key=lambda d: d[0])
enc = my_urlencode(items)
return enc
Precautions regarding request string
Request string parameters must be sorted first. The string is then url-encoded. This means that each key / value pair will have an & character.
The final result looks like the example below, but with a longer length.
AccessKeyId=LTAIQlgy6erobert&AccountName=test%40test.com&Action=SingleSendMail …
This is a link to Alibaba Documentation on DirectMail Signature.
# Build the request string for the signing process
params = build_request_string(parameters)
# Create the actual string to sign (method = "POST")
stringToSign = method + "&%2F&" + percentEncode(params)
Signature = sign(stringToSign, credentials['AccessKeySecret'])
Download sendEmail.zip.
############################################################
# Version 1.00
# Date Created: 2018-05-26
# Last Update: 2018-05-27
# https://www.neoprime.io
# Copyright (c) 2018, NeoPrime, LLC
############################################################
""" Alibaba Cloud DirectMail REST API With Signing """
import base64
import datetime
import hmac
import hashlib
import urllib
import uuid
import json
import requests
# My library for processing Alibaba Cloud Services (ACS) credentials
import mycred_acs
# From the DirectMail Console
dm_account = "<enter your value here>"
dm_alias = "<enter your value here>"
debug = 0
def set_connection_logging():
""" Enable HTTP connection logging """
if debug is 0:
return
import logging
import http.client as http_client
http_client.HTTPConnection.debuglevel = 1
# You must initialize logging, otherwise you'll not see debug output.
logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True
return
def get_uuid():
""" return a uuid as a signing nonce """
return str(uuid.uuid4())
def percentEncode(path):
""" Encode a URL """
res = urllib.parse.quote(path)
res = res.replace('+', '%20')
res = res.replace('*', '%2A')
res = res.replace('%7E', '~')
return res
def my_urlencode(query):
""" Encode a Query """
res = urllib.parse.urlencode(query)
res = res.replace('+', '%20')
res = res.replace('*', '%2A')
res = res.replace('%7E', '~')
return res
def build_request_string(table):
""" Build canonical list """
items = sorted(iter(table.items()), key=lambda d: d[0])
enc = my_urlencode(items)
return enc
def sign(string, secret):
""" Sign REST API Request """
nsecret = secret + '&'
h = hmac.new(
bytes(nsecret, "utf-8"),
bytes(string, "utf-8"),
hashlib.sha1)
#sig = base64.b64encode(h.digest())
sig = str(base64.encodebytes(h.digest()).strip(), "utf-8")
return sig
def sendEmail(credentials, subject, body, body_text, to_list):
""" Send an email using Alibaba DirectMail """
# HTTP Method
method = "POST"
# Correctly formatted date and time
now = datetime.datetime.utcnow()
date = now.strftime("%a, %d %b %Y %H:%M:%S GMT")
utc = now.isoformat(timespec='seconds') + 'Z'
# HTTP Host header
host = "dm.ap-southeast-1.aliyuncs.com"
# URL for POST
url = "https://dm.ap-southeast-1.aliyuncs.com/"
parameters = {}
# Add the DirectMail public request parameters
parameters["Format"] = "json"
parameters["AccessKeyId"] = credentials['AccessKey']
parameters["SignatureMethod"] = "HMAC-SHA1"
parameters["SignatureType"] = ""
parameters["SignatureVersion"] = "1.0"
parameters["SignatureNonce"] = get_uuid()
parameters["Timestamp"] = utc
#parameters["Version"] = "2015-11-23"
parameters["Version"] = "2017-06-22"
parameters["RegionId"] = "ap-southeast-1"
# Add parameters that are always set
parameters["Action"] = "SingleSendMail"
parameters["AddressType"] = "1"
parameters["ReplyToAddress"] = "true"
# Add the DirectMail API parameters
parameters["AccountName"] = dm_account
parameters["FromAlias"] = dm_alias
parameters["ToAddress"] = to_list
parameters["Subject"] = subject
parameters["HtmlBody"] = body
parameters["textBody"] = body_text
# Build the request string for the signing process
params = build_request_string(parameters)
# Create the actual string to sign
stringToSign = method + "&%2F&" + percentEncode(params)
#print("String to Sign")
#print(stringToSign)
Signature = sign(stringToSign, credentials['AccessKeySecret'])
#print("Signature", Signature)
parameters["Signature"] = Signature
headers = {
'Date': date,
'Host': host
}
set_connection_logging()
print("Sending Email to", parameters["ToAddress"])
r = requests.post(url, data=parameters, headers=headers)
if r.status_code != 200:
print("Error: Email Send Failed:", r.status_code)
print(r.text)
return 1
#print(r.text)
result = json.loads(r.text)
print("Success: Request ID:", result['RequestId'])
return 0
# Load the Alibaba Cloud Credentials (AccessKey)
cred = mycred_acs.LoadCredentials()
dm_subject = "Welcome to Alibaba Cloud DirectMail"
dm_body = "<h2>Welcome to Alibaba Cloud DirectMail<h2>You are receiving this email as part of a test program.<br /><br />Click for <a href='https://www.neoprime.io/info/alibaba/'>more information<a>.<br /><br /><a href='https://www.alibabacloud.com/'><img src='https://www.neoprime.io/info/alibaba/img/alibaba-600x263.png' alt='Alibaba' width='700'><a>"
dm_body_text = "Welcome to Alibaba Cloud DirectMail\nYou are receiving this email as part of a test program."
dm_to_list = "[email protected], [email protected]
sendEmail(cred, dm_subject, dm_body, dm_body_text, dm_to_list)
Run on Python 3.x: python sendEmail.py
Alibaba DirectMail Product Page Alibaba DirectMail Documentation Alibaba DirectMail Public parameters Alibaba DirectMail Request parameters Alibaba DirectMail Signature
Recommended Posts