diff --git a/Readme.md b/Readme.md
index 4ff4837..24e7066 100644
--- a/Readme.md
+++ b/Readme.md
@@ -1,5 +1,8 @@
[![Rust Build](https://github.com/MinaMatta98/Bulk-Email-Cli-CLient/actions/workflows/rust.yml/badge.svg)](https://github.com/MinaMatta98/Bulk-Email-Cli-CLient/actions/workflows/rust.yml)
+[![Test](https://github.com/MinaMatta98/Bulk-Email-Cli-CLient/actions/workflows/test.yml/badge.svg)](https://github.com/MinaMatta98/Bulk-Email-Cli-CLient/actions/workflows/test.yml)
+
+
[![GitHub version](https://img.shields.io/github/v/tag/MinaMatta98/Bulk-Email-Cli-CLient?label=Version)](https://github.com/MinaMatta98/Bulk-Email-Cli-CLient/releases)
@@ -15,26 +18,23 @@
An asynchronous [RUST](https://www.rust-lang.org/) based CLI bulk emailing client, built on top of [lettre-rs](https://github.com/lettre/lettre).
-### Features
----
+## Features
|Feature|Description|
|-------|-----------|
+|Template Variable Substitution| Refer to the [Template Variable Substitution](#template-variable-substitution) section for modifying email-templates|
|Single Email Support| Refer to [Send a Single Email](#send-a-single-email)|
|Bulk Email Support| Support for asynchronous unordered sending of bulk emails detailed within a csv file as described within [Send Bulk Emails](#send-bulk-emails) |
|Attachment Support| Support for Inline/Standard Attachments |
|SMTP Transport| This tool uses the SMTP protocol to send emails over the network |
|TLS Encryption| This tool defaults to TLS encryption over network|
-
-
-### Instructions:
----
+## Instructions:
-#### Installation:
+### Installation:
Installation of this tool will require [RUST installation version](https://www.rust-lang.org/tools/install) of 1.70 or newer.
To install this package via cargo, run the following command from a shell of choice:
@@ -42,13 +42,10 @@ To install this package via cargo, run the following command from a shell of cho
```bash
cargo install --locked --git https://github.com/MinaMatta98/Bulk-Email-Cli-CLient.git
```
-
-
-
-#### Setting Environmental Variables
+### Setting Environmental Variables
---
The following environmental variables must be set:
@@ -58,17 +55,15 @@ The following environmental variables must be set:
|SENDER_PASSWORD|Corrosponding password for the email account sending Email(s).Turn on Less-Secure-Apps to send emails: https://myaccount.google.com |
|SMTP_RELAY|The SMTP relay corrosponding to the SMTP Gateway of Choice. For example, Gmail uses smtp.gmail.com and AOL uses smtp.aol.com |
-
-
-#### Send a Single Email
+### Send a Single Email
---
Refer to [Environmental Variables](#environmental-variables) for setting up environmental variables.
-##### Scenario 1:
+#### Scenario 1
Send an email to `minamatta98@gmail.com` with the template saved within `./templates/email.html` relative to the current working directory (check with ```bash pwd```).
```bash
@@ -77,22 +72,21 @@ email-sender single-email --to-addr "minamatta98@gmail.com" --subject "Email Tes
-##### Scenario 2:
+#### Scenario 2
Send an email to `minamatta98@gmail.com` with the template saved within `./templates/email.html` relative to the current working directory (check with ```bash pwd```).
This is to also send a pdf attachment within the example directory relative to the root directory of this repository.
```bash
-email-sender single-email --to-addr "minamatta98@gmail.com" --subject "Email Testing CLI" --email-template "./templates/email.html" --attachment-1-path "./example/rust.pdf"
+email-sender single-email --to-addr "minamatta98@gmail.com" --subject "Email Testing CLI" --email-template "./templates/email.html" attachments --attachment-1-path "./example/rust.pdf"
```
-##### Scenario 3:
+#### Scenario 3
Send an email to `minamatta98@gmail.com` with the template saved within `./templates/email.html` relative to the current working directory (check with ```bash pwd```).
-This is to also send an inline email attachment located within `./example/send_mail_7590.png` corrosponding to an inline content id of 2335.
+This is to also send an inline email attachment located within `./example/send_mail_7590.png` corresponding to an inline content id of 2335.
```bash
-email-sender single-email --to-addr "minamatta98@gmail.com" --subject "Email Testing CLI" --email-template "./templates/email.html" --attachment-1-path "./example/send_mail_7590.png" --attachment-1-inline-content-id 2335
-```
+email-sender single-email --to-addr "minamatta98@gmail.com" --subject "Email Testing CLI" --email-template "./templates/email.html" attachments --attachment-1-path "./example/send-mail-7590.svg" --attachment-1-inline-content-id 2335```
@@ -107,13 +101,14 @@ email-sender single-email --to-addr "minamatta98@gmail.com" --subject "Email Tes
-#### Send Bulk Emails
+### Send Bulk Emails
---
All three scenarios are listed within their respective order within the following table.
-This will corrospond to the following csv file:
+This will correspond to the following csv file:
-_Note that unfilled fields must still be comma seperated_
+> _Note that unfilled fields must still be comma separated._
+> _Also note that attachment and substitution headers can be omitted where not needed_
```csv
DeliveryAddress,Subject,RelativeEmailTemplatePath,Attachment1Path,Attachment1InlineContentId
@@ -128,3 +123,47 @@ To send bulk emails from a csv file saved within `./example/example.csv`, run th
email-sender bulk-email --csv-file "./example/example.csv"
```
+
+
+
+### Template Variable Substitution
+---
+The following variables can be used within an email-template and encoded as `{{field name}}` to be replaced:
+
+| Field Name | Description |Csv Header |
+|----------------------|------------------------------------------------------------------------------------------------------| ----------|
+| `name` | Replace instance of `{{name}}` within email-template to `--name` value |Name|
+| `email` | Replace instance of `{{email}}` within email-template to `--email` value |Email|
+| `date` | Replace instance of `{{date}}` within email-template to `--date` value |Date|
+| `time` | Replace instance of `{{time}}` within email-template to `--time` value |Time|
+| `order_number` | Replace instance of `{{order_number}}` within email-template to `--order-number` value |OrderNumber|
+| `product_information`| Replace instance of `{{product_information}}` within email-template to `--product-information` value| ProductInformation |
+| `location` | Replace instance of `{{location}}` within email-template to `--location` value |Location|
+| `username` | Replace instance of `{{user_name}}` within email-template to `--user-name` value |Username|
+| `confirmation_link` | Replace instance of `{{confirmation_link}}` within email-template to `--confirmation-link` value |ConfirmationLink|
+| `password_reset_link`| Replace instance of `{{password_reset_link}}` within email-template to `--password-reset-link` value |PasswordResetLink|
+| `discount_code` | Replace instance of `{{discount_code}}` within email-template to `--discount-code` value |DiscountCode|
+| `temp_code` | Replace instance of `{{temp_code}}` within email-template to `--temp-code` value |TempCode|
+| `course_details` | Replace instance of `{{course_details}}` within email-template to `--course-details` value |CourseDetails|
+
+
+
+#### Single Email Substitution Example
+In this example, instances of `{{name}}` within the email-template will be replaced with Mina and instances of ``{{temp_code}}`` will be replaced with 123456
+
+```bash
+cargo run --release -- single-email --to-addr "minamatta98@gmail.com" --subject "Email Testing CLI" --email-template "./templates/test.html" attachments --attachment-1-path "./example/send-mail-7590.svg" --attachment-1-inline-content-id 2335 token --name "Mina" --temp-code 123456
+```
+
+
+
+#### Bulk Email Substitution Example
+The following example accomplishes the same function as the [single email substitution example](#single-email-substitution-example).
+
+> _Note that variables are evaluated separately for each row entry and can be left blank if not needed._
+> _Also note that field names for substitutions can be left empty if not needed. For example, the Name and TempCode header are not required if values are not passed._
+
+```csv
+DeliveryAddress,Subject,RelativeEmailTemplatePath,Attachment1Path,Attachment1InlineContentId,Name,TempCode
+minamatta98@gmail.com,Email Template Tests,./templates/replacement_test.html,./example/send_mail_7590.png,2335,Mina,123456
+```
diff --git a/src/cli.rs b/src/cli.rs
index 0116e93..6763564 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -82,7 +82,7 @@ macro_rules! commands_struct {
#[serde(flatten)]
#[command(subcommand)]
- replacement_tokens: ReplacementTokens,
+ replacement_tokens: Option,
},
}
}
@@ -125,7 +125,7 @@ pub struct EmailInfo {
/// Optional Inline File Attachment
#[serde(flatten)]
#[command(subcommand)]
- pub attachment: AttachmentCommand,
+ pub attachment: Option,
}
commands_struct!(10);
@@ -148,7 +148,7 @@ mod test {
attachment_1_path,
attachment_1_inline_content_id,
..
- } = record.attachment;
+ } = record.attachment.unwrap();
assert!(attachment_1_path.is_some());
assert!(attachment_1_inline_content_id.is_some());
diff --git a/src/email.rs b/src/email.rs
index 1253e35..388c943 100644
--- a/src/email.rs
+++ b/src/email.rs
@@ -54,7 +54,7 @@ macro_rules! email_struct {
subject: String,
email_body_location: PathBuf,
#[serde(flatten)]
- attachment: AttachmentCommand,
+ attachment: Option,
}
impl Email {
@@ -63,7 +63,7 @@ macro_rules! email_struct {
delivery_address: String,
subject: String,
email_body_location: PathBuf,
- attachment: AttachmentCommand,
+ attachment: Option,
) -> Self {
Email {
delivery_address,
@@ -129,46 +129,60 @@ macro_rules! email_struct {
let mut email = std::fs::read_to_string(email_body_location)?;
+ let mut multi_part: MultiPart;
+
#[allow(clippy::collapsible_match)]
- let AttachmentCommand::Attachments {
+ if let Some(AttachmentCommand::Attachments {
$(
[],
[],
)*
replacement_tokens
+ })
+ = attachment {
+
+ if let Some(replacement_tokens) = replacement_tokens {
+ replacement_tokens.replace_all_substrings(&mut email);
+ }
+
+ multi_part = MultiPart::related().singlepart(
+ SinglePart::builder()
+ .header(header::ContentType::TEXT_HTML)
+ .body(email),
+ );
+
+
+
+ $(
+ if let Some([]) = [] && &[].display().to_string() != "" {
+ let attachment = if let Some([]) = [] && [] != String::new() {
+ Attachment::new_inline(
+ [].to_string().replace('"', "")
+ )
+ .body(
+ std::fs::read(&[< attachment_ $no _path>])?,
+ ContentType::parse(&mime_guess::from_path([< attachment_ $no _path>]).first().unwrap().to_string())?,
+ )
+
+ } else {
+ Attachment::new([< attachment_ $no _path>].file_name().unwrap().to_str().unwrap().to_string())
+ .body(
+ std::fs::read(&[< attachment_ $no _path>])?,
+ ContentType::parse(&mime_guess::from_path([< attachment_ $no _path>]).first().unwrap().to_string())?,
+ )
+
+ };
+ multi_part = multi_part.singlepart(attachment);
+ };
+ )*
+
+ } else {
+ multi_part = MultiPart::related().singlepart(
+ SinglePart::builder()
+ .header(header::ContentType::TEXT_HTML)
+ .body(email),
+ );
}
- = attachment;
-
- replacement_tokens.replace_all_substrings(&mut email);
-
- let mut multi_part = MultiPart::related().singlepart(
- SinglePart::builder()
- .header(header::ContentType::TEXT_HTML)
- .body(email),
- );
-
- $(
- if let Some([]) = [] && &[].display().to_string() != "" {
- let attachment = if let Some([]) = [] && [] != String::new() {
- Attachment::new_inline(
- [].as_number().unwrap().to_string()
- )
- .body(
- std::fs::read(&[< attachment_ $no _path>])?,
- ContentType::parse(&mime_guess::from_path([< attachment_ $no _path>]).first().unwrap().to_string())?,
- )
-
- } else {
- Attachment::new([< attachment_ $no _path>].file_name().unwrap().to_str().unwrap().to_string())
- .body(
- std::fs::read(&[< attachment_ $no _path>])?,
- ContentType::parse(&mime_guess::from_path([< attachment_ $no _path>]).first().unwrap().to_string())?,
- )
-
- };
- multi_part = multi_part.singlepart(attachment);
- };
- )*
let email = Message::builder()
.from(from_addr.parse()?)
diff --git a/src/tokens.rs b/src/tokens.rs
index 56f9ef2..07d9d4a 100644
--- a/src/tokens.rs
+++ b/src/tokens.rs
@@ -172,9 +172,9 @@ mod test {
let AttachmentCommand::Attachments {
replacement_tokens, ..
- } = record.attachment;
+ } = record.attachment.unwrap();
- let ReplacementTokens::Token { replacement_tokens } = replacement_tokens;
+ let ReplacementTokens::Token { replacement_tokens } = replacement_tokens.unwrap();
replace_html_file_substrings(replacement_tokens)?;
}