使用 Amazon SES API v2 發送原始電子郵件 - Amazon Simple Email Service

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

使用 Amazon SES API v2 發送原始電子郵件

您可以raw將 Amazon SES API v2 SendEmail 作業與指定為的內容類型搭配使用,以原始電子郵件格式傳送自訂訊息給收件者。

關於電子郵件標頭欄位

簡易郵件傳送通訊協定 (SMTP) 會指定如何透過定義郵件信封及其某些參數來傳送電子郵件訊息,但它與郵件的內容並不相關。相反地,網際網路訊息格式 (RFC5322) 會定義訊息的建構方式。

在網際網路訊息格式的明確定義下,每個電子郵件訊息都會含有標題和內文。標題包含訊息中繼資料,而內文則包含訊息本身。如需有關電子郵件標題和內文的詳細資訊,請參閱 Amazon SES 中的電子郵件格式

使用 MIME

該SMTP協議最初設計用於發送僅包含 7 位ASCII字符的電子郵件。對於非ASCII文本編碼(例如 Unicode),二進制內容或附件,此規範SMTP不足。多用途互聯網郵件擴展標準(MIME)是為了使其可以使用發送許多其他類型的內容SMTP。

該MIME標準的工作原理是將消息主體分成多個部分,然後指定要對每個部分進行的操作。例如,電子郵件訊息內文的一部分可能是純文字,而另一部分則可能是純文字HTML。此外,MIME允許電子郵件訊息包含一或多個附件。訊息收件人可以在自己的電子郵件用戶端中檢視附件,也可以儲存附件。

訊息標題和內容則是以空白行分隔。每個部分的電子郵件則是以邊界為分隔,邊界為字元字串,用以標記出每個部分的開始與結束。

下列範例中的多部分訊息包含文字、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 內容類型的第二個部分。此內容類型表示每個零件都包含相同內容的替代版本 (在本例中為文字版本與HTML版本)。如果收件者的電子郵件用戶端可以顯示HTML內容,則會顯示郵件內HTML文的版本。如果收件者的電子郵件用戶端無法顯示HTML內容,則會顯示郵件內文的純文字版本。

這兩種訊息版本也都包含附件 (在本案例中是包含部分客戶名稱的簡短文字檔案)。

在另一個MIME零件中巢狀零件時,如本範例所示,巢狀零件必須使用與父系零件中boundary參數不同的參數。boundary這些邊界應為獨特的字元字串。若要定義MIME零件之間的邊界,請鍵入兩個連字號 (--),後面接著邊界字串。在MIME零件結尾處,將兩個連字號放在邊界字串的開頭和結尾處。

注意

訊息不能包含超過 500 個MIME部分。

MIME編碼

為了維持與舊系統的相容性,Amazon SES 遵守 RFC28 21 中定義SMTP的 7 位元ASCII限制。如果要傳送包含非ASCII字元的內容,則必須將這些字元編碼為使用 7 位元ASCII字元的格式。

電子郵件位址

電子郵件地址字串必須為 7 位元ASCII。如果您要寄出的電子郵件地址或收件人的電子郵件地址網域部分包含 Unicode 字元,您必須使用 Punycode 編碼來將網域編碼。Punycode 不可用於電子郵件的本機部分 (也就是 @ 前的部分),也不能使用於「友善寄件人」名稱中。如果您想要在「易記的寄件者」名稱中使用 Unicode 字元,您必須使用編碼MIME字語法對「易記來源」名稱進行編碼,如中所述。使用 Amazon SES API v2 發送原始電子郵件如需有關旁遮普碼的詳細資訊,請參閱 3492 RFC。

注意

此規則僅適用於您在訊息信封中指定的電子郵件地址,不適用於訊息標頭。當您使用 Amazon SES API v2 SendEmail 操作時,您在SourceDestinations參數中指定的地址會分別定義信封寄件者和收件者。

電子郵件標頭

若要對郵件標頭進行編碼,請使用MIME編碼字語法。MIME編碼的字語法使用以下格式:

=?charset?encoding?encoded-text?=

encoding 的值可以是 QB。如果編碼值為 Q,則值 encoded-text 必須使用 Q 編碼。如果編碼值為 B,則值 encoded-text 必須使用 base64 編碼。

例如,如果您想要在電子郵件主旨列中使用字串「Як ти поживаєш?」,您可以使用下列其中一種編碼:

  • Q 編碼

    =?utf-8?Q?=D0=AF=D0=BA_=D1=82=D0=B8_=D0=BF=D0=BE=D0=B6=D0=B8=D0=B2=D0=B0=D1=94=D1=88=3F?=
  • Base64 編碼

    =?utf-8?B?0K/QuiDRgtC4INC/0L7QttC40LLQsNGU0Yg/?=

如需 Q 編碼的詳細資訊,請參閱 RFC20 47。如需有關 Base64 編碼的詳細資訊,請參閱 RFC2045

訊息內文

若要編碼訊息的內文,您可以使用 quoted-printable 編碼或 base64 編碼。然後,使用 Content-Transfer-Encoding 標頭,指出您使用的編碼方案。

例如,假設您的訊息內文包含下列文字:

१९७२ मे रे टॉमलिंसन ने पहला ई-मेल संदेश भेजा | रे टॉमलिंसन ने ही सर्वप्रथम @ चिन्ह का चयन किया और इन्ही को ईमेल का आविष्कारक माना जाता है

如果您選擇使用 base64 編碼編碼此段文字,請先指定以下標頭:

Content-Transfer-Encoding: base64

然後,在電子郵件的內文區段,包含 base64 編碼的文字:

4KWn4KWv4KWt4KWoIOCkruClhyDgpLDgpYcg4KSf4KWJ4KSu4KSy4KS/4KSC4KS44KSoIOCkqOCl hyDgpKrgpLngpLLgpL4g4KSILeCkruClh+CksiDgpLjgpILgpKbgpYfgpLYg4KSt4KWH4KSc4KS+ IHwg4KSw4KWHIOCkn+ClieCkruCksuCkv+CkguCkuOCkqCDgpKjgpYcg4KS54KWAIOCkuOCksOCl jeCkteCkquCljeCksOCkpeCkriBAIOCkmuCkv+CkqOCljeCkuSDgpJXgpL4g4KSa4KSv4KSoIOCk leCkv+Ckr+CkviDgpJTgpLAg4KSH4KSo4KWN4KS54KWAIOCkleCliyDgpIjgpK7gpYfgpLIg4KSV 4KS+IOCkhuCkteCkv+Ckt+CljeCkleCkvuCksOCklSDgpK7gpL7gpKjgpL4g4KSc4KS+4KSk4KS+ IOCkueCliAo=
注意

在某些情況下,您可以在使用 Amazon SES 傳送的訊息Content-Transfer-Encoding中使用 8 位元。但是,如果 Amazon 必SES須對您的訊息進行任何變更 (例如,當您使用開啟和點擊追蹤時),8 位元編碼的內容在送達收件者的收件匣時可能無法正確顯示。因此,您應該始終對不是 7 位ASCII的內容進行編碼。

檔案附件

若要將檔案附加到電子郵件,您必須使用 base64 編碼來編碼附件。附件通常會放置在專用MIME郵件部分中,其中包括下列標頭:

  • Content-Type - 附件的檔案類型。以下是常見的MIME內容類型聲明的例子:

    • 純文字檔案 - 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 - 指定收件人的電子郵件用戶端應該如何處理內容。針對附件,此值為 Content-Disposition: attachment

  • Content-Transfer-Encoding - 過去用來編碼附件的方案。針對檔案附件,此幾乎一律為 base64

  • 編碼附件 - 您必須對實際附件進行編碼,并將其包含在附件標題下方的正文中,如範例中所示

Amazon SES 接受最常見的文件類型。SES如需 Amazon 不接受的檔案類型清單,請參閱Amazon SES 不支援的附件類型

使用 Amazon SES API v2 發送原始電子郵件

Amazon SES API v2 提供的SendEmail動作可讓您以將內容類型設定為簡單、原始或範本化時指定的格式來撰寫和傳送電子郵件訊息。如需完整描述,請參閱SendEmail。下面的例子將指定內容類型為raw使用原始電子郵件格式發送消息。

注意

如需對 SendEmail 執行多重呼叫時提高電子郵件傳送速率的方法,請參閱 透過 Amazon SES 增加輸送量

訊息內文必須包含一封格式正確的電子郵件原始碼訊息,並使用適當的標題欄位與訊息內文編碼。雖然您可以在應用程式內手動建構訊息原始碼,但是使用現有的郵件程式庫來操作會更簡單。

Java

下列程式碼範例會示範如何使用程式JavaMail庫和 AWS SDK for Java撰寫並發送原始電子郵件。

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 電子郵件 .MIME 套件以及 AWS SDK for Python (Boto)撰寫並發送原始電子郵件。

import json 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 import os def boto3_rawemailv2(): SENDER = "Sender <sender@example.com>" RECIPIENT = "recipient@example.com" CONFIGURATION_SET = "ConfigSet" AWS_REGION = "us-east-1" SUBJECT = "Customer service contact info" ATTACHMENT = "path/to/customers-to-contact.xlsx" 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/> <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" 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) msg.attach(att) #changes start from here strmsg = str(msg) body = bytes (strmsg, 'utf-8') client = boto3.client('sesv2') response = client.send_email( FromEmailAddress=SENDER, Destination={ 'ToAddresses': [RECIPIENT] }, Content={ 'Raw': { 'Data': body } } ) print(response) boto3_rawemailv2 ()