Introducing 'sparkpost' a Rust Crate for email API
Tags: showdev, rust, opensource
Published: 2018-10-16 09:33:56

---
title: "Introducing 'sparkpost' a Rust Crate for email API"
published: true
cover_image: https://hgill.io/images/rustacean-orig-holding-email.png
description: 
tags: showdev, rust, opensource
---

Rust is an enjoyable language, and I have been experimenting with it for a some time. I started with  creating a few web servers using different crates including rocket and actix. I needed to use an email api to send messages from the backend to either myself or the user.


I have used [Sparkpost](https://sparkpost.com) as an email service for such purpose in some of my `nodejs` apps. Having not found any `rust` API lib for it I decided to create one for myself. It is available on [https://crates.io/crates/sparkpost](https://crates.io/crates/sparkpost).


Current implementation includes transmission api only. That allows you to send emails with metadata, templates and other features.


##### Here is a complete example of how to use the lib
```toml
[dependencies]
sparkpost="0.4"
serde_json="1.0"
serde_derive = "1.0"
serde = "1.0"
chrono = { version = "0.4", features = ["serde"] }
dotenv = "0.13"
```

```rust
// main.rs

#[macro_use]
extern crate serde_derive;
extern crate chrono; // for setting dateTime option to an email
extern crate dotenv; // optional- to read api key from .env file
extern crate serde;
extern crate sparkpost;

use chrono::prelude::*;
use sparkpost::transmission::{
  Attachment, EmailAddress, Message, Options, Recipient, Transmission, TransmissionResponse,
};


// this could be any Type to replace vlaues in sparkpost template
// only requirement is that it implements Serialize from serde
#[derive(Debug, Serialize)]
struct Data {
  name: String,
}

#[allow(unused)]
fn get_api_key() -> String {
  use dotenv::dotenv;
  use std::env;
  dotenv().ok();
  env::var("SPARKPOST_API_KEY").expect("SPARKPOST_API_KEY must be set")
}

fn main() {
  // for eu servers use 
  // let tm = Transmission::new_eu(get_api_key());
  let tm = Transmission::new(get_api_key());


  // new email message with sender name and email
  let mut email = Message::new(EmailAddress::new(
    "marketing@example.sink.sparkpostmail.com",
    "Example Company",
  ));

  let options = Options {
    open_tracking: true,
    click_tracking: true,
    transactional: false,
    sandbox: false,
    inline_css: false,
    start_time: Some(Utc.ymd(2019, 1, 1).and_hms(0, 0, 0)),
  };

  // recipient with substitute data for the template
  let recipient = Recipient::with_substitution(
    EmailAddress::new("bob@company.com", "Bob"),
    Data { name: "Bob".into() },
  );

  let attachment = Attachment {
       file_type: "image/png".into(),
       name: "AnImage.png".into(),
       // data is base64 encoded string
       data: "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAmCC".into(),
   };

  // complete the email message with details
  email
    .add_recipient(recipient)
    .add_attachment(attachment)
    .options(options)
    .campaign_id("marketing_blitz")
    .subject("My Awesome email 😎")
    .html("<h1>hello {name}</h1>")
    .text("hello {name}");

  let result = tm.send(&email);

  match result {
    Ok(res) => {
      match res {
        TransmissionResponse::ApiResponse(api_res) => {
          println!("API Response: \n {:#?}", api_res);
            assert_eq!(1, api_res.total_accepted_recipients);
            assert_eq!(0, api_res.total_rejected_recipients);
        }
        TransmissionResponse::ApiError(errors) => {
          println!("Response Errors: \n {:#?}", &errors);
        }
      }
    }
    Err(error) => {
      println!("error \n {:#?}", error);
    }
  }
}


```

As I mentioned above that there are many features that are lacking i.e. saving and retrieving templates and recipient list etc. Reason is that I don't use those features for now. If anyone is interested I will be more than happy to help.

[Twitter](https://Twitter.com/mygnu_)

### Originally published on [hgill.io](https://hgill.io/posts/introducing-rust-sparkpost/)