Amazon Simple Email Service
開発者ガイド

Amazon SES API を使用して raw E メールを送信する

高度にカスタマイズされたメッセージを受取人に送信するために、Amazon SES SendRawEmail オペレーションを使用できます。

このセクションには、Amazon SES API を使用して raw E メールを作成および送信する手順が含まれています。

E メールヘッダーフィールドについて

Simple Mail Transfer Protocol (SMTP) は、E メールエンベロープとそのパラメータのいくつかを定義することにより、E メールメッセージの送信方法を定義しますが、メッセージの内容については何も定義しません。一方、Internet Message Format (RFC 5322) は、メッセージの構成方法を定義します。

Internet Message Format の仕様に従って、すべてのメッセージ E メールはヘッダーと本文から構成されます。ヘッダーはメッセージのメタデータで構成され、本文にメッセージそのものが含まれます。E メールヘッダーと本文の詳細については、「E メールの形式と Amazon SES」を参照してください。

MIME の使用

SMTP プロトコルは 7 ビットの ASCII 文字で構成された E メールメッセージを送信するように設計されています。多くの場合は、この仕様が有効に機能しますが、非 ASCII 文字エンコード (Unicode など)、バイナリコンテンツ、添付ファイルに対しては十分ではありません。多目的インターネットメール拡張‎ (MIME) 標準は、これらの制限を回避するために開発されたもので、SMTP を使用して、他の多くの種類のコンテンツを送信できます。

MIME 標準には、メッセージ本文を複数のパートに分割し、パートごとに、どのような操作を行うかを指定する機能があります。たとえば、E メールメッセージ本文の、あるパートはプレーンテキスト、別のパートは HTML という場合があります。さらに、MIME では、E メールメッセージに 1 つ以上の添付ファイルを含めることができます。メッセージの受取人は、E メールクライアント内から添付ファイルを見たり、保存したりできます。

メッセージヘッダーとコンテンツとは空白行で分離されます。E メールの各パートは、boundary で分離されます。boundary は、各パートの開始と終了を示す文字列です。

次の例のマルチパートメッセージには、テキストと HTML パートが含まれています。また、添付ファイルが含まれます。

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 エンコード

SMTP の 7 ビット ASCII 制限により、8 ビット文字を含むコンテンツは、送信前にまず、7 ビット ASCII に変換される必要があります。そのため、MIME は Content-Transfer-Encoding ヘッダーフィールドを定義します。

慣例により、最も一般的なエンコードスキームは、8 ビットのバイナリコンテンツが、明確に定義された 7 ビット ASCII 文字セットでエンコードされる base64 です。E メールを受信した E メールクライアントは、Content-Transfer-Encoding ヘッダーフィールドを検査し、コンテンツに対して、ただちに、base64 デコード操作を実行します。これによって、コンテンツは元の形に戻ります。ほとんどの E メールクライアントでは、エンコードおよびデコードは自動的に行われ、ユーザーはそれを意識する必要はありません。

上記の例では、添付ファイルの customers.txt を base64 形式からデコードして読み取れるようにする必要があります。E メールクライアントによっては、元の形式がプレーンテキストであっても、すべての MIME パートを base64 形式でエンコードするものもあります。E メールクライアントはエンコードとデコードを自動的に行うため、これは通常、問題ではありません。

注記

Amazon SES が許容する MIME タイプの一覧については、「付録: サポート対象外の添付ファイルの種類」を参照してください。

ヘッダーなど、メッセージ内の特定の部分に 7 ビット ASCII 以外の文字を含める場合には、リテラル文字列ではなく MIME encoded-word 構文 (RFC 2047) を使用する必要があります。MIME encoded-word 構文は、=?charset?encoding?encoded-text?= という形式を使います。詳細については、RFC 2047を参照してください。送信先または送信元の E メールアドレス内で、ドメインの部分に unicode 文字が含まれる場合は、Punycode を使用してドメインをエンコードする必要があります。詳細については、「RFC 3492」を参照してください。

Amazon SES API を使用して raw E メールを送信する

Amazon SES API は SendRawEmail アクションを提供します。これにより、指定したフォーマットの E メールメッセージを構成して送信できます。SendRawEmail の詳細については、「Amazon Simple Email Service API Reference」を参照してください。

注記

SendRawEmail に複数の呼び出しを作成する場合の E メール送信速度向上方法については、「Amazon SES のスループットを上げる」を参照してください。

メッセージ本文には、正しくフォーマットされ、適切なヘッダーフィールドとメッセージ本文がエンコードされた raw E メールメッセージを含める必要があります。アプリケーション内で raw メッセージを手動で構成することはできますが、既存のメールライブラリを使用して構成するほうが、はるかに簡単です。

JavaPython
Java

次のコード例は、JavaMail ライブラリと AWS SDK for Java を使用して raw E メールを作成および送信する方法を示しています。

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. After you download the jar file, // include it in the build path for your project. 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; import javax.mail.internet.MimeUtility; // 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 are 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 { String DefaultCharSet = MimeUtility.getDefaultJavaCharset(); 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(); // Encode the text content and set the character encoding. This step is // necessary if you're sending a message with characters outside the // ASCII range. textPart.setContent(MimeUtility .encodeText(BODY_TEXT,DefaultCharSet,"B"), "text/plain; charset=UTF-8"); textPart.setHeader("Content-Transfer-Encoding", "base64"); // Define the HTML part. MimeBodyPart htmlPart = new MimeBodyPart(); // Encode the HTML content and set the character encoding. htmlPart.setContent(MimeUtility .encodeText(BODY_HTML,DefaultCharSet,"B"),"text/html; charset=UTF-8"); htmlPart.setHeader("Content-Transfer-Encoding", "base64"); // 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['ResponseMetadata']['RequestId'])