2013-12-04

AWSのSESをApex使って触ってみた。

AWSのSESというメール配信サービスが気になったので、force.comのApexから動かしてみた。

 

・コンソールから送る方式

・SMTP方式

・HTTPS方式

の3つがあって、自動配信とかそういうのやる場合はプログラムでSMTP or HTTPS方式でやるみたい。

 

ApexからSMTPは不可能なので、HTTPS方式で、メール送る処理だけ書いてみた。

/**
 * SES呼び出しコモンクラス
 */
public with sharing class SESCommon {
	/**
	 * AccessKey
	 */
	public String AWSAccessKeyId = 'AKI**********';

	/**
	 * SecretKey
	 */
	public String AWSSecretKeyId = '**************************';

    /**
     * メール送信
     * @param fromAddress fromアドレス
     * @param toAddress toアドレス
     * @param subject メール件名
     * @param messageBody メール本文
     */
    public String sendMail(
    	String fromAddress, 
    	String toAddress,
    	String subject, 
    	String messageBody
    ) {
    	String postBody = 'Action=SendEmail';
		postBody += '&Source=' + EncodingUtil.urlEncode(fromAddress, 'UTF-8');
		postBody += '&Destination.ToAddresses.member.1=' + EncodingUtil.urlEncode(toAddress, 'UTF-8');
		postBody += '&Message.Subject.Data=' + EncodingUtil.urlEncode(subject, 'UTF-8');
		postBody += '&Message.Body.Text.Data=' + EncodingUtil.urlEncode(messageBody, 'UTF-8');
        String dateHeader = this.getDateTime(DateTime.now());
        HttpRequest req = new HttpRequest();
        req.setHeader('Date', dateHeader);
        req.setHeader('Content-Type', 'application/x-www-form-urlencoded');
        req.setHeader('Content-Length', String.valueOf(postBody.length()));
        req.setHeader(
        	'X-Amzn-Authorization',
        	'AWS3-HTTPS AWSAccessKeyId=' + this.AWSAccessKeyId + ',' +
        	'Signature=' + createSignature(dateHeader) + ',' + 
        	'Algorithm=HmacSHA1');
    	req.setEndpoint('https://email.us-east-1.amazonaws.com');
        req.setMethod('POST');

        req.setBody(postBody);

        Http http = new Http();
        HTTPResponse res = http.send(req);
        return res.getBody();
    }
    /**
     * フォーマットされた日付文字列を取得
     */
    private String getDateTime(DateTime dt) {
        return dt.format('EEE, dd MMM yyyy HH:mm:ss ') + '+0900';
    }

    /**
     * Signature生成
     */
    private String createSignature(String target) {
    	return EncodingUtil.base64Encode(Crypto.generateMac(
    		'HMacSHA1', 
            Blob.valueOf(target),
            Blob.valueOf(this.AWSSecretKeyId)
        ));
    }
}

 

上記の場合はPOSTでやっているけどGETでもOK。

HTTPリクエストヘッダには以下の内容を入れる。

・Date

→いつものDateヘッダーの値(http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.18

・Content-Type

→"application/x-www-form-urlencoded"の固定値

・Content-Length

→いつもの通り、Bodyの長さ

・X-Amzn-Authorization

→Dateヘッダーの値のハッシュ値(HmacSha1 or HmaxSha256)のBase64エンコード値

 

GETの場合はContent-LengthとかContent-Typeはいらないっす。

サンプル読むとGETのURLパラメータにAlgorithmとかSignatureとか含めちゃってて、

URLパラメータだけでいけんのかなーと思って検証してみたけど、うまくいきませんでした…。

 

S3のSignature生成とかよりは遥かに楽で、

Apexからのメール送信が一日1000件だったり、

WFメールが1000*[SalesforceユーザとかPlatformユーザとかのユーザ数]と

制限が厳しいSalesforceにとっては1000件あたり10円と格安の従量課金で

呼び出しも簡単で、うまくマッチしそうな感じ。

ガバナにさえ気をつければバッチで自動的にメール配信なんかも出来なくは無さそう。

 

SMTP方式もいける(っていうかSES自体がSMTPサーバ扱い?)ので、

メールサーバ立てずにバンバンメール送れるっていうのも良いなって思う。

このエントリーをはてなブックマークに追加