Questo post è diretto allo sviluppatore che vuole ottenere il massimo dalle capacità di creazione di modelli email di SparkPost. Si presume che sei a tuo agio con la lettura di contenuti JSON e il seguire il flusso di programmazione di base. Quando vengono introdotti termini che potrebbero essere nuovi per te, come RFC 5322, il testo è collegato alla sua fonte di riferimento. Con ciò fuori mano, iniziamo subito.
Le capacità di modello e di trasmissione di SparkPost rendono l'invio di email diretto. Queste capacità forniscono un'astrazione per il contenuto testo e HTML, il che significa che la maggior parte delle volte non è necessario codificare direttamente il formato grezzo dell'email, che è definito in RFC 5322 precedentemente noto come (RFC 822). Ma a volte potresti voler creare messaggi più complessi che contengono altre estensioni multipurpose Internet Mail (MIME) che non sono direttamente esposte tramite l'interfaccia RESTful di SparkPost.
Composizione Email Semplificata
Per prima cosa, rivediamo uno scenario ideale per l'invio di un'email. Usa l'endpoint di trasmissione per fornire il testo
e il contenuto HTML. Dietro le quinte, SparkPost si prende cura di comporre un'email RFC 5322 valida. SparkPost inserirà variabili di sostituzione da substitution_data nel testo e nel contenuto HTML. Questo è un modo potente per generare contenuti personalizzati per ciascun destinatario in un comune modello.
Ecco un esempio di trasmissione con contenuto HTML e testuale 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>"
}
}
Sostituzione Array di Dati
Molti si rendono conto che gli endpoint di trasmissione e modello di SparkPost possono fare una semplice sostituzione di contenuti negli intestazioni email e nei corpi email. Ma molti trascurano la capacità di fornire contenuti condizionali o array di dati che possono essere sostituiti anche. Puoi anche fornire contenuti unici per destinatario. In questo esempio inviamo un array di link unici a ciascun destinatario.
Questo viene realizzato fornendo un array JSON di dati che sarà popolato nel corpo dell'email. Una volta che i dati sono forniti, SparkPost utilizzerà la logica nel modello per popolarli.
In questo esempio, SparkPost cercherà i dati di sostituzione chiamati "files_html" e farà un "per ognuno" su ciascun elemento nell'array. Creerà una riga con il valore di "file" nell'elemento "files_html". Nota le triple graffe intorno a "loop_var.file". Questo perché ogni elemento dell'array contiene HTML e dobbiamo dire al server di usarlo così com'è e non di sfugarlo. La parte di testo sarà un semplice etichetta di testo e l'URL al file.
<table>
{{each files_html}}
<tr>
<td>{{{loop_var.file}}}</td>
</tr>
{{ end }}
</table>
Qui è il esempio completo funzionante:
{
"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"
}
}
Pro Tip: Nel tuo codice è consigliabile mantenere il markup della vista separato dai dati, ma l'obiettivo qui era mantenere l'esempio il più semplice e facile da seguire possibile, quindi abbiamo creato due array. Uno è per la parte HTML e l'altro è per la parte Testo. In un uso di produzione sarebbe comune avere un set di dati e scrivere la logica nel codice del modello.
Allegati nelle Capacità di Trasmissione
L'endpoint di trasmissione fornisce anche un'astrazione per l'invio di allegati. Di seguito vedrai che gli allegati sono specificati nell'array content.attachments dove ciascun oggetto nell'array descrive un singolo elemento di allegato. Come prima, SparkPost si occupa di codificare testo, HTML, sostituzioni e iterare attraverso l'array di allegati per codificare un messaggio email correttamente formato.
Le migliori pratiche dicono che l'invio di allegati è meglio evitarlo a meno che non sia esplicitamente richiesto come parte del tuo servizio.
Di seguito sono riportati i campi richiesti per un allegato:
type: Il tipo MIME dell'allegato
name: Il nome del file dell'allegato
data: I dati del file codificati in Base64
Questo è l'aspetto di un allegato all'interno del contenuto di trasmissione:
"content": {
"attachments": [
{
"type": "audio/mp3",
"name": "voicemail.mp3",
"data": "TVAzIERhdGEK"
}
]
}
Puoi anche inviare "immagini inline" in una trasmissione. Queste sono molto simili agli allegati e sono specificate nell'array content.inline_images dove ciascun oggetto inline_image è simile all'oggetto allegato mostrato sopra.
Allegati nei Modelli
Ora che abbiamo il background corretto per inviare allegati con l'endpoint di trasmissione, diamo un'occhiata a come farlo con i modelli. Al momento della stesura di questo documento, non esiste un'astrazione per gli allegati come quella che trovi per le trasmissioni inline. Si potrebbe concludere che i modelli non possono essere creati con allegati. Avresti parzialmente ragione, ma esiste un espediente, sebbene non sarai più isolato dal formato RFC 5322.
Puoi realizzare allegati nei modelli codificandoti il contenuto RFC 5322 che include gli allegati. La buona notizia è che non perderai la possibilità di usare ancora Substitute Data nelle tue intestazioni email, HTML e parti di testo. Sappi che questo tipo di modello limita le sostituzioni alle intestazioni e alla prima parte HTML e prima parte testo.
Di seguito un esempio di come è fatto.
Email RFC822
Crea la tua email RFC 5322 con i dati di sostituzione che desideri. Ho creato questo nel mio client di posta e l'ho inviato a me stesso. Una volta ricevuto, ho copiato la fonte e sostituito i campi che voglio sostituire dinamicamente.
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}}
<
L'ultima parte MIME in questo messaggio vedrai Content-Disposition: attachment; filename=myfile.txt”. È lì che è definito il nome del file. Il tuo contenuto dell'allegato sarà sicuramente molto più complesso ma questo esempio cerca di mantenerlo semplice.
Modello Memorizzato
Una volta che hai un'email RFC 5322 valida, memorizzala utilizzando la forma email_rfc822 dell'endpoint del modello invece di utilizzare i campi text e HTML. Ecco un esempio di come si presenta il contenuto per quel messaggio:
{
"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"
}
Quando la richiesta è completata, SparkPost risponderà con un identificatore unico per il tuo nuovo modello. Ad esempio xxxxxxx.
Invio del Modello
La buona notizia è che creare il contenuto RFC 5322 era la parte difficile. Da qui in avanti inviare quel modello con SparkPost è esattamente lo stesso di inviare qualsiasi altro modello.
Ecco come inviamo quel modello e popolare i dati di sostituzione:
{
"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
}
}
Modelli da API di un Client di Posta
Se stai usando un linguaggio di programmazione che ha una libreria per comporre un'email, puoi usarlo per creare programmaticamente il modello o persino inviare il messaggio inline. Qui è un esempio di utilizzo di JavaMail per fare esattamente quello attraverso l'endpoint di trasmissione di SparkPost. Questo metodo dovrebbe essere facilmente tradotto in PHP o nel tuo linguaggio di scelta.
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();
String rfc822Content = getMessageAsString(message);
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();
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);
Map<String, String> substitutionData = new HashMap<>();
substitutionData.put("from", from);
substitutionData.put("name", "Your Name Here");
transmission.setSubstitutionData(substitutionData);
TemplateContentAttributes contentAttributes = new TemplateContentAttributes();
contentAttributes.setEmailRFC822(email);
transmission.setContentAttributes(contentAttributes);
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);
}
}
private Message createMultipartMessage() throws MessagingException {
Properties props = new Properties();
props.put("mail.smtp.host", "none");
Session session = Session.getDefaultInstance(props, null);
Message message = new MimeMessage(session);
message.setSubject("A multipart MIME message demo");
Multipart multiPart = new MimeMultipart("mixed");
MimeMultipart altPart = new MimeMultipart("alternative");
MimeBodyPart textPart = new MimeBodyPart();
textPart.setText("{{name}},\r\nplain text content", "utf-8");
MimeBodyPart htmlPart = new MimeBodyPart();
htmlPart.setContent("<b>{{name}},<br><br>Our HTML content</b>", "text/html; charset=utf-8");
altPart.addBodyPart(textPart);
altPart.addBodyPart(htmlPart);
MimeBodyPart altBodyPart = new MimeBodyPart();
altBodyPart.setContent(altPart);
multiPart.addBodyPart(altBodyPart);
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);
message.setContent(multiPart);
return message;
}
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();
}
}
}
}
Conclusione
Ora che vedi come SparkPost può essere utilizzato per inviare email di quasi ogni complessità, potresti voler dare un'occhiata a “SparkPost Supports Sending Email on Apple Watch” o dare un'occhiata alla sintassi di sostituzione per vedere come può essere utilizzata con “if then else”, “espressioni nei condizionali” o “iterazione array” direttamente all'interno del tuo contenuto di template o trasmissione.