Zaawansowane szablony e-mail

Ptak

25 mar 2016

Email

1 min read

Zaawansowane szablony e-mail

Ten post jest skierowany do programisty, który chce w pełni wykorzystać możliwości szablonów e-mailowych SparkPost. Zakłada się, że potrafisz czytać zawartość JSON i śledzić podstawowy przepływ programowania. Gdy pojawiają się terminy, które mogą być dla ciebie nowe, takie jak RFC 5322, tekst jest powiązany z jego źródłem.

Ten post jest skierowany do dewelopera, który chce jak najlepiej wykorzystać możliwości szablonów e-mail SparkPost. Zakłada się, że jesteś dobrze zaznajomiony z czytaniem zawartości JSON i śledzeniem podstawowego przepływu programowania. Jeśli pojawiają się terminy, które mogą być dla Ciebie nowe, jak RFC 5322, tekst jest powiązany z jego źródłem. Z tą kwestią załatwioną, przejdźmy od razu do rzeczy.

Szablony i możliwości transmisji SparkPost sprawiają, że wysyłanie e-maili jest proste. Te możliwości zapewniają abstrakcję dla treści tekstowych i HTML, co oznacza, że zazwyczaj nie ma potrzeby bezpośredniego kodowania surowego formatu e-mail, który jest zdefiniowany w RFC 5322 wcześniej znanym jako (RFC 822). Ale czasami możesz chcieć tworzyć bardziej złożone wiadomości, które mają inne części Multipurpose Internet Mail Extensions (MIME), które nie są bezpośrednio dostępne przez interfejs RESTful SparkPost.

Uproszczona Kompozycja E-mail

Najpierw przeanalizujemy scenariusz bezproblemowego wysyłania e-maila. Użyj punktu końcowego transmission do dostarczenia tekstu i treści HTML. W tle SparkPost zajmuje się tworzeniem poprawnego e-maila RFC 5322. SparkPost wstawi zmienne zastępcze z substitution_data w treści tekstowej i HTML. Jest to potężny sposób na generowanie dostosowanej treści dla każdego odbiorcy w typowym szablonie.

Oto przykład transmission z treścią HTML i tekstową zawierającą 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>"
  }
}

Zamiana Tablic Danych 

Wiele osób zdaje sobie sprawę, że końcowe punkty transmisji i szablonów SparkPost mogą wykonywać prostą zamianę treści w nagłówkach e-mail i treściach e-mail. Ale wielu przeocza możliwość dostarczania warunkowej treści lub tablic danych, które można również zastępować. Możesz także dostarczyć unikalną treść dla każdego odbiorcy. W tym przykładzie wysyłamy tablicę unikalnych linków do każdego odbiorcy.

To osiąga się poprzez dostarczenie tablicy danych w formacie JSON, która będzie wypełniona w ciele e-maila. Gdy dane zostaną dostarczone, SparkPost użyje logiki w szablonie do ich wypełnienia.

W tym przykładzie SparkPost będzie szukać danych zastępczych zwanych „files_html” i wykona „for each” na każdym elemencie w tablicy. Utworzy wiersz z wartością „file” w elemencie „files_html”. Zauważ potrójny nawias klamrowy wokół „loop_var.file“. Dzieje się tak, ponieważ każdy element tablicy zawiera HTML i musimy powiedzieć serwerowi, aby użył go w takiej formie, a nie go escape’ował. Część tekstowa będzie prostą etykietą tekstową i adresem URL do pliku.

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

Oto gotowy działający przykład:

{
  "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"
  }
}

Wskazówka: W kodzie zaleca się oddzielić znacznik widoku od danych, ale celem tutaj było utrzymanie przykładu jak najprostszym i łatwym do śledzenia, więc stworzyliśmy dwie tablice. Jedna tablica jest dla części HTML, a druga dla części tekstowej. W produkcji powszechnym rozwiązaniem jest posiadanie jednego zestawu danych i pisanie logiki w kodzie szablonu.

Załączniki w Możliwościach Transmisji

Końcowy punkt transmisji zapewnia również abstrakcję do wysyłania załączników. Poniżej zobaczysz, że załączniki są określone w content.attachments tablica, gdzie każdy obiekt w tablicy opisuje pojedynczy element załącznika. Tak jak wcześniej, SparkPost zajmuje się kodowaniem tekst, HTML, zamiennikami i iteracją przez tablicę załączników, aby zakodować poprawnie sformatowaną wiadomość e-mail.

Najlepsze praktyki sugerują unikanie wysyłania załączników, chyba że jest to wyraźnie wymagane jako część twojej usługi.

Poniżej znajdują się wymagane pola dla załącznika:

  • type: Typ MIME załącznika

  • name: Nazwa pliku załącznika

  • data: Dane pliku w formacie Base64

Tak wygląda załącznik w ramach treści transmisji:

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

Możesz również wysyłać „obrazy osadzone” w transmisji. Są one bardzo podobne do załączników i są określone w tablicy content.inline_images, gdzie każdy z obiektów inline_image  jest podobny do obiektu załącznika pokazanym powyżej.

Załączniki w Szablonach

Teraz, gdy mamy odpowiednie podstawy do wysyłania załączników z końcowego punktu transmisji, przyjrzymy się, jak to zrobić za pomocą szablonów. W momencie pisania tego tekstu nie ma jeszcze abstrakcji dla załączników, takiej jak dla transmisji inline. Można by wnioskować, że szablonów nie da się tworzyć z załącznikami. Byłbyś częściowo poprawny, ale istnieje obejście, chociaż nie będziesz już izolowany od formatu RFC 5322.

Możesz osiągnąć załączniki w szablonach, kodując samodzielnie treść RFC 5322, która zawiera załączniki. Dobrą wiadomością jest to, że nadal będziesz mógł używać danych zastępczych Substitution Data w nagłówkach e-mail, HTML i częściach tekstowych. Weź jednak pod uwagę, że ten rodzaj szablonu ogranicza zastępstwa do nagłówków i pierwszej części HTML oraz tekstowej.

Oto jak to się robi.

E-mail RFC822

Stwórz swój e-mail RFC 5322 z danymi zastępczymi, które chcesz. Stworzyłem go w swoim kliencie poczty i wysłałem do siebie. Po jego otrzymaniu skopiowałem źródło i zastąpiłem pola, które chcę dynamicznie zamienić.

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

Ostatnia część MIME tej wiadomości zawiera Content-Disposition: attachment; filename=myfile.txt”. To tu zdefiniowana jest nazwa pliku. Treść twojego załącznika będzie z pewnością dużo bardziej złożona, ale ten przykład ma być jak najprostszy.

Przechowywany Szablon

Gdy masz poprawny e-mail RFC 5322, przechowaj go używając formy email_rfc822 końcowego punktu szablonu zamiast używać text i HTML. Oto, jak wygląda content dla tej wiadomości:

{
  "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"
}

Gdy żądanie zostanie zrealizowane, SparkPost odpowie unikalnym identyfikatorem dla nowego szablonu. Na przykład xxxxxxx.

Wysyłanie Szablonu

Dobra wiadomość jest taka, że utworzenie treści RFC 5322 było najtrudniejszą częścią. Od tego momentu wysyłanie tego szablonu za pomocą SparkPost jest dokładnie takie samo, jak wysyłanie każdego innego szablonu.

Tak wysyłamy ten szablon i wypełniamy dane zastępcze:

{
  "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
  }
}

Szablony z API Klienta Mailowego

Jeśli używasz języka programowania, który ma bibliotekę do komponowania e-maila, możesz z niej skorzystać, aby programowo stworzyć szablon lub nawet wysłać wiadomość inline. Oto przykład użycia JavaMail przez końcowy punkt transmisji SparkPost. Ta metoda powinna być łatwo przetłumaczona na PHP lub wybrany język.

/**
 * 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();
            }
        }
    }
}

Podsumowanie

Teraz, gdy widzisz, jak SparkPost może być używany do wysyłania e-maili o prawie dowolnej złożoności, możesz chcieć przyjrzeć się „SparkPost Wspiera Wysyłanie E-maili na Apple Watch” lub przyjrzeć się syntaksie zamiany, aby zobaczyć, jak można ją używać z „if then else”, „wyrażeniami w warunkach” lub „Iteracją tablicy” bezpośrednio w twoim szablonie lub treści transmisji.

Inne wiadomości

Czytaj więcej z tej kategorii

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

Kompletna, AI-native platforma, która skaluje się wraz z Twoim business.

Produkt

Rozwiązania

Zasoby

Company

Ustawienia prywatności

Już wkrótce

Social

Biuletyn

Bądź na bieżąco z Bird dzięki cotygodniowym aktualizacjom do Twojej skrzynki odbiorczej.

Zarejestruj się

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

Kompletna, AI-native platforma, która skaluje się wraz z Twoim business.

Produkt

Rozwiązania

Zasoby

Company

Ustawienia prywatności

Social

Biuletyn

Bądź na bieżąco z Bird dzięki cotygodniowym aktualizacjom do Twojej skrzynki odbiorczej.

Zarejestruj się