Amazon SES API を使用して raw E メールを送信する
高度にカスタマイズされたメッセージを受信者に送信するために、Amazon SES SendRawEmail
オペレーションを使用できます。
このセクションには、Amazon SES API を使用して raw E メールを作成および送信する手順が含まれています。
Simple Mail Transfer Protocol (SMTP) は、E メールエンベロープとそのパラメータのいくつかを定義することにより、E メールメッセージの送信方法を定義しますが、メッセージの内容については何も定義しません。一方、Internet Message Format(RFC 5322)は、メッセージの構成方法を定義します。
Internet Message Format の仕様に従って、すべてのメッセージ E メールはヘッダーと本文から構成されます。ヘッダーはメッセージのメタデータで構成され、本文にメッセージそのものが含まれます。E メールヘッダーと本文の詳細については、「Amazon SESのE メール形式」を参照してください。
MIME の使用
SMTP プロトコルはもともと 7 ビット ASCII 文字のみを含む E メールメッセージを送信するように設計されていました。この仕様により、ASCII 以外のテキストエンコード (Unicode など)、バイナリコンテンツ、または添付ファイルでは SMTP が不十分になります。多目的インターネットメール拡張 (MIME) 標準は、SMTP を使用して、他の多くの種類のコンテンツを送信できるようにするために開発されたものです。
MIME 標準には、メッセージ本文を複数のパートに分割し、パートごとに、どのような操作を行うかを指定する機能があります。たとえば、E メールメッセージ本文の、あるパートはプレーンテキスト、別のパートは HTML という場合があります。さらに、MIME では、E メールメッセージに 1 つ以上の添付ファイルを含めることができます。メッセージの受取人は、E メールクライアント内から添付ファイルを見たり、保存したりできます。
メッセージヘッダーとコンテンツとは空白行で分離されます。E メールの各パートは、boundary で分離されます。boundary は、各パートの開始と終了を示す文字列です。
次の例のマルチパートメッセージには、テキストと HTML パート、および添付ファイルが含まれています。添付ファイルは添付ファイルヘッダーのすぐ下に配置する必要があります。ほとんどの場合、この例のように base64
でエンコードされます。
From: "Sender Name" <sender@example.com>
To: recipient@example.com
Subject: Customer service contact info
Content-Type: multipart/mixed;
boundary="a3f166a86b56ff6c37755292d690675717ea3cd9de81228ec2b76ed4a15d6d1a"
--a3f166a86b56ff6c37755292d690675717ea3cd9de81228ec2b76ed4a15d6d1a
Content-Type: multipart/alternative;
boundary="sub_a3f166a86b56ff6c37755292d690675717ea3cd9de81228ec2b76ed4a15d6d1a"
--sub_a3f166a86b56ff6c37755292d690675717ea3cd9de81228ec2b76ed4a15d6d1a
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: quoted-printable
Please see the attached file for a list of customers to contact.
--sub_a3f166a86b56ff6c37755292d690675717ea3cd9de81228ec2b76ed4a15d6d1a
Content-Type: text/html; charset=iso-8859-1
Content-Transfer-Encoding: quoted-printable
<html>
<head></head>
<body>
<h1>Hello!</h1>
<p>Please see the attached file for a list of customers to contact.</p>
</body>
</html>
--sub_a3f166a86b56ff6c37755292d690675717ea3cd9de81228ec2b76ed4a15d6d1a--
--a3f166a86b56ff6c37755292d690675717ea3cd9de81228ec2b76ed4a15d6d1a
Content-Type: text/plain; name="customers.txt"
Content-Description: customers.txt
Content-Disposition: attachment;filename="customers.txt";
creation-date="Sat, 05 Aug 2017 19:35:36 GMT";
Content-Transfer-Encoding: base64
SUQsRmlyc3ROYW1lLExhc3ROYW1lLENvdW50cnkKMzQ4LEpvaG4sU3RpbGVzLENhbmFkYQo5MjM4
OSxKaWUsTGl1LENoaW5hCjczNCxTaGlybGV5LFJvZHJpZ3VleixVbml0ZWQgU3RhdGVzCjI4OTMs
QW5heWEsSXllbmdhcixJbmRpYQ==
--a3f166a86b56ff6c37755292d690675717ea3cd9de81228ec2b76ed4a15d6d1a--
メッセージのコンテンツタイプが multipart/mixed
であることから、メッセージに多数のパートがあり (この例では、本文および添付ファイル)、受信するクライアントは各パートを別々に扱う必要があることがわかります。
本文セクション内に入れ子になっているのは、multipart/alternative
コンテンツタイプを使用する 2 番目のパートです。このコンテンツタイプは、各パートに同じコンテンツの代替バージョンが含まれる (この場合はテキストバージョンおよび HTML バージョン) ことを示します。受取人の E メールクライアントで HTML コンテンツを表示できる場合は、メッセージ本文の HTML バージョンが表示されます。受取人の E メールクライアントで HTML コンテンツを表示できない場合は、メッセージ本文のプレーンテキストバージョンが表示されます。
メッセージの両方のバージョンには添付ファイルも含まれます (この場合、一部の顧客名を含むショートテキストファイル)。
この例のように MIME パートを他のパートに入れ子にすると、入れ子になったパートは、親のパートの boundary
パラメータとは異なる boundary
パラメータを使用する必要があります。これらの境界は固有の文字列でなければなりません。MIME パーツ間の境界を定義するには、2 つのハイフンを (--) タイプし、その後に境界文字列が続きます。MIME パーツの最後に、境界文字列の先頭および末尾の両方に 2 つのハイフンを置きます。
MIME エンコード
古いシステムとの互換性を維持するために、Amazon SES は RFC 2821 で定義されている SMTP の 7 ビット ASCII 制限を優先します。非 ASCII 文字を含むコンテンツを送信する場合は、これらの文字を 7 ビット ASCII 文字を使用する形式にエンコードする必要があります。
E メールアドレス
メッセージエンベロープで使用された E メールアドレスをエンコードするには、Punycode エンコードを使用します。
たとえば、张伟@example.comに E メールを送信するには、アドレスのローカル部分 (@ 記号の前の部分) で Punycode エンコーディングを使用します。結果として得られるエンコードされたアドレスは、xn--cpqy30b@example.com です。
このルールは、メッセージヘッダーではなく、メッセージエンベロープで指定する E メールアドレスにのみ適用されます。SendRawEmail
API を使用する場合、Source
およびDestinations
パラメータで指定したアドレスは、それぞれエンベロープの送信者と受取人を定義します。
Punycode エンコードの詳細については、RFC 3492 を参照してください。
メッセージヘッダーをエンコードするには、MIME encoded-word 構文を使用します。MIME encoded word 構文では、次の形式が使用されます。
=?charset
?encoding
?encoded-text
?=
encoding
の値は Q
または B
となります。エンコードの値が Q
の場合、値 encoded-text
には Q エンコードを使用する必要があります。エンコードの値が B
の場合、encoded-text
の値には base64 エンコードを使用する必要があります。
たとえば、「Як ти поживаєш?」を使用する場合 E メールの件名に次のエンコードのいずれかを使用することができます。
Q エンコードの詳細については、RFC 2047 を参照してください。base64 エンコードの詳細については、RFC 2045 を参照してください。
メッセージ本文
メッセージの本文をエンコードするには、quoted-printable エンコードまたは base64 エンコードを使用できます。次に、Content-Transfer-Encoding
ヘッダーを使用して、使用するエンコードスキームを指定します。
たとえば、メッセージの本文に次のテキストが含まれているとします。
१९७२ मे रे टॉमलिंसन ने पहला ई-मेल संदेश भेजा | रे टॉमलिंसन ने ही सर्वप्रथम @ चिन्ह का चयन किया और इन्ही को ईमेल का आविष्कारक माना जाता है
base64 エンコードを使用してこのテキストをエンコードする場合、最初に以下のヘッダーを指定します。
Content-Transfer-Encoding: base64
次に、E メールの本文セクションに、base64 でエンコードされたテキストを含めます。
4KWn4KWv4KWt4KWoIOCkruClhyDgpLDgpYcg4KSf4KWJ4KSu4KSy4KS/4KSC4KS44KSoIOCkqOCl
hyDgpKrgpLngpLLgpL4g4KSILeCkruClh+CksiDgpLjgpILgpKbgpYfgpLYg4KSt4KWH4KSc4KS+
IHwg4KSw4KWHIOCkn+ClieCkruCksuCkv+CkguCkuOCkqCDgpKjgpYcg4KS54KWAIOCkuOCksOCl
jeCkteCkquCljeCksOCkpeCkriBAIOCkmuCkv+CkqOCljeCkuSDgpJXgpL4g4KSa4KSv4KSoIOCk
leCkv+Ckr+CkviDgpJTgpLAg4KSH4KSo4KWN4KS54KWAIOCkleCliyDgpIjgpK7gpYfgpLIg4KSV
4KS+IOCkhuCkteCkv+Ckt+CljeCkleCkvuCksOCklSDgpK7gpL7gpKjgpL4g4KSc4KS+4KSk4KS+
IOCkueCliAo=
場合によっては、Amazon SES を使用して送信するメッセージに 8 ビットのContent-Transfer-Encoding
を使用できます。ただし、Amazon SES がメッセージを変更する必要がある場合 (たとえば、オープンとクリックの追跡を使用した場合)、8 ビットでエンコードされたコンテンツは、受取人の受信トレイに届いたときに正しく表示されないことがあります。このため、7 ビットの ASCII 以外のコンテンツは常にエンコードする必要があります。
添付ファイル
E メールにファイルを添付するには、base64 エンコードを使用して添付ファイルをエンコードする必要があります。添付ファイルは通常、次のヘッダーを含む専用の MIME メッセージ部分に配置されています。
-
Content-Type – 添付ファイルの種類。一般的な MIME Content-Type 宣言の例を以下に示します。
-
プレーンテキストファイル – Content-Type: text/plain;
name="sample.txt"
-
Microsoft Word ドキュメント – Content-Type: application/msword;
name="document.docx"
-
JPG イメージ – Content-Type: image/jpeg;
name="photo.jpeg"
-
Content-Disposition – 受取人の E メールクライアントがコンテンツをどのように処理するかを指定します。添付ファイルの場合、この値は Content-Disposition:
attachment
です。
-
Content-Transfer-Encoding – 添付ファイルのエンコードに使用されるスキーム。添付ファイルでは、ほとんどの場合この値は base64
です。
-
エンコードされた添付ファイル – 例に示すように、実際の添付ファイルをエンコードして、添付ファイルヘッダーの下の本文に含める必要があります。
Amazon SES は最も一般的なファイルタイプに対応しています。Amazon SES が対応していないファイルの種類の一覧については、「Amazon SES でサポートされていない添付ファイルの種類」を参照してください。
Amazon SES API を使用して raw E メールを送信する
Amazon SES API は SendRawEmail
アクションを提供します。これにより、指定したフォーマットの E メールメッセージを構成して送信できるようになります。SendRawEmail
の詳細については、「Amazon Simple Email Service API リファレンス」を参照してください。
メッセージ本文には、正しくフォーマットされ、適切なヘッダーフィールドとメッセージ本文がエンコードされた raw E メールメッセージを含める必要があります。アプリケーション内で raw メッセージを手動で構成することはできますが、既存のメールライブラリを使用して構成するほうが、はるかに簡単です。
- Java
-
次のコード例は、JavaMailライブラリとAWS SDK for Javaを使用して raw E メールを作成および送信する方法を示しています。
package com.amazonaws.samples;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.ByteBuffer;
import java.util.Properties;
// JavaMail libraries. Download the JavaMail API
// from https://javaee.github.io/javamail/
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
// AWS SDK libraries. Download the AWS SDK for Java
// from https://aws.amazon.com/sdk-for-java
import com.amazonaws.regions.Regions;
import com.amazonaws.services.simpleemail.AmazonSimpleEmailService;
import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClientBuilder;
import com.amazonaws.services.simpleemail.model.RawMessage;
import com.amazonaws.services.simpleemail.model.SendRawEmailRequest;
public class AmazonSESSample {
// Replace sender@example.com with your "From" address.
// This address must be verified with Amazon SES.
private static String SENDER = "Sender Name
<sender@example.com
>";
// Replace recipient@example.com with a "To" address. If your account
// is still in the sandbox, this address must be verified.
private static String RECIPIENT = "recipient@example.com
";
// Specify a configuration set. If you do not want to use a configuration
// set, comment the following variable, and the
// ConfigurationSetName=CONFIGURATION_SET argument below.
private static String CONFIGURATION_SET = "ConfigSet
";
// The subject line for the email.
private static String SUBJECT = "Customer service contact info";
// The full path to the file that will be attached to the email.
// If you're using Windows, escape backslashes as shown in this variable.
private static String ATTACHMENT = "C:\\Users\\sender\\customers-to-contact.xlsx";
// The email body for recipients with non-HTML email clients.
private static String BODY_TEXT = "Hello,\r\n"
+ "Please see the attached file for a list "
+ "of customers to contact.";
// The HTML body of the email.
private static String BODY_HTML = "<html>"
+ "<head></head>"
+ "<body>"
+ "<h1>Hello!</h1>"
+ "<p>Please see the attached file for a "
+ "list of customers to contact.</p>"
+ "</body>"
+ "</html>";
public static void main(String[] args) throws AddressException, MessagingException, IOException {
Session session = Session.getDefaultInstance(new Properties());
// Create a new MimeMessage object.
MimeMessage message = new MimeMessage(session);
// Add subject, from and to lines.
message.setSubject(SUBJECT, "UTF-8");
message.setFrom(new InternetAddress(SENDER));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(RECIPIENT));
// Create a multipart/alternative child container.
MimeMultipart msg_body = new MimeMultipart("alternative");
// Create a wrapper for the HTML and text parts.
MimeBodyPart wrap = new MimeBodyPart();
// Define the text part.
MimeBodyPart textPart = new MimeBodyPart();
textPart.setContent(BODY_TEXT, "text/plain; charset=UTF-8");
// Define the HTML part.
MimeBodyPart htmlPart = new MimeBodyPart();
htmlPart.setContent(BODY_HTML,"text/html; charset=UTF-8");
// Add the text and HTML parts to the child container.
msg_body.addBodyPart(textPart);
msg_body.addBodyPart(htmlPart);
// Add the child container to the wrapper object.
wrap.setContent(msg_body);
// Create a multipart/mixed parent container.
MimeMultipart msg = new MimeMultipart("mixed");
// Add the parent container to the message.
message.setContent(msg);
// Add the multipart/alternative part to the message.
msg.addBodyPart(wrap);
// Define the attachment
MimeBodyPart att = new MimeBodyPart();
DataSource fds = new FileDataSource(ATTACHMENT);
att.setDataHandler(new DataHandler(fds));
att.setFileName(fds.getName());
// Add the attachment to the message.
msg.addBodyPart(att);
// Try to send the email.
try {
System.out.println("Attempting to send an email through Amazon SES "
+"using the AWS SDK for Java...");
// Instantiate an Amazon SES client, which will make the service
// call with the supplied AWS credentials.
AmazonSimpleEmailService client =
AmazonSimpleEmailServiceClientBuilder.standard()
// Replace US_WEST_2 with the AWS Region you're using for
// Amazon SES.
.withRegion(Regions.US_WEST_2).build();
// Print the raw email content on the console
PrintStream out = System.out;
message.writeTo(out);
// Send the email.
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
message.writeTo(outputStream);
RawMessage rawMessage =
new RawMessage(ByteBuffer.wrap(outputStream.toByteArray()));
SendRawEmailRequest rawEmailRequest =
new SendRawEmailRequest(rawMessage)
.withConfigurationSetName(CONFIGURATION_SET);
client.sendRawEmail(rawEmailRequest);
System.out.println("Email sent!");
// Display an error if something goes wrong.
} catch (Exception ex) {
System.out.println("Email Failed");
System.err.println("Error message: " + ex.getMessage());
ex.printStackTrace();
}
}
}
- Python
-
次のコード例は、Python email.mime パッケージと AWS SDK for Python (Boto) を使用して raw E メールを作成および送信する方法を示しています。
import os
import boto3
from botocore.exceptions import ClientError
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
# Replace sender@example.com with your "From" address.
# This address must be verified with Amazon SES.
SENDER = "Sender Name <sender@example.com>
"
# Replace recipient@example.com with a "To" address. If your account
# is still in the sandbox, this address must be verified.
RECIPIENT = "recipient@example.com
"
# Specify a configuration set. If you do not want to use a configuration
# set, comment the following variable, and the
# ConfigurationSetName=CONFIGURATION_SET argument below.
CONFIGURATION_SET = "ConfigSet
"
# If necessary, replace us-west-2 with the AWS Region you're using for Amazon SES.
AWS_REGION = "us-west-2
"
# The subject line for the email.
SUBJECT = "Customer service contact info"
# The full path to the file that will be attached to the email.
ATTACHMENT = "path/to/customers-to-contact.xlsx
"
# The email body for recipients with non-HTML email clients.
BODY_TEXT = "Hello,\r\nPlease see the attached file for a list of customers to contact."
# The HTML body of the email.
BODY_HTML = """\
<html>
<head></head>
<body>
<h1>Hello!</h1>
<p>Please see the attached file for a list of customers to contact.</p>
</body>
</html>
"""
# The character encoding for the email.
CHARSET = "utf-8"
# Create a new SES resource and specify a region.
client = boto3.client('ses',region_name=AWS_REGION)
# Create a multipart/mixed parent container.
msg = MIMEMultipart('mixed')
# Add subject, from and to lines.
msg['Subject'] = SUBJECT
msg['From'] = SENDER
msg['To'] = RECIPIENT
# Create a multipart/alternative child container.
msg_body = MIMEMultipart('alternative')
# Encode the text and HTML content and set the character encoding. This step is
# necessary if you're sending a message with characters outside the ASCII range.
textpart = MIMEText(BODY_TEXT.encode(CHARSET), 'plain', CHARSET)
htmlpart = MIMEText(BODY_HTML.encode(CHARSET), 'html', CHARSET)
# Add the text and HTML parts to the child container.
msg_body.attach(textpart)
msg_body.attach(htmlpart)
# Define the attachment part and encode it using MIMEApplication.
att = MIMEApplication(open(ATTACHMENT, 'rb').read())
# Add a header to tell the email client to treat this part as an attachment,
# and to give the attachment a name.
att.add_header('Content-Disposition','attachment',filename=os.path.basename(ATTACHMENT))
# Attach the multipart/alternative child container to the multipart/mixed
# parent container.
msg.attach(msg_body)
# Add the attachment to the parent container.
msg.attach(att)
#print(msg)
try:
#Provide the contents of the email.
response = client.send_raw_email(
Source=SENDER,
Destinations=[
RECIPIENT
],
RawMessage={
'Data':msg.as_string(),
},
ConfigurationSetName=CONFIGURATION_SET
)
# Display an error if something goes wrong.
except ClientError as e:
print(e.response['Error']['Message'])
else:
print("Email sent! Message ID:"),
print(response['MessageId'])