Amazon Simple Email Service
Guía del desarrollador

Envío de correo electrónico sin procesar mediante la API de Amazon SES

Puede utilizar la operación SendRawEmail de Amazon SES para enviar mensajes muy personalizados a sus destinatarios.

Esta sección incluye procedimientos para la construcción y el envío de correos electrónicos sin procesar a través de la API de Amazon SES.

Acerca de los campos de encabezados de correo electrónico

Simple Mail Transfer Protocol (SMTP) especifica la forma en que se envían los mensajes de correo electrónico definiendo el sobre del correo y algunos de sus parámetros, pero no se preocupa del contenido del mensaje. En lugar de ello, el formato de mensajes de Internet (RFC 5322) define cómo se construye el mensaje.

Con la especificación de formato de mensajes de Internet, todos los mensajes de correo electrónico se componen de un encabezado y de un cuerpo. El encabezado se compone de metadatos de mensaje y el cuerpo contiene el mensaje propiamente dicho. Para obtener más información acerca los encabezados y cuerpos de correo electrónico, consulte Formato de correo electrónico y Amazon SES.

Uso de MIME

El protocolo SMTP fue diseñado originalmente para enviar mensajes de correo electrónico que solo contenían caracteres ASCII de 7 bits. Esta limitación hace que SMTP no sea suficiente para codificaciones de texto no ASCII (como Unicode), contenido binario o archivos adjuntos. El estándar Multipurpose Internet Mail Extensions (MIME) se ha desarrollado para superar estas limitaciones, haciendo que sea posible enviar muchas otras clases de contenido utilizando SMTP.

El estándar MIME funciona desglosando el cuerpo del mensaje en varias partes y, a continuación, especificando lo que hay que hacer con cada parte. Por ejemplo, una parte del cuerpo de un mensaje de correo electrónico podría ser texto sin formato, mientras que otra podría ser HTML. Además, MIME permite a los mensajes de correo electrónico contener uno o más archivos adjuntos. Los destinatarios del mensaje pueden ver los archivos adjuntos desde sus clientes de correo electrónico o pueden guardar los archivos adjuntos.

El encabezado del mensaje y el contenido están separados por una línea en blanco. Cada parte del correo electrónico está separada por un límite, una cadena de caracteres que indica el inicio y el final de cada parte.

El mensaje multiparte del siguiente ejemplo contiene un texto y una parte HTML. También contiene un archivo adjunto.

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

El tipo de contenido del mensaje es multipart/mixed, lo que indica que el mensaje tiene muchas partes (en este ejemplo, un cuerpo y un archivo adjunto) y el cliente de recepción debe gestionar cada parte por separado. Anidada en la sección del cuerpo, hay una segunda parte que utiliza el tipo de contenido multipart/alternative. Este tipo de contenido indica que cada parte contiene otras versiones alternativas del mismo contenido (en este caso, una versión de texto y una versión en HTML). Si el cliente de correo electrónico del destinatario puede mostrar contenido HTML, muestra la versión HTML del cuerpo del mensaje. Si el cliente de correo electrónico del destinatario no puede mostrar contenido HTML, muestra la versión de texto sin formato del cuerpo del mensaje. Ambas versiones del mensaje también contendrán un archivo adjunto (en este caso, un archivo de texto breve que contiene los nombres de algunos clientes).

Al anidar una parte de MIME dentro de otra parte, como en este ejemplo, la parte anidada debe utilizar un parámetro boundary que es distinto del parámetro boundary en la parte principal. Estos límites deben ser cadenas de caracteres únicas. Para definir un límite entre las partes de MIME, escriba dos guiones (--) seguidos de la cadena límite. Al final de una parte MIME, coloque dos guiones tanto al comienzo como al final de la cadena límite.

Codificación MIME

Para mantener la compatibilidad con sistemas antiguos, Amazon SES respeta la limitación de ASCII de 7 bits de SMTP, tal y como se define en RFC 2821. Si desea enviar contenido que contiene caracteres no ASCII, debe codificar los caracteres en un formato que utiliza caracteres ASCII de 7 bits.

Direcciones de correo electrónico

Para codificar una dirección de correo electrónico que se utiliza en el sobre del mensaje, utilice la codificación Punycode.

Por ejemplo, para enviar un correo electrónico a 张伟@example.com, utilice la codificación Punycode en la parte local de la dirección (la parte situada antes del signo @). La dirección codificada resultante es xn--cpqy30b@example.com.

nota

Esta regla solo se aplica a las direcciones de correo electrónico que se especifican en el sobre, no a los encabezados del mensaje. Cuando se utiliza la API SendRawEmail, las direcciones que especifique en los parámetros Source y Destinations definen el remitente y los destinatarios del sobre, respectivamente.

Para obtener más información acerca de la codificación Punycode, consulte RFC 3492.

Encabezados de correo electrónico

Para codificar el encabezado de un mensaje, utilice la sintaxis de palabras codificadas de MIME. la sintaxis de palabras codificadas de MIME utiliza el formato siguiente:

=?charset?encoding?encoded-text?=

El valor de encoding puede ser Q o B. Si el valor de encoding es Q, el valor encoded-text debe utilizar la codificación Q. Si el valor de encoding es B, el valor encoded-text debe utilizar la codificación Base64.

Por ejemplo, si desea utilizar la cadena "Як ти поживаєш?" en la línea de asunto de un mensaje de correo electrónico, puede utilizar cualquiera de las siguientes codificaciones:

  • Codificación 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?=
  • Codificación Base64

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

Para obtener más información sobre la codificación Q, consulte RFC 2047. Para obtener más información sobre la codificación Base64, consulte RFC 2045.

Cuerpo del mensaje

Para codificar el cuerpo de un mensaje, puede utilizar la codificación quoted-printable o la codificación Base64. A continuación, utilice el encabezado Content-Transfer-Encoding para indicar el esquema de codificación que ha utilizado.

Por ejemplo, supongamos que el cuerpo del mensaje contiene el texto siguiente:

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

Si opta por codificar este texto con la codificación Base64, en primer lugar, especifique el siguiente encabezado:

Content-Transfer-Encoding: base64

A continuación, en la sección del cuerpo del mensaje, incluya el texto codificado en Base64:

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

nota

En algunos casos, puede utilizar la Content-Transfer-Encoding de 8 bits en los mensajes que envíe a través de Amazon SES. Sin embargo, si Amazon SES tiene que realizar algún cambio en los mensajes (por ejemplo, cuando se utiliza el seguimiento de apertura y de clics), el contenido codificado en 8 bits podría no aparecer correctamente cuando llegue a las bandejas de correo de los destinatarios. Por este motivo, siempre debe codificar el contenido que no esté en ASCII de 7 bits.

Archivos adjuntos

Para adjuntar un archivo a un correo electrónico, debe codificar el archivo adjunto con la codificación Base64. Los archivos adjuntos normalmente se colocan en partes de mensaje MIME dedicadas, que incluyen los siguientes encabezados:

  • Content-Type: el tipo de archivo del archivo adjunto. A continuación, se muestran ejemplos de declaraciones comunes de Content-Type de MIME:

    • Archivo de texto sin formato: Content-Type: text/plain; name="sample.txt"

    • Documento de Microsoft Word: Content-Type: application/msword; name="document.docx"

    • Imagen JPG: Content-Type: image/jpeg; name="photo.jpeg"

  • Content-Disposition: especifica cómo debe gestionar el contenido el cliente de correo electrónico del destinatario. Para los archivos adjuntos, este valor es Content-Disposition: attachment.

  • Content-Transfer-Encoding: el esquema que se utilizó para codificar el archivo adjunto. Para los archivos adjuntos, este valor casi siempre es base64.

Amazon SES acepta los tipos de archivos más comunes. Para obtener una lista de los tipos de archivos que Amazon SES no acepta, consulte Apéndice: tipos de archivos adjuntos no admitidos.

Envío de un correo electrónico sin procesar mediante la API de Amazon SES

La API de Amazon SES proporciona la acción SendRawEmail, que le permite componer y enviar un mensaje de correo electrónico en el formato que especifique. Para obtener una descripción completa de SendRawEmail, consulte la Amazon Simple Email Service API Reference.

nota

Para obtener consejos sobre cómo incrementar la velocidad de envío de correo electrónico al realizar varias llamadas a SendRawEmail, consulte Aumento del rendimiento con Amazon SES.

El cuerpo del mensaje debe contener un mensaje de correo electrónico sin procesar con el formato correcto, con campos de encabezado adecuados y con codificación del cuerpo del mensaje. Aunque es posible construir el mensaje sin procesar manualmente dentro de una aplicación, es mucho más sencillo hacerlo a través de las bibliotecas de correo existentes.

JavaPython
Java

El siguiente ejemplo de código muestra cómo utilizar la biblioteca JavaMail y el AWS SDK for Java para componer y enviar correo electrónico sin procesar.

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

El siguiente ejemplo de código muestra cómo utilizar los paquetes email.mime de Python y el AWS SDK for Python (Boto) para componer y enviar un correo electrónico sin procesar.

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'])