From efcb0a69708c377a2184600e04c48d09c4906b26 Mon Sep 17 00:00:00 2001 From: Max Fowler Date: Wed, 18 Nov 2020 18:22:48 +0100 Subject: [PATCH] surviving --- Cargo.lock | 181 +++++++++++++++++++++++++++++++++++++++++++++++---- Cargo.toml | 2 + README.md | 7 ++ gmail.py | 52 +++++++++++++++ src/email.rs | 42 ++++++++++++ src/main.rs | 52 ++++++++++----- 6 files changed, 306 insertions(+), 30 deletions(-) create mode 100644 README.md create mode 100644 gmail.py create mode 100644 src/email.rs diff --git a/Cargo.lock b/Cargo.lock index 868d86f..dbe4aee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,20 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +dependencies = [ + "memchr", +] + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + [[package]] name = "autocfg" version = "0.1.7" @@ -12,12 +27,24 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "base64" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" + [[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +[[package]] +name = "bufstream" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40e38929add23cdf8a366df9b0e088953150724bcbe5fc330b0d8eb3b328eec8" + [[package]] name = "bytes" version = "0.5.6" @@ -36,6 +63,19 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "time", + "winapi 0.3.9", +] + [[package]] name = "cloudabi" version = "0.0.3" @@ -47,9 +87,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.7.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" +checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" dependencies = [ "core-foundation-sys", "libc", @@ -57,9 +97,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.7.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" +checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" [[package]] name = "dotenv" @@ -213,7 +253,7 @@ checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.9.0+wasi-snapshot-preview1", ] [[package]] @@ -312,6 +352,31 @@ dependencies = [ "tokio-tls", ] +[[package]] +name = "imap" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae5af85d36c7f2062a5a3abed1fc73142a7cbf04a8cf4248fc672d763148884" +dependencies = [ + "base64", + "bufstream", + "chrono", + "imap-proto", + "lazy_static", + "native-tls", + "nom", + "regex", +] + +[[package]] +name = "imap-proto" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16a6def1d5ac8975d70b3fd101d57953fe3278ef2ee5d7816cba54b1d1dfc22f" +dependencies = [ + "nom", +] + [[package]] name = "indexmap" version = "1.6.0" @@ -353,6 +418,19 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lexical-core" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616" +dependencies = [ + "arrayvec", + "bitflags", + "cfg-if", + "ryu", + "static_assertions", +] + [[package]] name = "libc" version = "0.2.80" @@ -450,9 +528,9 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b0d88c06fe90d5ee94048ba40409ef1d9315d86f6f38c2efdaad4fb50c58b2d" +checksum = "6fcc7939b5edc4e4f86b1b4a04bb1498afaaf871b1a6691838ed06fcb48d3a3f" dependencies = [ "lazy_static", "libc", @@ -477,6 +555,27 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "nom" +version = "5.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" +dependencies = [ + "lexical-core", + "memchr", + "version_check 0.9.2", +] + +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg 1.0.1", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.14" @@ -829,6 +928,24 @@ version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" +[[package]] +name = "regex" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", +] + +[[package]] +name = "regex-syntax" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189" + [[package]] name = "remove_dir_all" version = "0.5.3" @@ -856,9 +973,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "0.4.4" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64808902d7d99f78eaddd2b4e2509713babc3dc3c85ad6f4c447680f3c01e535" +checksum = "c1759c2e3c8580017a484a7ac56d3abc5a6c1feadf88db2f3633f12ae4268c69" dependencies = [ "bitflags", "core-foundation", @@ -869,9 +986,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "0.4.3" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17bf11d99252f512695eb468de5516e5cf75455521e69dfe343f3b74e4748405" +checksum = "f99b9d5e26d2a71633cc4f2ebae7cc9f874044e0c351a27e17892d76dce5678b" dependencies = [ "core-foundation-sys", "libc", @@ -942,6 +1059,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "syn" version = "1.0.48" @@ -997,6 +1120,26 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "thread_local" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "time" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi 0.3.9", +] + [[package]] name = "tokio" version = "0.2.22" @@ -1111,7 +1254,7 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" dependencies = [ - "version_check", + "version_check 0.1.5", ] [[package]] @@ -1132,6 +1275,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" +[[package]] +name = "version_check" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" + [[package]] name = "want" version = "0.3.0" @@ -1148,12 +1297,20 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + [[package]] name = "wgbot" version = "0.1.0" dependencies = [ "dotenv", "futures", + "imap", + "native-tls", "telegram-bot", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index 196df93..11b4f0e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,3 +11,5 @@ telegram-bot = "0.7" dotenv = "0.15.0" futures = "0.3.7" tokio = { version = "0.2", features = ["macros", "time", "fs"] } +imap = "2.3.0" +native-tls = "0.2.6" diff --git a/README.md b/README.md new file mode 100644 index 0000000..430557a --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# run + +cargo build +cargo run + + + diff --git a/gmail.py b/gmail.py new file mode 100644 index 0000000..6c6ac47 --- /dev/null +++ b/gmail.py @@ -0,0 +1,52 @@ +import email, getpass, imaplib, os + +detach_dir = '.' # directory where to save attachments (default: current) +user = "maxhfowler@gmail.com" +pwd = "hidden" + +# connecting to the gmail imap server +m = imaplib.IMAP4_SSL("imap.gmail.com") +m.login(user, pwd) +# +# m.select("wgbot") # here you a can choose a mail box like INBOX instead +m.select("INBOX") # here you a can choose a mail box like INBOX instead +# # use m.list() to get all the mailboxes +# +resp, items = m.search(None, + "ALL") # you could filter using the IMAP rules here (check http://www.example-code.com/csharp/imap-search-critera.asp) +items = items[0].split() # getting the mails id + +for emailid in items: + resp, data = m.fetch(emailid, + "(RFC822)") # fetching the mail, "`(RFC822)`" means "get the whole stuff", but you can ask for headers only, etc + email_body = data[0][1] # getting the mail content + mail = email.message_from_bytes(email_body) # parsing the mail content to get a mail object + + # Check if any attachments at all + if mail.get_content_maintype() != 'multipart': + continue + + print("[" + mail["From"] + "] :" + mail["Subject"]) + + # we use walk to create a generator so we can iterate on the parts and forget about the recursive headach + for part in mail.walk(): + # multipart are just containers, so we skip them + if part.get_content_maintype() == 'multipart': + continue + + # is this part an attachment ? + if part.get('Content-Disposition') is None: + continue + + # filename = part.get_filename() + + filename = mail["From"] + "_hw1answer" + + att_path = os.path.join(detach_dir, filename) + + # Check if its already there + if not os.path.isfile(att_path): + # finally write the stuff + fp = open(att_path, 'wb') + fp.write(part.get_payload(decode=True)) + fp.close() \ No newline at end of file diff --git a/src/email.rs b/src/email.rs new file mode 100644 index 0000000..b1d56ab --- /dev/null +++ b/src/email.rs @@ -0,0 +1,42 @@ +extern crate imap; +extern crate native_tls; + +pub fn fetch_inbox_top(imap_username: &str, imap_password: &str) -> imap::error::Result> { + let domain = "imap.gmail.com"; + let tls = native_tls::TlsConnector::builder().build().unwrap(); + + // we pass in the domain twice to check that the server's TLS + // certificate is valid for the domain we're connecting to. + let client = imap::connect((domain, 993), domain, &tls).unwrap(); + + // the client we have here is unauthenticated. + // to do anything useful with the e-mails, we need to log in + let mut imap_session = client + .login(imap_username, imap_password) + .map_err(|e| e.0)?; + + // we want to fetch the first email in the INBOX mailbox + imap_session.select("INBOX")?; + + // fetch message number 1 in this mailbox, along with its RFC822 field. + // RFC 822 dictates the format of the body of e-mails + let messages = imap_session.fetch("1", "RFC822")?; + let message = if let Some(m) = messages.iter().next() { + m + } else { + return Ok(None); + }; + + // extract the message's body + let body = message.body().expect("message did not have a body!"); + let body = std::str::from_utf8(body) + .expect("message was not valid utf-8") + .to_string(); + + println!("{}", body); + + // be nice to the server and log out + imap_session.logout()?; + + Ok(Some(body)) +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 4d6a6ac..7acda0d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,9 @@ use dotenv; use futures::StreamExt; use telegram_bot::*; +use telegram_bot::{Api, Message, SendMessage, MessageKind, UpdateKind}; +mod email; + #[tokio::main] async fn main() -> Result<(), Error> { @@ -10,24 +13,37 @@ async fn main() -> Result<(), Error> { let token = env::var("TELEGRAM_BOT_TOKEN").expect("TELEGRAM_BOT_TOKEN not set"); let api = Api::new(token); - // Fetch new updates via long poll method - let mut stream = api.stream(); - while let Some(update) = stream.next().await { - // If the received update contains a new message... - let update = update?; - if let UpdateKind::Message(message) = update.kind { - if let MessageKind::Text { ref data, .. } = message.kind { - // Print received text message to stdout. - println!("<{}>: {}", &message.from.first_name, data); +// api.send(message.text_reply(format!("+ wgbot is booting up"))); - // Answer message with "Hi". - api.send(message.text_reply(format!( - "Hi, {}! You just wrote '{}'", - &message.from.first_name, data - ))) - .await?; - } - } - } + let imap_username = env::var("IMAP_USERNAME").expect("imap username is not set"); + let imap_password = env::var("IMAP_PASSWORD").expect("imap password is not set"); + let telegram_log_id: i64 = env::var("TELEGRAM_LOG_ID").expect("TELEGRAM_LOG_ID is not set").parse().unwrap(); + + let chatId = ChatId::new(telegram_log_id); + let s:SendMessage = SendMessage::new(chatId, "very cool that this is working"); + api.send(s).await?; + +// email::fetch_inbox_top(&imap_username, &imap_password); +// +// // Fetch new updates via long poll method +// let mut stream = api.stream(); +// while let Some(update) = stream.next().await { +// // If the received update contains a new message... +// let update = update?; +// if let UpdateKind::Message(message) = update.kind { +// if let MessageKind::Text { ref data, .. } = message.kind { +// // Print received text message to stdout. +// println!("<{}>: {}", &message.from.first_name, data); +// println!("user id: {}", &message.from.id); +// +// // Answer message with "Hi". +// api.send(message.text_reply(format!( +// "Hi, {}! You just wrote '{}'", +// &message.from.first_name, data +// ))) +// .await?; +// } +// } +// } Ok(()) } \ No newline at end of file