×
Community Blog How to Apply API Gateway for DirectMail in Python

How to Apply API Gateway for DirectMail in Python

In this article, you will get some information on Alibaba Cloud DirectMail for DevOps using REST API in Python.

My favorite language for rapid prototyping and learning a new cloud service is Python. Python makes most tasks so simple that I can test a new API in minutes. This allows me to focus on learning and not on the details of how an API works in a particular language. However, for enterprise level code where a mistake could cost millions of dollars, I use C++.

The Alibaba SDK for DirectMail does not support Python. It does support PHP, Java and C#. A very common use case for DirectMail is delivering emails for dynamic and static websites. For dynamic websites PHP is perfect. For static websites, integrating Function Compute with DirectMail is perfect. However, Function Compute does not support PHP. This means that you develop in one language on your desktop and another in the cloud.

This led me to the idea of using the DirectMail REST API. This means that I can use Python and learn how to use the REST API and in particular how to create the Signature that is not documented very well. Nothing like picking a difficult challenge to really learn a new service.

In this article I will focus on the DirectMail REST API and include a real working example in Python.

Calculating the correct dates

# 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'

Complete Program to Call DirectMail REST API and Send an Email

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 = "test@test.com, test2@test.com

sendEmail(cred, dm_subject, dm_body, dm_body_text, dm_to_list)

Execute with Python 3.x: python sendEmail.py

For details, please go to Cloud DevOps Cookbook Part 4 – API Gateway and DirectMail with Python 3.0.

Related Blog Posts

Alibaba Cloud DevOps Cookbook Part 1 – CLI, SDK, SSH, SFTP

Now that I have a test website that is load balanced and has auto scaling, I would like to learn more about the Alibaba Cloud CLI and Python SDK. During development I often need to make changes to files that I publish on my ECS instances. Since the auto scaling group is built from an image, changing the image takes effort and time. During testing, I want to do rapid-fire edit / deploy / debug / improve. This means that I need a quick way to upload files to my ECS instances all at once.

Alibaba Cloud DevOps Cookbook Part 3 – Function Compute with Python 3.0

In today's article we will be exploring Alibaba Cloud Function Compute for DevOps with some example programs using Python 3. Our ultimate goal is to combine API Gateway, Function Compute, and Direct Mail to provide a contact form suitable for a static website hosted on OSS.

Related Market Product

Spark Mllib Hadoop Core powered by Miri Infotech

Spark is a general-purpose and quick cluster computing system that provides high-level APIs in Scala, Java, Python, and R, and an optimized engine, which supports general execution graphs.

Related Documentation

SMTP - Python

This page shows how to send an email through SMTP using Python.

Set HTTPS requests

Alibaba Cloud Python SDK supports using HTTP and HTTPS protocols to send API requests. Most Alibaba Cloud products use the HTTP protocol, whereas Resource Access Manager (RAM), Security Token Service (STS), and Key Management Service (KMS) use the HTTPS protocol.

Related Products

Direct Mail

DirectMail is a simple and efficient service to send email notifications and batch email quickly and efficiently without the need to build your own email server. DirectMail is a key product for serving Alibaba's own e-commerce platforms, which includes servicing Alibaba's record-breaking annual sales festival. Tens of millions of emails are sent every day through DirectMail by Alibaba and Alibaba Cloud customers.

Elastic Compute Service

Alibaba Cloud Elastic Compute Service (ECS) provides fast memory and the latest Intel CPUs to help you to power your cloud applications and achieve faster results with low latency. All ECS instances come with Anti-DDoS protection to safeguard your data and applications from DDoS and Trojan attacks.

Related Course

A Quick Guide to Process Structured Data with Python

The data set of this course is from virtual blog site, we are going to use the data to solve business problems,for example what countries do your customers come from;Which day of the week gets the most online traffic; Which region contributes the most clickstream data etc. Basic functions for data cleaning, data analysis and visualization will be coverd in this course. It is also the foundation for programming on distributed system like Spark SQL,or with Alibaba cloud MaxCompute Python SDK.

0 0 0
Share on

Alibaba Clouder

1,233 posts | 198 followers

You may also like

Comments