From 8ff3f8056b705d6401aa72b8809e9e897a458378 Mon Sep 17 00:00:00 2001 From: veeso Date: Fri, 29 Sep 2023 10:54:46 +0200 Subject: [PATCH] initial commit --- .env | 0 .env.test | 2 + .gitignore | 2 + CONTRIBUTING.md | 101 ----- Cargo.lock | 967 ++++++++++++++++++++++------------------ Cargo.toml | 34 +- README.md | 117 +++-- assets/body_example.txt | 1 + src/aws_ses.rs | 52 +++ src/config.rs | 5 +- src/main.rs | 37 +- src/test.rs | 3 + src/web/email.rs | 56 +++ src/web/health_check.rs | 22 +- src/web/mod.rs | 26 +- 15 files changed, 764 insertions(+), 661 deletions(-) delete mode 100644 .env delete mode 100644 CONTRIBUTING.md create mode 100644 assets/body_example.txt create mode 100644 src/aws_ses.rs create mode 100644 src/test.rs create mode 100644 src/web/email.rs diff --git a/.env b/.env deleted file mode 100644 index e69de29..0000000 diff --git a/.env.test b/.env.test index e69de29..73b88c7 100644 --- a/.env.test +++ b/.env.test @@ -0,0 +1,2 @@ +EMAIL_SENDER=test@test.com +WEB_PORT=3000 diff --git a/.gitignore b/.gitignore index b630a4c..adbd5c0 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ target/ # MSVC Windows builds of rustc generate these, which store debugging information *.pdb + +.env diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index b252bdb..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,101 +0,0 @@ -# Contributing - -- [Contributing](#contributing) - - [Open an issue](#open-an-issue) - - [Questions](#questions) - - [Bug reports](#bug-reports) - - [Feature requests](#feature-requests) - - [Preferred contributions](#preferred-contributions) - - [Pull Request Process](#pull-request-process) - - [Software guidelines](#software-guidelines) - ---- - -## Open an issue - -Open an issue when: - -- You have questions or concerns regarding the project or the application itself. -- You have a bug to report. -- You have a feature or a suggestion to improve tui-realm to submit. - -### Questions - -If you have a question open an issue using the `Question` template. -By default your question should already be labeled with the `question` label, if you need help with your installation, please also add the `help wanted` label. -Check the issue is always assigned to `veeso`. - -### Bug reports - -If you want to report an issue or a bug you've encountered while using tui-realm, open an issue using the `Bug report` template. -The `Bug` label should already be set and the issue should already be assigned to `veeso`. -Don't set other labels to your issue, not even priority. - -When you open a bug try to be the most precise as possible in describing your issue. I'm not saying you should always be that precise, since sometimes it's very easy for maintainers to understand what you're talking about. Just try to be reasonable to understand sometimes we might not know what you're talking about or we just don't have the technical knowledge you might think. -Please always provide the environment you're working on and consider I only offer support for the latest release of the library. -Last but not least: the template I've written must be used. Full stop. - -Maintainers will may add additional labels to your issue: - -- **duplicate**: the issue is duplicated; the reference to the related issue will be added to your description. Your issue will be closed. -- **priority**: this must be fixed asap -- **sorcery**: it is not possible to find out what's causing your bug, nor is reproducible on our test environments. -- **wontfix**: your bug has a very high ratio between the probability to encounter it and the difficult to fix it, or it just isn't a bug, but a feature. - -### Feature requests - -Whenever you have a good idea which chould improve the project, it is a good idea to submit it to the project owner. -The first thing you should do though, is not starting to write the code, but is to become concern about how tui-realm works, what kind -of contribution I appreciate and what kind of contribution I won't consider. -Said so, follow these steps: - -- Read the contributing guidelines, entirely -- Think on whether your idea would fit in the project mission and guidelines or not -- Think about the impact your idea would have on the project -- Open an issue using the `feature request` template describing with accuracy your suggestion -- Wait for the maintainer feedback on your idea - -It is very important to follow these steps, since it will prevent you from working on a feature that will be rejected and trust me, none of us wants to deal with this situation. - -Always mind that your suggestion, may be rejected: I'll always provide a feedback on the reasons that brought me to reject your feature, just try not to get mad about that. - ---- - -## Preferred contributions - -At the moment, these kind of contributions are more appreciated and should be preferred: - -- Fix for issues described in [Known Issues](./README.md#known-issues-) or [issues reported by the community](https://github.com/veeso-dev/ozone/issues) -- Code optimizations: any optimization to the code is welcome - -For any other kind of contribution, especially for new features, please submit a new issue first. - -## Pull Request Process - -Let's make it simple and clear: - -1. Open a PR with an **appropriate label** (e.g. bug, enhancement, ...). -2. Write a **properly documentation** for your software compliant with **rustdoc** standard. -3. Write tests for your code -4. Check your code with `cargo clippy`. -5. Check if the CI for your commits reports three-green. -6. Report changes to the PR you opened, writing a report of what you changed and what you have introduced. -7. Update the `CHANGELOG.md` file with details of changes to the application. In changelog report changes under a chapter called `PR{PULL_REQUEST_NUMBER}` (e.g. PR12). -8. Assign a maintainer to the reviewers. -9. Request maintainers to merge your changes. - -### Software guidelines - -In addition to the process described for the PRs, I've also decided to introduce a list of guidelines to follow when writing the code, that should be followed: - -1. **Let's stop the NPM apocalypse**: personally I'm against the abuse of dependencies we make in software projects and I think that NodeJS has opened the way to this drama (and has already gone too far). Nowadays nobody cares about adding hundreds of dependencies to their projects. Don't misunderstand me: I think that package managers are cool, but I'm totally against the abuse we're making of them. I think when we work on a project, we should try to use the minor quantity of dependencies as possible, especially because it's not hard to see how many libraries are getting abandoned right now, causing compatibility issues after a while. So please, when working on tui-realm, try not to add useless dependencies. -2. **No C-bindings**: personally I think that Rust still relies too much on C. And that's bad, really bad. Many libraries in Rust are just wrappers to C libraries, which is a huge problem, especially considering this is a multiplatform project. Everytime you add a C-binding to your project, you're forcing your users to install additional libraries to their systems. Sometimes these libraries are already installed on their systems (as happens for libssh2 or openssl in this case), but sometimes not. So if you really have to add a dependency to this project, please AVOID completely adding C-bounded libraries. -3. **Test units matter**: Whenever you implement something new to this project, always implement test units which cover the most cases as possible. -4. **Comments are useful**: Many people say that the code should be that simple to talk by itself about what it does, and comments should then be useless. I personally don't agree. I'm not saying they're wrong, but I'm just saying that this approach has, in my personal opinion, many aspects which are underrated: - 1. What's obvious for me, might not be for the others. - 2. Our capacity to work on a code depends mostly on **time and experience**, not on complexity: I'm not denying complexity matter, but the most decisive factor when working on code is the experience we've acquired working on it and the time we've spent. As the author of the project, I know the project like the back of my hands, but if I didn't work on it for a year, then I would probably have some problems in working on it again as the same speed as before. And do you know what's really time-saving in these cases? Comments. - ---- - -Thank you for any contribution! -Christian Visintin diff --git a/Cargo.lock b/Cargo.lock index 2327c9c..717efbe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -68,44 +68,6 @@ dependencies = [ "syn 2.0.27", ] -[[package]] -name = "actix-multipart" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee489e3c01eae4d1c35b03c4493f71cb40d93f66b14558feb1b1a807671cc4e" -dependencies = [ - "actix-multipart-derive", - "actix-utils", - "actix-web", - "bytes", - "derive_more", - "futures-core", - "futures-util", - "httparse", - "local-waker", - "log", - "memchr", - "mime", - "serde", - "serde_json", - "serde_plain", - "tempfile", - "tokio", -] - -[[package]] -name = "actix-multipart-derive" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ec592f234db8a253cf80531246a4407c8a70530423eea80688a6c5a44a110e7" -dependencies = [ - "darling 0.14.4", - "parse-size", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "actix-router" version = "0.5.1" @@ -125,6 +87,7 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15265b6b8e2347670eb363c47fc8c75208b4a4994b27192f345fcbe707804f3e" dependencies = [ + "actix-macros", "futures-core", "tokio", ] @@ -284,31 +247,360 @@ dependencies = [ ] [[package]] -name = "android-tzdata" -version = "0.1.1" +name = "anyhow" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" +checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" [[package]] -name = "android_system_properties" -version = "0.1.5" +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "aws-config" +version = "0.56.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +checksum = "fc6b3804dca60326e07205179847f17a4fce45af3a1106939177ad41ac08a6de" dependencies = [ - "libc", + "aws-credential-types", + "aws-http", + "aws-sdk-sso", + "aws-sdk-sts", + "aws-smithy-async", + "aws-smithy-client", + "aws-smithy-http", + "aws-smithy-http-tower", + "aws-smithy-json", + "aws-smithy-types", + "aws-types", + "bytes", + "fastrand", + "hex", + "http", + "hyper", + "ring", + "time", + "tokio", + "tower", + "tracing", + "zeroize", ] [[package]] -name = "anyhow" -version = "1.0.72" +name = "aws-credential-types" +version = "0.56.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" +checksum = "70a66ac8ef5fa9cf01c2d999f39d16812e90ec1467bd382cbbb74ba23ea86201" +dependencies = [ + "aws-smithy-async", + "aws-smithy-types", + "fastrand", + "tokio", + "tracing", + "zeroize", +] [[package]] -name = "autocfg" -version = "1.1.0" +name = "aws-http" +version = "0.56.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "3e626370f9ba806ae4c439e49675fd871f5767b093075cdf4fef16cac42ba900" +dependencies = [ + "aws-credential-types", + "aws-smithy-http", + "aws-smithy-types", + "aws-types", + "bytes", + "http", + "http-body", + "lazy_static", + "percent-encoding", + "pin-project-lite", + "tracing", +] + +[[package]] +name = "aws-runtime" +version = "0.56.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07ac5cf0ff19c1bca0cea7932e11b239d1025a45696a4f44f72ea86e2b8bdd07" +dependencies = [ + "aws-credential-types", + "aws-http", + "aws-sigv4", + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "fastrand", + "http", + "percent-encoding", + "tracing", + "uuid", +] + +[[package]] +name = "aws-sdk-sesv2" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a639c7e86623edb8573203a87939fae2e4903503f7306454efac4e8a579a3ac" +dependencies = [ + "aws-credential-types", + "aws-http", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-client", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "http", + "regex", + "tokio-stream", + "tracing", +] + +[[package]] +name = "aws-sdk-sso" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "903f888ff190e64f6f5c83fb0f8d54f9c20481f1dc26359bb8896f5d99908949" +dependencies = [ + "aws-credential-types", + "aws-http", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-client", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "http", + "regex", + "tokio-stream", + "tracing", +] + +[[package]] +name = "aws-sdk-sts" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47ad6bf01afc00423d781d464220bf69fb6a674ad6629cbbcb06d88cdc2be82" +dependencies = [ + "aws-credential-types", + "aws-http", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-client", + "aws-smithy-http", + "aws-smithy-json", + "aws-smithy-query", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-smithy-xml", + "aws-types", + "http", + "regex", + "tracing", +] + +[[package]] +name = "aws-sigv4" +version = "0.56.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7b28f4910bb956b7ab320b62e98096402354eca976c587d1eeccd523d9bac03" +dependencies = [ + "aws-smithy-http", + "form_urlencoded", + "hex", + "hmac", + "http", + "once_cell", + "percent-encoding", + "regex", + "sha2", + "time", + "tracing", +] + +[[package]] +name = "aws-smithy-async" +version = "0.56.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cdb73f85528b9d19c23a496034ac53703955a59323d581c06aa27b4e4e247af" +dependencies = [ + "futures-util", + "pin-project-lite", + "tokio", + "tokio-stream", +] + +[[package]] +name = "aws-smithy-client" +version = "0.56.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c27b2756264c82f830a91cb4d2d485b2d19ad5bea476d9a966e03d27f27ba59a" +dependencies = [ + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-http-tower", + "aws-smithy-types", + "bytes", + "fastrand", + "http", + "http-body", + "hyper", + "hyper-rustls", + "lazy_static", + "pin-project-lite", + "rustls", + "tokio", + "tower", + "tracing", +] + +[[package]] +name = "aws-smithy-http" +version = "0.56.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54cdcf365d8eee60686885f750a34c190e513677db58bbc466c44c588abf4199" +dependencies = [ + "aws-smithy-types", + "bytes", + "bytes-utils", + "futures-core", + "http", + "http-body", + "hyper", + "once_cell", + "percent-encoding", + "pin-project-lite", + "pin-utils", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "aws-smithy-http-tower" +version = "0.56.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "822de399d0ce62829a69dfa8c5cd08efdbe61a7426b953e2268f8b8b52a607bd" +dependencies = [ + "aws-smithy-http", + "aws-smithy-types", + "bytes", + "http", + "http-body", + "pin-project-lite", + "tower", + "tracing", +] + +[[package]] +name = "aws-smithy-json" +version = "0.56.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1e7ab8fa7ad10c193af7ae56d2420989e9f4758bf03601a342573333ea34f" +dependencies = [ + "aws-smithy-types", +] + +[[package]] +name = "aws-smithy-query" +version = "0.56.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28556a3902091c1f768a34f6c998028921bdab8d47d92586f363f14a4a32d047" +dependencies = [ + "aws-smithy-types", + "urlencoding", +] + +[[package]] +name = "aws-smithy-runtime" +version = "0.56.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "745e096b3553e7e0f40622aa04971ce52765af82bebdeeac53aa6fc82fe801e6" +dependencies = [ + "aws-smithy-async", + "aws-smithy-client", + "aws-smithy-http", + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "fastrand", + "http", + "http-body", + "once_cell", + "pin-project-lite", + "pin-utils", + "tokio", + "tracing", +] + +[[package]] +name = "aws-smithy-runtime-api" +version = "0.56.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d0ae0c9cfd57944e9711ea610b48a963fb174a53aabacc08c5794a594b1d02" +dependencies = [ + "aws-smithy-async", + "aws-smithy-http", + "aws-smithy-types", + "bytes", + "http", + "tokio", + "tracing", +] + +[[package]] +name = "aws-smithy-types" +version = "0.56.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d90dbc8da2f6be461fa3c1906b20af8f79d14968fe47f2b7d29d086f62a51728" +dependencies = [ + "base64-simd", + "itoa", + "num-integer", + "ryu", + "serde", + "time", +] + +[[package]] +name = "aws-smithy-xml" +version = "0.56.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01d2dedcdd8023043716cfeeb3c6c59f2d447fce365d8e194838891794b23b6" +dependencies = [ + "xmlparser", +] + +[[package]] +name = "aws-types" +version = "0.56.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85aa0451bf8af1bf22a4f028d5d28054507a14be43cb8ac0597a8471fba9edfe" +dependencies = [ + "aws-credential-types", + "aws-smithy-async", + "aws-smithy-client", + "aws-smithy-http", + "aws-smithy-types", + "http", + "rustc_version", + "tracing", +] [[package]] name = "backtrace" @@ -331,6 +623,16 @@ version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +[[package]] +name = "base64-simd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" +dependencies = [ + "outref", + "vsimd", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -375,9 +677,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "bytes" @@ -385,6 +687,16 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +[[package]] +name = "bytes-utils" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e47d3a8076e283f3acd27400535992edb3ba4b5bb72f8891ad8fbe7932a7d4b9" +dependencies = [ + "bytes", + "either", +] + [[package]] name = "bytestring" version = "1.3.0" @@ -409,19 +721,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "chrono" -version = "0.4.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "num-traits", - "serde", - "winapi", -] - [[package]] name = "convert_case" version = "0.4.0" @@ -483,76 +782,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "darling" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" -dependencies = [ - "darling_core 0.14.4", - "darling_macro 0.14.4", -] - -[[package]] -name = "darling" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" -dependencies = [ - "darling_core 0.20.3", - "darling_macro 0.20.3", -] - -[[package]] -name = "darling_core" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 1.0.109", -] - -[[package]] -name = "darling_core" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.27", -] - -[[package]] -name = "darling_macro" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" -dependencies = [ - "darling_core 0.14.4", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "darling_macro" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" -dependencies = [ - "darling_core 0.20.3", - "quote", - "syn 2.0.27", -] - [[package]] name = "derive_more" version = "0.99.17" @@ -580,8 +809,15 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", + "subtle", ] +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + [[package]] name = "encoding_rs" version = "0.8.32" @@ -636,9 +872,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "flate2" @@ -656,21 +892,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.0" @@ -796,6 +1017,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "http" version = "0.2.9" @@ -861,61 +1091,21 @@ dependencies = [ ] [[package]] -name = "hyper-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" -dependencies = [ - "futures-util", - "http", - "hyper", - "rustls", - "tokio", - "tokio-rustls", -] - -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes", - "hyper", - "native-tls", - "tokio", - "tokio-native-tls", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" +name = "hyper-rustls" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" dependencies = [ - "cc", + "futures-util", + "http", + "hyper", + "log", + "rustls", + "rustls-native-certs", + "tokio", + "tokio-rustls", ] -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - [[package]] name = "idna" version = "0.4.0" @@ -934,15 +1124,8 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown", - "serde", ] -[[package]] -name = "ipnet" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" - [[package]] name = "is-terminal" version = "0.4.9" @@ -1069,24 +1252,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -1097,6 +1262,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.16" @@ -1131,32 +1306,6 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" -[[package]] -name = "openssl" -version = "0.10.55" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.27", -] - [[package]] name = "openssl-probe" version = "0.1.5" @@ -1164,16 +1313,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] -name = "openssl-sys" -version = "0.9.90" +name = "outref" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] +checksum = "4030760ffd992bef45b0ae3f10ce1aba99e33464c90d14dd7c039884963ddc7a" [[package]] name = "overload" @@ -1204,12 +1347,6 @@ dependencies = [ "windows-targets", ] -[[package]] -name = "parse-size" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "944553dd59c802559559161f9816429058b869003836120e262e8caec061b7ae" - [[package]] name = "paste" version = "1.0.14" @@ -1222,6 +1359,26 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +[[package]] +name = "pin-project" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.27", +] + [[package]] name = "pin-project-lite" version = "0.2.10" @@ -1342,48 +1499,6 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" -[[package]] -name = "reqwest" -version = "0.11.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" -dependencies = [ - "base64", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-rustls", - "hyper-tls", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "tokio", - "tokio-native-tls", - "tokio-rustls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots", - "winreg", -] - [[package]] name = "ring" version = "0.16.20" @@ -1399,27 +1514,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "rust-template" -version = "0.1.0" -dependencies = [ - "actix-multipart", - "actix-web", - "anyhow", - "env_logger", - "envy", - "lazy_static", - "pretty_assertions", - "reqwest", - "serde", - "serde_json", - "serde_with", - "thiserror", - "tokio", - "tracing", - "tracing-subscriber", -] - [[package]] name = "rustc-demangle" version = "0.1.23" @@ -1450,9 +1544,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.5" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79ea77c539259495ce8ca47f53e66ae0330a8819f67e23ac96ca02f50e7b7d36" +checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" dependencies = [ "log", "ring", @@ -1460,6 +1554,18 @@ dependencies = [ "sct", ] +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", +] + [[package]] name = "rustls-pemfile" version = "1.0.3" @@ -1471,9 +1577,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.101.1" +version = "0.101.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15f36a6828982f422756984e47912a7a51dcbc2a197aa791158f8ca61cd8204e" +checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe" dependencies = [ "ring", "untrusted", @@ -1570,15 +1676,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_plain" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6018081315db179d0ce57b1fe4b62a12a0028c9cf9bbef868c9cf477b3c34ae" -dependencies = [ - "serde", -] - [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -1592,38 +1689,41 @@ dependencies = [ ] [[package]] -name = "serde_with" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e47d95bc83ed33b2ecf84f4187ad1ab9685d18ff28db000c99deac8ce180e3" +name = "sesamo" +version = "0.1.0" dependencies = [ + "actix-rt", + "actix-web", + "anyhow", + "aws-config", + "aws-sdk-sesv2", "base64", - "chrono", - "hex", - "indexmap", + "env_logger", + "envy", + "pretty_assertions", "serde", "serde_json", - "serde_with_macros", - "time", + "thiserror", + "tracing", + "tracing-subscriber", ] [[package]] -name = "serde_with_macros" -version = "3.1.0" +name = "sha1" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea3cee93715c2e266b9338b7544da68a9f24e227722ba482bd1c024367c77c65" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ - "darling 0.20.3", - "proc-macro2", - "quote", - "syn 2.0.27", + "cfg-if", + "cpufeatures", + "digest", ] [[package]] -name = "sha1" -version = "0.10.5" +name = "sha2" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -1680,10 +1780,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] -name = "strsim" -version = "0.10.0" +name = "subtle" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" @@ -1707,19 +1807,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "tempfile" -version = "3.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5486094ee78b2e5038a6382ed7645bc084dc2ec433426ca4c3cb61e2007b8998" -dependencies = [ - "cfg-if", - "fastrand", - "redox_syscall", - "rustix", - "windows-sys", -] - [[package]] name = "termcolor" version = "1.2.0" @@ -1820,22 +1907,23 @@ dependencies = [ ] [[package]] -name = "tokio-native-tls" -version = "0.3.1" +name = "tokio-rustls" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "native-tls", + "rustls", "tokio", ] [[package]] -name = "tokio-rustls" -version = "0.24.1" +name = "tokio-stream" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" dependencies = [ - "rustls", + "futures-core", + "pin-project-lite", "tokio", ] @@ -1853,6 +1941,28 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -1969,16 +2079,22 @@ dependencies = [ ] [[package]] -name = "valuable" -version = "0.1.0" +name = "urlencoding" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + +[[package]] +name = "uuid" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" [[package]] -name = "vcpkg" -version = "0.2.15" +name = "valuable" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "version_check" @@ -1986,6 +2102,12 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "vsimd" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" + [[package]] name = "want" version = "0.3.1" @@ -2026,18 +2148,6 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "wasm-bindgen-macro" version = "0.2.87" @@ -2077,25 +2187,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "webpki-roots" -version = "0.22.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" -dependencies = [ - "webpki", -] - [[package]] name = "winapi" version = "0.3.9" @@ -2127,15 +2218,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" -dependencies = [ - "windows-targets", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -2203,13 +2285,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] -name = "winreg" -version = "0.10.1" +name = "xmlparser" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" -dependencies = [ - "winapi", -] +checksum = "4d25c75bf9ea12c4040a97f829154768bbbce366287e2dc044af160cd79a13fd" [[package]] name = "yansi" @@ -2217,6 +2296,12 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" + [[package]] name = "zstd" version = "0.12.4" diff --git a/Cargo.toml b/Cargo.toml index 064cfa4..ee2d4d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,44 +1,36 @@ [package] -name = "rust-template" +name = "sesamo" version = "0.1.0" authors = ["Christian Visintin "] edition = "2021" categories = ["network-programming"] description = "" -homepage = "https://github.com/veeso-dev/rust-template" +homepage = "https://github.com/veeso-dev/sesamo" include = ["src/**/*", "LICENSE", "README.md", "CHANGELOG.md"] keywords = [] license = "MIT" readme = "README.md" -repository = "https://github.com/veeso-dev/rust-template" +repository = "https://github.com/veeso-dev/sesamo" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [[bin]] -name = "rust-template" +name = "sesamo" path = "src/main.rs" [dependencies] +aws-config = "0.56" +aws-sdk-sesv2 = "0.31" +actix-web = "^4" anyhow = "^1" +base64 = "^0.21" envy = "^0.4" -lazy_static = "^1.4" -serde = { version = "^1.0.0", features = ["derive"] } -thiserror = "^1.0" - -#actix -actix-multipart = "^0.6" -actix-web = "^4" - -#async stuff -reqwest = { version = "^0.11", features = ["rustls-tls"] } -serde_json = "^1.0.0" -serde_with = "^3" -tokio = { version = "^1", features = ["io-std", "net", "fs"] } +serde = { version = "^1", features = ["derive"] } +serde_json = "^1" +thiserror = "^1" tracing = "^0.1" tracing-subscriber = "^0.3" [dev-dependencies] +actix-rt = "^2" env_logger = "^0.10" -pretty_assertions = "^1.0.0" - -[features] -with-containers = [] +pretty_assertions = "^1" diff --git a/README.md b/README.md index e6331f3..9a0d69b 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,7 @@ -# Rust-template +# sesamo -

~ ~

-

- Get started - · - Crates.io -

Developed by @veeso

-

Current version: 0.1.0 (26/06/2023)

+

Current version: 0.1.0 (29/09/2023)

- Repo stars - Downloads counter - Latest version - - Ko-fi

- Linux CI

--- -- [Rust-template](#rust-template) - - [About rust-template](#about-rust-template) +- [sesamo](#sesamo) + - [About sesamo](#about-sesamo) - [Get started](#get-started) - - [Run with docker](#run-with-docker) - - [rust-template API](#rust-template-api) + - [Setup env](#setup-env) + - [Setup AWS credentials](#setup-aws-credentials) + - [Run with Cargo make](#run-with-cargo-make) + - [sesamo API](#sesamo-api) - [Check](#check) - - [Support the developer](#support-the-developer) - - [Contributing and issues](#contributing-and-issues) + - [Send](#send) - [Changelog](#changelog) - [License](#license) --- -## About rust-template +## About sesamo -rust-template is a Rust web service which comes integrated with ClamAV. The service provides an API endpoint to scan files with ClamAV. +sesamo is a Rust web service which exposes an endpoint to send custom email to custom recipients. --- ## Get started -### Run with docker - -The entire rust-template web service comes with a docker compose file to easily run the service on your machine. -Just run: +### Setup env ```sh -docker-compose build -docker-compose up -d +cp .env.test .env +vim .env ``` -At this point rust-template will be served on the specified port in the docker-compose file. (Default: `3010`) +```env +EMAIL_SENDER=EMAIL_ADDRESS_CONFIGURED_TO_AWS_SES +WEB_PORT=3001 +``` -## rust-template API +### Setup AWS credentials -### Check +AWS credentials must be configured with aws-cli with `aws configure`. +Credentials are then automatically loaded from defined profile -Check web service status: +### Run with Cargo make -```txt -GET /check +```sh +cargo make -p production run ``` -Response: +## sesamo API -```json -{ - "status": "ok" -} -``` +### Check ---- +Check web service status: -## Support the developer +```txt +GET /check +``` -If you like rust-template and you're grateful for the work I've done, please consider a little donation 🥳 +Response: Empty (200) -You can make a donation with one of these platforms: +### Send -[![ko-fi](https://img.shields.io/badge/Ko--fi-F16061?style=for-the-badge&logo=ko-fi&logoColor=white)](https://ko-fi.com/veeso) -[![PayPal](https://img.shields.io/badge/PayPal-00457C?style=for-the-badge&logo=paypal&logoColor=white)](https://www.paypal.me/chrisintin) +Send email to recipients with provided subject and body ---- +```txt +POST /send +``` -## Contributing and issues +Body: -Contributions, bug reports, new features and questions are welcome! 😉 -If you have any question or concern, or you want to suggest a new feature, or you want just want to improve pavao, feel free to open an issue or a PR. +```json +{ + "recipients": ["test@test.com", "foo@bar.com"], + "subject": "email subject", + "body": "BODY BASE64 ENCODED" +} +``` -Please follow [our contributing guidelines](CONTRIBUTING.md) +Response: Empty (200) --- ## Changelog -View rust-template's changelog [HERE](CHANGELOG.md) +View sesamo's changelog [HERE](CHANGELOG.md) --- ## License -rust-template is licensed under the MIT license. +sesamo is licensed under the MIT license. You can read the entire license [HERE](LICENSE) diff --git a/assets/body_example.txt b/assets/body_example.txt new file mode 100644 index 0000000..6be8b98 --- /dev/null +++ b/assets/body_example.txt @@ -0,0 +1 @@ +PCFET0NUWVBFIGh0bWw+CjxodG1sPgoKPGhlYWQ+CiAgCiAgPHN0eWxlPgogICAgYm9keSB7CiAgICAgIGZvbnQtZmFtaWx5OiBzYW5zLXNlcmlmOwogICAgICBtaW4td2lkdGg6IDEwMHZ3OwogICAgICBvdmVyZmxvdy14OiBoaWRkZW47CiAgICB9CgogICAgcCB7CiAgICAgIGZvbnQtd2VpZ2h0OiAzMDA7CiAgICB9CgogICAgdGV4dGFyZWEgewogICAgICBmb250LWZhbWlseTogc2Fucy1zZXJpZjsKICAgIH0KCiAgICBoMSwKICAgIGgyLAogICAgaDMsCiAgICBoNCwKICAgIGg1LAogICAgaDYgewogICAgICBjb2xvcjogIzMxMzYzYjsKICAgICAgbWFyZ2luLXRvcDogMDsKICAgICAgbWFyZ2luLWJvdHRvbTogMC41cmVtOwogICAgfQoKICAgIGJ1dHRvbiB7CiAgICAgIGJveC1zaXppbmc6IGJvcmRlci1ib3g7CiAgICAgIGN1cnNvcjogcG9pbnRlcjsKICAgIH0KCiAgICBidXR0b24sCiAgICBpbnB1dCB7CiAgICAgIG1hcmdpbjogMDsKICAgICAgZm9udC1mYW1pbHk6IGluaGVyaXQ7CiAgICAgIGZvbnQtc2l6ZTogaW5oZXJpdDsKICAgICAgbGluZS1oZWlnaHQ6IGluaGVyaXQ7CiAgICB9CgogICAgLmxvZ28gewogICAgICBwYWRkaW5nOiAwLjVyZW07CiAgICB9CgogICAgLmxvZ28gaW1nIHsKICAgICAgaGVpZ2h0OiAxMjhweDsKICAgICAgd2lkdGg6IDEyOHB4OwogICAgfQoKICAgIC5jb250YWN0IGEgewogICAgICBjb2xvcjogIzMxMzYzYjsKICAgICAgZm9udC13ZWlnaHQ6IDMwMDsKICAgICAgdGV4dC1kZWNvcmF0aW9uOiB1bmRlcmxpbmU7CiAgICB9CgogICAgLmNvbnRhY3Q6aG92ZXIgewogICAgICBjb2xvcjogIzMxMzYzYjsKICAgICAgdGV4dC1kZWNvcmF0aW9uOiBub25lOwogICAgfQoKICAgIC5xdW90ZS1hZGRpdGlvbmFsLWluZm9ybWF0aW9uIHsKICAgICAgZm9udC1zaXplOiAxLjFlbTsKICAgICAgdGV4dC1hbGlnbjoganVzdGlmeTsKICAgICAgcGFkZGluZzogMXJlbSAycmVtOwogICAgICB3aWR0aDogMTAwJTsKICAgIH0KCiAgICAucXVvdGUtcHJpY2luZyB7CiAgICAgIHBhZGRpbmc6IDFyZW07CiAgICB9CgogICAgLnF1b3RlLXByaWNpbmctLXByaWNlIHsKICAgICAgY29sb3I6ICMzMTM2M2I7CiAgICAgIGRpc3BsYXk6IGJsb2NrOwogICAgICBmb250LXdlaWdodDogMTAwOwogICAgICBwYWRkaW5nOiAxcmVtOwogICAgfQoKICAgIC5xdW90ZS1wcmljaW5nLS10b3RhbCB7CiAgICAgIGRpc3BsYXk6IGJsb2NrOwogICAgICBmb250LXNpemU6IDEuMnJlbTsKICAgICAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgICAgIHBhZGRpbmc6IDFyZW07CiAgICB9CiAgPC9zdHlsZT4KICA8dGl0bGU+UmljaGllc3RhIGRpIHByZXZlbnRpdm88L3RpdGxlPgogIAo8L2hlYWQ+Cgo8Ym9keT4KICA8aGVhZGVyPgogICAgCiAgICA8ZGl2IGNsYXNzPSJsb2dvIj4KICAgICAgPGltZyBhbHQ9ImxvZ28iIHNyYz0iaHR0cHM6Ly9zdGF0aWMudmVlc28uZGV2L2xvZ28ud2VicCIgLz4KICAgIDwvZGl2PgogICAgCiAgICA8ZGl2IGNsYXNzPSJjdXN0b21lci1kYXRhIj4KICAgICAgPGgyPgogICAgICAgIFZpc2ludGluIENocmlzdGlhbgogICAgICA8L2gyPgogICAgICA8cCBjbGFzc05hbWU9ImNvbnRhY3QiPgogICAgICAgIDxhIGhyZWY9Im1haWx0bzpjaHJpc3RpYW4udmlzaW50aW4xOTk3QGdtYWlsLmNvbSI+Y2hyaXN0aWFuLnZpc2ludGluMTk5N0BnbWFpbC5jb208L2E+CiAgICAgIDwvcD4KICAgICAgPHAgY2xhc3NOYW1lPSJjb250YWN0Ij4KICAgICAgICA8YSBocmVmPSJ0ZWw6MzY2IDE2NyA3NTA5Ij4zNjYgMTY3IDc1MDk8L2E+CiAgICAgIDwvcD4KICAgICAgPC9kaXY+CiAgICAKICAgIDxkaXYgY2xhc3M9InF1b3RlLXNldHVwIj4KICAgICAgPGRpdiBjbGFzcz0icXVvdGUtaW5mbyI+CiAgICAgICAgPGgyPlByb2R1Y3Q6IEVjb21tZXJjZTwvaDI+CiAgICAgICAgPGgzPkRlbGl2ZXJ5IGRhdGU6IDIwMjMtMDctMzE8L2gzPgogICAgICAgIDxoMz5EZXNjcmlwdGlvbjo8L2gzPgogICAgICAgIDxwIGNsYXNzPSJxdW90ZS1hZGRpdGlvbmFsLWluZm9ybWF0aW9uIj4gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4gSW4gdmVuZW5hdGlzIGFjIG5lcXVlIGFjIGludGVyZHVtLiBVdCBjdXJzdXMgcmlzdXMgYXVndWUsIHF1aXMgY29uc2VxdWF0IGRpYW0gZmFjaWxpc2lzIGlkLiBOdWxsYW0gYXVndWUgZXJhdCwgdmFyaXVzIG9ybmFyZSB1bHRyaWNpZXMgdml0YWUsIGVnZXN0YXMgcXVpcyBhdWd1ZS4gTWF1cmlzIHZlbGl0IG1hc3NhLCBmYXVjaWJ1cyBpZCBleCB1dCwgdGluY2lkdW50IG9ybmFyZSBlc3Q8L3A+CiAgICAgICAgPC9kaXY+CiAgICAgIDxociAvPgogICAgICA8ZGl2IGNsYXNzPSJxdW90ZS1wcmljaW5nIj4KICAgICAgICA8aDM+UHJpY2luZzwvaDM+CiAgICAgICAgPHNwYW4gY2xhc3M9InF1b3RlLXByaWNpbmctLXByaWNlIj5CYXNlIHByaWNlOiAxNTAwIOKCrDwvc3Bhbj4KICAgICAgICA8c3BhbiBjbGFzcz0icXVvdGUtcHJpY2luZy0tcHJpY2UiPkZhc3QgRGVsaXZlcnk6IDEwMDAg4oKsPC9zcGFuPgogICAgICAgIDxzcGFuIGNsYXNzPSJxdW90ZS1wcmljaW5nLS1wcmljZSI+UGlwcG8gcGx1dG86IDEwMCDigqw8L3NwYW4+CiAgICAgICAgPHNwYW4gY2xhc3M9InF1b3RlLXByaWNpbmctLXByaWNlIj5DcnlwdG9tYWRvbm5lOiAyMDAg4oKsPC9zcGFuPgogICAgICAgIDxzcGFuIGNsYXNzPSJxdW90ZS1wcmljaW5nLS10b3RhbCI+VG90YWwgcHJpY2U6IDI4MDAg4oKsPC9zcGFuPgogICAgICA8L2Rpdj4KICAgIDwvZGl2PgogIDwvaGVhZGVyPgo8L2JvZHk+Cgo8L2h0bWw+ \ No newline at end of file diff --git a/src/aws_ses.rs b/src/aws_ses.rs new file mode 100644 index 0000000..c6f0d09 --- /dev/null +++ b/src/aws_ses.rs @@ -0,0 +1,52 @@ +use aws_config::SdkConfig; +use aws_sdk_sesv2::types::{Body, Content, Destination, EmailContent, Message}; + +/// client for AWS SES +pub struct AwsSesClient { + aws_config: SdkConfig, +} + +impl From for AwsSesClient { + fn from(aws_config: SdkConfig) -> Self { + Self { aws_config } + } +} + +impl AwsSesClient { + /// Send email to `recipient` with the set + pub async fn send( + &self, + sender: &str, + recipients: &[String], + subject: &str, + content: &str, + ) -> anyhow::Result<()> { + let client = aws_sdk_sesv2::Client::new(&self.aws_config); + debug!("AWS SES client ready"); + let destination = Destination::builder() + .set_to_addresses(Some(recipients.iter().map(|s| s.to_string()).collect())) + .build(); + + let body = Content::builder().data(content).charset("UTF-8").build(); + let body = Body::builder().text(body).build(); + let subject = Content::builder().data(subject).charset("UTF-8").build(); + + let message = Message::builder().subject(subject).body(body).build(); + + let email_content = EmailContent::builder().simple(message).build(); + + info!("sending email from {sender} to {recipients:?}"); + + client + .send_email() + .from_email_address(sender) + .destination(destination) + .content(email_content) + .send() + .await?; + + info!("email sent"); + + Ok(()) + } +} diff --git a/src/config.rs b/src/config.rs index 59c2e90..83441a3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -4,7 +4,10 @@ /// App configuration read from environment #[derive(Debug, Deserialize, Serialize)] -pub struct Config {} +pub struct Config { + pub email_sender: String, + pub web_port: u16, +} impl Config { pub fn try_from_env() -> anyhow::Result { diff --git a/src/main.rs b/src/main.rs index 7bf1293..de3d43e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,43 +3,32 @@ extern crate serde; #[macro_use] extern crate tracing; +mod aws_ses; mod config; +#[cfg(test)] +mod test; mod web; +const APP_NAME: &str = env!("CARGO_PKG_NAME"); const APP_AUTHORS: &str = env!("CARGO_PKG_AUTHORS"); const APP_VERSION: &str = env!("CARGO_PKG_VERSION"); -/* #[actix_web::main] async fn main() -> anyhow::Result<()> { tracing_subscriber::fmt::init(); - info!("rust-template v{} - developed by {}", APP_VERSION, APP_AUTHORS); + info!("{APP_NAME} v{APP_VERSION} - developed by {APP_AUTHORS}"); let config = config::Config::try_from_env()?; + info!("initializing Aws Config..."); + let aws_config = aws_config::load_from_env().await; + info!( + "AWS configuration loaded for region: {:?}", + aws_config.region() + ); info!("initializing web service..."); - let web_service = web::WebServer::init( - &config.clamav_address, - config.max_upload_size, - config.web_port, - ) - .await?; + let web_service = + web::WebServer::init(config.web_port, aws_config, &config.email_sender).await?; info!("web service OK; running web server..."); web_service.run().await?; Ok(()) } -*/ - -/* -#[tokio::main] -async fn main() -> anyhow::Result<()> { - tracing_subscriber::fmt::init(); - info!("rust-template v{} - developed by {}", APP_VERSION, APP_AUTHORS); - let config = config::Config::try_from_env()?; - - Ok(()) -} -*/ - -fn main() -> anyhow::Result<()> { - Ok(()) -} diff --git a/src/test.rs b/src/test.rs new file mode 100644 index 0000000..aaf3276 --- /dev/null +++ b/src/test.rs @@ -0,0 +1,3 @@ +pub fn log_init() { + let _ = env_logger::builder().is_test(true).try_init(); +} diff --git a/src/web/email.rs b/src/web/email.rs new file mode 100644 index 0000000..517af45 --- /dev/null +++ b/src/web/email.rs @@ -0,0 +1,56 @@ +use actix_web::{post, web, HttpResponse}; +use base64::{engine, Engine as _}; + +use super::WebserverData; + +/// Send request payload +#[derive(Debug, Deserialize)] +pub struct Send { + /// Email recipients + recipients: Vec, + /// Email subject + subject: String, + /// Base 64 encoded email content + body: String, +} + +#[post("/send")] +pub(super) async fn send(payload: web::Json, data: web::Data) -> HttpResponse { + if payload.recipients.is_empty() { + return HttpResponse::BadRequest().body("recipients should contain at least one item"); + } + + // decode body + let body = match engine::general_purpose::STANDARD_NO_PAD + .decode(&payload.body) + .map(String::from_utf8) + { + Ok(Ok(body)) => body, + Ok(Err(e)) => { + error!("failed to decode body as string: {e}"); + return HttpResponse::BadRequest() + .body("body must be a valid UTF-8 string encoded to Base64"); + } + Err(e) => { + error!("failed to decode body: {e}"); + return HttpResponse::BadRequest() + .body("body must be a valid UTF-8 string encoded to Base64"); + } + }; + + if let Err(err) = data + .aws_ses_client + .send( + &data.email_sender, + &payload.recipients, + &payload.subject, + &body, + ) + .await + { + error!("failed to send mail: {err}"); + return HttpResponse::InternalServerError().finish(); + } + + HttpResponse::Ok().finish() +} diff --git a/src/web/health_check.rs b/src/web/health_check.rs index dcadf7e..1936344 100644 --- a/src/web/health_check.rs +++ b/src/web/health_check.rs @@ -2,7 +2,23 @@ use actix_web::{get, HttpResponse}; #[get("/check")] pub async fn check_action() -> HttpResponse { - HttpResponse::Ok() - .content_type("application/json") - .body(r#"{"status": "ok"}"#) + HttpResponse::Ok().content_type("application/json").finish() +} + +#[cfg(test)] +mod test { + use actix_web::dev::Service; + use actix_web::{test, App}; + + use super::*; + + #[actix_rt::test] + async fn test_check_action() { + crate::test::log_init(); + let app = test::init_service(App::new().service(check_action)).await; + let request = test::TestRequest::with_uri("/check").to_request(); + + let res = app.call(request).await.unwrap(); + assert!(res.status().is_success()); + } } diff --git a/src/web/mod.rs b/src/web/mod.rs index a5f12b1..ca6f073 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -1,31 +1,49 @@ +mod email; +mod health_check; + use std::net::TcpListener; use actix_web::dev::Server; +use actix_web::middleware::Logger; use actix_web::web::Data; use actix_web::{App as ActixApp, HttpServer}; +use aws_config::SdkConfig; -mod health_check; +use crate::aws_ses::AwsSesClient; pub struct WebServer { server: Server, } -struct WebserverData {} +struct WebserverData { + aws_ses_client: AwsSesClient, + email_sender: String, +} impl WebServer { /// Initialize web server - pub async fn init(web_port: u16) -> anyhow::Result { + pub async fn init( + web_port: u16, + aws_config: SdkConfig, + email_sender: &str, + ) -> anyhow::Result { info!("webserver initialized"); info!("web port: {web_port}"); let listener = TcpListener::bind(format!("0.0.0.0:{web_port}"))?; let server = { + let email_sender = email_sender.to_string(); HttpServer::new(move || { - let web_data = Data::new(WebserverData {}); + let web_data = Data::new(WebserverData { + aws_ses_client: AwsSesClient::from(aws_config.clone()), + email_sender: email_sender.clone(), + }); ActixApp::new() + .service(email::send) .service(health_check::check_action) .app_data(web_data) + .wrap(Logger::default()) }) .listen(listener)? .run()