Product

Soluciones

Recursos

Compañía

Product

Soluciones

Recursos

Compañía

Plantillas de correo electrónico avanzadas

Pájaro

25 mar 2016

Correo electrónico

1 min read

Plantillas de correo electrónico avanzadas

Pájaro

25 mar 2016

Correo electrónico

1 min read

Plantillas de correo electrónico avanzadas

Esta publicación está dirigida al desarrollador que desea aprovechar al máximo las capacidades de plantillas de correo electrónico de SparkPost. Se asume que estás cómodo leyendo contenido JSON y siguiendo un flujo de programación básico. A medida que se introducen términos que pueden ser nuevos para ti, como RFC 5322, el texto está vinculado a su referencia de origen.

Business in a box.

Descubre nuestras soluciones.

Esta publicación está dirigida al desarrollador que quiere aprovechar al máximo las capacidades de plantillas de correo electrónico de SparkPost. Se asume que te sientes cómodo leyendo contenido JSON y siguiendo el flujo básico de programación. A medida que se introducen términos que pueden ser nuevos para ti, como RFC 5322, el texto está vinculado a su referencia fuente. Con eso fuera del camino, vamos a entrar de lleno.

Las plantillas y capacidades de transmisión de SparkPost hacen que el envío de correos electrónicos sea sencillo. Esas capacidades proporcionan una abstracción para el contenido de texto y HTML, lo que significa que la mayoría de las veces no hay necesidad de codificar directamente el formato del correo electrónico sin procesar que está definido en RFC 5322, anteriormente conocido como (RFC 822). Pero a veces puedes querer crear mensajes más complejos que tengan otras partes de Multipurpose Internet Mail Extensions (MIME) que no están directamente expuestas a través de la interfaz RESTful de SparkPost.

Redacción Simplificada de Correos Electrónicos

Primero, revisemos un escenario ideal para el envío de un correo electrónico. Utiliza el endpoint de transmisión para proporcionar el contenido de texto y HTML. En segundo plano, SparkPost se encarga de componer un correo electrónico válido RFC 5322. SparkPost insertará variables de sustitución de substitution_data en el contenido de texto y HTML. Esta es una manera poderosa de generar contenido personalizado para cada destinatario en una plantilla común.

Aquí tienes un ejemplo de transmisión con contenido HTML y de texto con substitution_data.

{
  "options": {
    "open_tracking": true,
    "click_tracking": true
  },
  "campaign_id": "christmas_campaign",
  "return_path": "bounces-christmas-campaign@domain.com",
  "metadata": {
    "user_type": "students"
  },
  "substitution_data": {
    "sender": "Big Store Team"
  },
  "recipients": [
    {
      "return_path": "123@bounces.domain.com",
      "address": {
        "email": "wilma@domain.com",
        "name": "Wilma Flintstone"
      },
      "tags": [
        "greeting",
        "prehistoric",
        "fred",
        "flintstone"
      ],
      "metadata": {
        "place": "Bedrock"
      },
      "substitution_data": {
        "customer_type": "Platinum"
      }
    }
  ],
  "content": {
    "from": {
      "name": "Fred Flintstone",
      "email": "fred@domain.com"
    },
    "subject": "Big Christmas savings!",
    "reply_to": "Christmas Sales <sales@domain.com>",
    "headers": {
      "X-Customer-Campaign-ID": "christmas_campaign"
    },
    "text": "Hi {{address.name}} \nSave big this Christmas in your area {{place}}! \nClick http://www.mysite.com and get huge discount\n Hurry, this offer is only to {{user_type}}\n {{sender}}",
    "html": "<p>Hi {{address.name}} <br>Save big this Christmas in your area {{place}}! <br>Click <a href=\"http://www.mysite.com\">here</a> and get huge discount</p><p>Hurry, this offer is only to {{user_type}}</p><p>{{sender}}</p>"
  }
}

Sustitución de Arreglos de Datos

Muchas personas se dan cuenta de que los endpoints de transmisión y plantilla de SparkPost pueden hacer sustituciones de contenido simple en los encabezados y cuerpos de los correos electrónicos. Pero muchos pasan por alto la capacidad de proporcionar contenido condicional o arreglos de datos que también pueden ser sustituidos. También puedes proporcionar contenido único por destinatario. En este ejemplo enviamos un arreglo de enlaces únicos a cada destinatario.

Esto se logra proporcionando un arreglo JSON de datos que se poblarán en el cuerpo del correo electrónico. Una vez que se proporciona la información, SparkPost usará la lógica en la plantilla para poblarla.

En este ejemplo, SparkPost buscará datos de sustitución llamados “files_html” y realizará un “for each” en cada elemento del arreglo. Creará una fila con el valor de “file” en el elemento “files_html”. Nota el triple rizado alrededor de “loop_var.file“. Esto es porque cada elemento del arreglo contiene HTML y necesitamos decirle al servidor que lo use tal cual y no lo escape. La parte del texto será una etiqueta de texto simple y el URL al archivo.

<table>
  {{each files_html}}
    <tr>
      <td>{{{loop_var.file}}}</td>
    </tr>
  {{ end }}
</table>

Aquí está el ejemplo completado y funcionando:

{
  "recipients": [
    {
      "address": {
        "email": "recipient1@domain.com"
      },
      "substitution_data": {
        "files_html": [
          {
            "file": "<a href=\"http://domain.com/file1a.txt\">File 1a Description</a>"
          },
          {
            "file": "<a href=\"http://domain.com/file2a.txt\">File 2a Description</a>"
          }
        ],
        "files_plain": [
          {
            "file": "File 1a -- http://domain.com/file1a.txt"
          },
          {
            "file": "File 2a -- http://domain.com/file2a.txt"
          }
        ]
      }
    },
    {
      "address": {
        "email": "recipient2@domain.com"
      },
      "substitution_data": {
        "files_html": [
          {
            "file": "<a href=\"http://domain.com/file1b.txt\">File 1b Description</a>"
          },
          {
            "file": "<a href=\"http://domain.com/file2b.txt\">File 2b Description</a>"
          }
        ],
        "files_plain": [
          {
            "file": "File 1b -- http://domain.com/file1b.txt"
          },
          {
            "file": "File 2b -- http://domain.com/file2b.txt"
          }
        ]
      }
    }
  ],
  "return_path": "chris@test.domain.com",
  "content": {
    "from": {
      "name": "chris@test.domain.com",
      "email": "chris@test.domain.com"
    },
    "subject": "Sending with SparkPost is Fun",
    "html": "<b>Your Files:</b><br>\n<table>\n  {{each files_html}}\n    <tr><td>{{{loop_var.file}}}</td></tr>\n  {{ end }}\n</table>\n",
    "text": "Your Files:\n{{each files_plain}} {{loop_var.file}}\n{{ end }}\n"
  }
}

Consejo Profesional: En tu código es recomendable mantener el marcado de vista separado de los datos, pero el objetivo aquí era mantener el ejemplo lo más simple y fácil de seguir posible, así que creamos dos arreglos. Un arreglo es para la parte HTML y el otro es para la parte de Texto. En el uso en producción, sería común tener un conjunto de datos y escribir la lógica en el código de la plantilla.

Adjuntos en Capacidades de Transmisión

El endpoint de transmisión también proporciona una abstracción para el envío de adjuntos. A continuación, verás que los adjuntos se especifican en el arreglo content.attachments donde cada objeto en el arreglo describe un ítem individual adjunto. Así como antes, SparkPost se encargará de codificar texto, HTML, sustituciones e iterar a través del arreglo de adjuntos para codificar un mensaje de correo electrónico debidamente formado.

Las mejores prácticas dictan que el envío de adjuntos se debe evitar a menos que se requiera explícitamente como parte de tu servicio.

A continuación se muestran los campos requeridos para un adjunto:

  • type: El tipo MIME del adjunto

  • name: El nombre del archivo del adjunto

  • data: Datos del archivo codificados en Base64

Así es como se ve un adjunto dentro del contenido de la transmisión:

"content": {
  "attachments": [
    {
      "type": "audio/mp3",
      "name": "voicemail.mp3",
      "data": "TVAzIERhdGEK"
    }
  ]
}

También puedes enviar “imágenes en línea” en una transmisión. Estas son muy similares a los adjuntos y se especifican en el arreglo content.inline_images, donde cada uno de los objetos inline_image son similares al objeto de adjunto mostrado arriba.

Adjuntos en Plantillas

Ahora que tenemos el contexto adecuado para enviar adjuntos con el endpoint de transmisión, echemos un vistazo a cómo hacerlo con plantillas. Al momento de escribir esto, no hay una abstracción de adjuntos como la que encuentras para transmisiones en línea. Uno podría concluir que las plantillas no se pueden crear con adjuntos. Estarías parcialmente en lo correcto, pero hay una solución alternativa, aunque ya no estarás aislado del formato RFC 5322.

Puedes lograr adjuntos en plantillas codificando el contenido RFC 5322 tú mismo, lo que incluye los adjuntos. La buena noticia es que no perderás la capacidad de seguir usando Substitution Data en tus encabezados de correo electrónico, HTML y partes de texto. Ten en cuenta que este tipo de plantilla limita las sustituciones a los encabezados y la primera parte de HTML y de texto.

Aquí hay un ejemplo de cómo se hace.

Correo Electrónico RFC822

Crea tu correo electrónico RFC 5322 con los datos de sustitución que quieres. Creé este en mi cliente de correo y me lo envié a mí mismo. Una vez que lo recibí, copié la fuente y reemplacé los campos que quiero sustituir dinámicamente.

MIME-Version: 1.0
Reply-To: {{replyto}}
Subject: {{subject}}
From: {{from}}
To: {{address.email}}
Content-Type: multipart/mixed; boundary="001a113c48b0b89d92052d3051da"
--001a113c48b0b89d92052d3051da
Content-Type: multipart/alternative; boundary="001a113c48b0b89d89052d3051d8"
--001a113c48b0b89d89052d3051d8
Content-Type: text/plain; charset=UTF-8
Email with a *text attachment*.
{{body2}}
--001a113c48b0b89d89052d3051d8
Content-Type: text/html; charset=UTF-8
<div dir="ltr">
  <div>Email with a <i>text attachment</i>.</div>
  {{body1}}
<

La última parte MIME en este mensaje verás Content-Disposition: attachment; filename=myfile.txt”. Ahí es donde se define el nombre del archivo. El contenido de tu adjunto será sin duda mucho más complejo, pero este ejemplo intenta mantenerlo simple.

Plantilla Almacenada

Una vez que tengas un correo electrónico RFC 5322 válido, guárdalo usando el formulario email_rfc822 del endpoint de plantilla en lugar de usar los campos text y HTML. Aquí tienes un ejemplo de cómo se ve el content para ese mensaje:

{
  "content": {
    "email_rfc822": "MIME-Version: 1.0\nReply-To: {{replyto}}\nSubject: {{subject}}\nFrom: {{from}}\nTo: {{address.email}}\nContent-Type: multipart/mixed; boundary=001a113c48b0b89d92052d3051da\n\n--001a113c48b0b89d92052d3051da\nContent-Type: multipart/alternative; boundary=001a113c48b0b89d89052d3051d8\n\n--001a113c48b0b89d89052d3051d8\nContent-Type: text/plain; charset=UTF-8\n\nEmail with a *text attachment*.\n\n{{body2}}\n\n--001a113c48b0b89d89052d3051d8\nContent-Type: text/html; charset=UTF-8\n\n<div dir=\"ltr\"><div>Email with a <i>text attachment</i>.</div>\n\n{{body1}}\n</div>\n\n--001a113c48b0b89d89052d3051d8--\n--001a113c48b0b89d92052d3051da\nContent-Type: text/plain; charset=US-ASCII; name=\"myfile.txt\"\nContent-Disposition: attachment; filename=\"myfile.txt\"\nContent-Transfer-Encoding: base64\nX-Attachment-Id: f_ild455ce0\n\nVGhpcyBpcyBteSBzaW1wbGUgdGV4dCBmaWxlLgo=\n--001a113c48b0b89d92052d3051da--"
  },
  "name": "_TMP_TEMPLATE_TEST"
}

Cuando se complete la solicitud, SparkPost responderá con un identificador único para tu nueva plantilla. Por ejemplo, xxxxxxx.

Envío de la Plantilla

La buena noticia es que crear el contenido RFC 5322 fue la parte difícil. De aquí en adelante enviar esa plantilla con SparkPost es exactamente igual a enviar cualquier otra plantilla.

Aquí está cómo enviamos esa plantilla y poblamos los datos de sustitución:

{
  "campaign_id": "MyCampaign",
  "return_path": "myReturnPath@yourdomain.com",
  "substitution_data": {
    "replyto": "myReplyToh@yourdomain.com",
    "from": "MyFrom@yourdomain.com",
    "subject": "my subject",
    "body1": "Extra content for the HTML part",
    "body2": "Extra content for the text part"
  },
  "recipients": [
    {
      "substitution_data": {},
      "address": {
        "email": "test1@domain.com",
        "name": "test1"
      }
    }
  ],
  "content": {
    "template_id": "xxxxxxx",
    "use_draft_template": true
  }
}

Plantillas desde la API de un Cliente de Correo

Si estás utilizando un lenguaje de programación que tiene una biblioteca para componer un correo electrónico, puedes usarlo para crear programáticamente la plantilla o incluso enviar el mensaje en línea. Aquí tienes un ejemplo de uso de JavaMail a través del endpoint de transmisión de SparkPost. Este método debería traducirse fácilmente a PHP o tu lenguaje de elección.

/**
 * Demonstration of using JavaMail MIME message with the SparkPost RESTful interface
 */
public class App extends SparkPostBaseApp {
    public static void main(String[] args) throws Exception {
        Logger.getRootLogger().setLevel(Level.DEBUG);
        App app = new App();
        app.runApp();
    }
    private void runApp() throws Exception {
        Message message = createMultipartMessage();
        // Convert JavaMail message into a string for transmission
        String rfc822Content = getMessageAsString(message);
        // Add dynamic To and From using SparkPost substitution syntax
        rfc822Content = "To: {{address.email}}\r\nFrom: {{from}}\r\n" + rfc822Content;
        String fromAddress = getFromAddress();
        String[] recipients = getTestRecipients();
        sendEmail(fromAddress, recipients, rfc822Content);
    }
    private void sendEmail(String from, String[] recipients, String email)
            throws SparkPostException, IOException {
        Client sparkpostClient = newConfiguredClient();
        TransmissionWithRecipientArray transmission = new TransmissionWithRecipientArray();
        // Populate Recipients
        List<RecipientAttributes> recipientArray = new ArrayList<>();
        for (String recipient : recipients) {
            RecipientAttributes recipientAttribs = new RecipientAttributes();
            recipientAttribs.setAddress(new AddressAttributes(recipient));
            recipientArray.add(recipientAttribs);
        }
        transmission.setRecipientArray(recipientArray);
        transmission.setReturnPath(from);
        // Populate Substitution Data
        Map<String, String> substitutionData = new HashMap<>();
        substitutionData.put("from", from);
        substitutionData.put("name", "Your Name Here");
        transmission.setSubstitutionData(substitutionData);
        // Populate Email Body with RFC822 MIME
        TemplateContentAttributes contentAttributes = new TemplateContentAttributes();
        contentAttributes.setEmailRFC822(email);
        transmission.setContentAttributes(contentAttributes);
        // Send Email
        RestConnection connection = new RestConnection(sparkpostClient, getEndPoint());
        Response response = ResourceTransmissions.create(connection, 0, transmission);
        if (response.getResponseCode() == 200) {
            System.out.println("✅ Transmission Response: " + response);
        } else {
            System.err.println("❌ TRANSMISSION ERROR: " + response);
        }
    }
    /**
     * Builds an email with text, HTML, and attachment parts
     */
    private Message createMultipartMessage() throws MessagingException {
        Properties props = new Properties();
        props.put("mail.smtp.host", "none"); // Required for JavaMail to work
        Session session = Session.getDefaultInstance(props, null);
        Message message = new MimeMessage(session);
        message.setSubject("A multipart MIME message demo");
        // Main multipart container
        Multipart multiPart = new MimeMultipart("mixed");
        // Sub multipart for text + HTML
        MimeMultipart altPart = new MimeMultipart("alternative");
        // Text part
        MimeBodyPart textPart = new MimeBodyPart();
        textPart.setText("{{name}},\r\nplain text content", "utf-8");
        // HTML part
        MimeBodyPart htmlPart = new MimeBodyPart();
        htmlPart.setContent("<b>{{name}},<br><br>Our HTML content</b>", "text/html; charset=utf-8");
        // Add text and HTML to the alternative container
        altPart.addBodyPart(textPart);
        altPart.addBodyPart(htmlPart);
        // Wrap alternative part in a MimeBodyPart so it can be added to mixed container
        MimeBodyPart altBodyPart = new MimeBodyPart();
        altBodyPart.setContent(altPart);
        // Add alternative section to mixed container
        multiPart.addBodyPart(altBodyPart);
        // Add attachment
        MimeBodyPart attachmentPart = new MimeBodyPart();
        String filename = "java_SparkPost_background.pdf";
        DataSource source = new FileDataSource(filename);
        attachmentPart.setDataHandler(new DataHandler(source));
        attachmentPart.setFileName(filename);
        multiPart.addBodyPart(attachmentPart);
        // Set full content
        message.setContent(multiPart);
        return message;
    }
    /**
     * Converts a JavaMail message into an RFC822 string
     */
    private String getMessageAsString(Message msg) throws IOException, MessagingException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            msg.writeTo(out);
            return out.toString("UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("UTF-8 not found! " + e.getMessage());
        } finally {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Conclusión

Ahora que ves cómo se puede usar SparkPost para enviar correos electrónicos de casi cualquier complejidad, puedes querer echar un vistazo a “SparkPost Supports Sending Email on Apple Watch” o echar un vistazo a la sintaxis de sustitución para ver cómo se puede usar con “if then else”, “expresiones en condicionales” o “Iteración en arreglos” directamente dentro de tu contenido de plantilla o transmisión.

A person is standing at a desk while typing on a laptop.

La plataforma completa nativa de AI que escala con tu negocio.

Product

Soluciones

Recursos

Compañía

Configuración de privacidad

Próximamente

Social

Newsletter

Mantente al día con Bird a través de actualizaciones semanales en tu buzón.

Signup

© 2025 Bird

A person is standing at a desk while typing on a laptop.

La plataforma completa nativa de AI que escala con tu negocio.

Product

Soluciones

Recursos

Compañía

Configuración de privacidad

Social

Newsletter

Mantente al día con Bird a través de actualizaciones semanales en tu buzón.

Signup

© 2025 Bird