0000: 75 73 65 20 63 72 61 74 65 3a 3a 7b 0a 09 43 75 use crate::{..Cu
0010: 72 73 6f 72 2c 0a 09 74 65 6c 65 67 72 61 6d 3a rsor,..telegram:
0020: 3a 7b 0a 09 09 65 6e 63 6f 64 65 2c 0a 09 09 54 :{...encode,...T
0030: 65 6c 65 67 72 61 6d 54 72 61 6e 73 70 6f 72 74 elegramTransport
0040: 2c 0a 09 7d 2c 0a 09 75 74 69 6c 73 3a 3a 7b 0a ,..},..utils::{.
0050: 09 09 41 74 74 61 63 68 6d 65 6e 74 2c 0a 09 09 ..Attachment,...
0060: 52 45 5f 44 4f 4d 41 49 4e 2c 0a 09 7d 2c 0a 7d RE_DOMAIN,..},.}
0070: 3b 0a 0a 75 73 65 20 73 74 64 3a 3a 7b 0a 09 62 ;..use std::{..b
0080: 6f 72 72 6f 77 3a 3a 43 6f 77 2c 0a 09 63 6f 6c orrow::Cow,..col
0090: 6c 65 63 74 69 6f 6e 73 3a 3a 7b 0a 09 09 48 61 lections::{...Ha
00a0: 73 68 4d 61 70 2c 0a 09 09 48 61 73 68 53 65 74 shMap,...HashSet
00b0: 2c 0a 09 7d 2c 0a 09 69 6f 3a 3a 45 72 72 6f 72 ,..},..io::Error
00c0: 2c 0a 09 73 79 6e 63 3a 3a 41 72 63 2c 0a 7d 3b ,..sync::Arc,.};
00d0: 0a 0a 75 73 65 20 6d 61 69 6c 69 6e 5f 65 6d 62 ..use mailin_emb
00e0: 65 64 64 65 64 3a 3a 7b 0a 09 52 65 73 70 6f 6e edded::{..Respon
00f0: 73 65 2c 0a 09 72 65 73 70 6f 6e 73 65 3a 3a 7b se,..response::{
0100: 0a 09 09 49 4e 54 45 52 4e 41 4c 5f 45 52 52 4f ...INTERNAL_ERRO
0110: 52 2c 0a 09 09 49 4e 56 41 4c 49 44 5f 43 52 45 R,...INVALID_CRE
0120: 44 45 4e 54 49 41 4c 53 2c 0a 09 09 4e 4f 5f 4d DENTIALS,...NO_M
0130: 41 49 4c 42 4f 58 2c 0a 09 09 4f 4b 0a 09 7d 2c AILBOX,...OK..},
0140: 0a 7d 3b 0a 75 73 65 20 72 65 67 65 78 3a 3a 7b .};.use regex::{
0150: 0a 09 52 65 67 65 78 2c 0a 09 65 73 63 61 70 65 ..Regex,..escape
0160: 2c 0a 7d 3b 0a 75 73 65 20 73 74 61 63 6b 65 64 ,.};.use stacked
0170: 5f 65 72 72 6f 72 73 3a 3a 7b 0a 09 52 65 73 75 _errors::{..Resu
0180: 6c 74 2c 0a 09 53 74 61 63 6b 61 62 6c 65 45 72 lt,..StackableEr
0190: 72 2c 0a 09 62 61 69 6c 2c 0a 7d 3b 0a 75 73 65 r,..bail,.};.use
01a0: 20 74 67 62 6f 74 3a 3a 74 79 70 65 73 3a 3a 43 tgbot::types::C
01b0: 68 61 74 50 65 65 72 49 64 3b 0a 0a 2f 2f 2f 20 hatPeerId;..///
01c0: 60 53 6f 6d 65 48 65 61 64 65 72 73 60 20 6f 62 `SomeHeaders` ob
01d0: 6a 65 63 74 20 74 6f 20 73 74 6f 72 65 20 64 61 ject to store da
01e0: 74 61 20 74 68 72 6f 75 67 68 20 53 4d 54 50 20 ta through SMTP
01f0: 73 65 73 73 69 6f 6e 0a 23 5b 64 65 72 69 76 65 session.#[derive
0200: 28 43 6c 6f 6e 65 2c 20 44 65 62 75 67 29 5d 0a (Clone, Debug)].
0210: 73 74 72 75 63 74 20 53 6f 6d 65 48 65 61 64 65 struct SomeHeade
0220: 72 73 20 7b 0a 09 66 72 6f 6d 3a 20 53 74 72 69 rs {..from: Stri
0230: 6e 67 2c 0a 09 74 6f 3a 20 56 65 63 3c 53 74 72 ng,..to: Vec<Str
0240: 69 6e 67 3e 2c 0a 7d 0a 0a 2f 2f 2f 20 60 4d 61 ing>,.}../// `Ma
0250: 69 6c 53 65 72 76 65 72 60 20 43 65 6e 74 72 61 ilServer` Centra
0260: 6c 20 6f 62 6a 65 63 74 20 77 69 74 68 20 54 47 l object with TG
0270: 20 61 70 69 20 61 6e 64 20 63 6f 6e 66 69 67 75 api and configu
0280: 72 61 74 69 6f 6e 0a 23 5b 64 65 72 69 76 65 28 ration.#[derive(
0290: 43 6c 6f 6e 65 2c 20 44 65 62 75 67 29 5d 0a 70 Clone, Debug)].p
02a0: 75 62 20 73 74 72 75 63 74 20 4d 61 69 6c 53 65 ub struct MailSe
02b0: 72 76 65 72 20 7b 0a 09 64 61 74 61 3a 20 56 65 rver {..data: Ve
02c0: 63 3c 75 38 3e 2c 0a 09 68 65 61 64 65 72 73 3a c<u8>,..headers:
02d0: 20 4f 70 74 69 6f 6e 3c 53 6f 6d 65 48 65 61 64 Option<SomeHead
02e0: 65 72 73 3e 2c 0a 09 72 65 6c 61 79 3a 20 62 6f ers>,..relay: bo
02f0: 6f 6c 2c 0a 09 74 67 3a 20 41 72 63 3c 54 65 6c ol,..tg: Arc<Tel
0300: 65 67 72 61 6d 54 72 61 6e 73 70 6f 72 74 3e 2c egramTransport>,
0310: 0a 09 66 69 65 6c 64 73 3a 20 48 61 73 68 53 65 ..fields: HashSe
0320: 74 3c 53 74 72 69 6e 67 3e 2c 0a 09 61 64 64 72 t<String>,..addr
0330: 65 73 73 3a 20 52 65 67 65 78 2c 0a 7d 0a 0a 69 ess: Regex,.}..i
0340: 6d 70 6c 20 4d 61 69 6c 53 65 72 76 65 72 20 7b mpl MailServer {
0350: 0a 09 2f 2f 2f 20 49 6e 69 74 69 61 6c 69 7a 65 ../// Initialize
0360: 20 41 50 49 20 61 6e 64 20 72 65 61 64 20 63 6f API and read co
0370: 6e 66 69 67 75 72 61 74 69 6f 6e 0a 09 70 75 62 nfiguration..pub
0380: 20 66 6e 20 6e 65 77 28 73 65 74 74 69 6e 67 73 fn new(settings
0390: 3a 20 63 6f 6e 66 69 67 3a 3a 43 6f 6e 66 69 67 : config::Config
03a0: 29 20 2d 3e 20 52 65 73 75 6c 74 3c 4d 61 69 6c ) -> Result<Mail
03b0: 53 65 72 76 65 72 3e 20 7b 0a 09 09 6c 65 74 20 Server> {...let
03c0: 61 70 69 5f 6b 65 79 20 3d 20 73 65 74 74 69 6e api_key = settin
03d0: 67 73 2e 67 65 74 5f 73 74 72 69 6e 67 28 22 61 gs.get_string("a
03e0: 70 69 5f 6b 65 79 22 29 0a 09 09 09 2e 63 6f 6e pi_key").....con
03f0: 74 65 78 74 28 22 5b 73 6d 74 70 32 74 67 2e 74 text("[smtp2tg.t
0400: 6f 6d 6c 5d 20 6d 69 73 73 69 6e 67 20 5c 22 61 oml] missing \"a
0410: 70 69 5f 6b 65 79 5c 22 20 70 61 72 61 6d 65 74 pi_key\" paramet
0420: 65 72 2e 5c 6e 22 29 3f 3b 0a 09 09 6c 65 74 20 er.\n")?;...let
0430: 6d 75 74 20 72 65 63 69 70 69 65 6e 74 73 20 3d mut recipients =
0440: 20 48 61 73 68 4d 61 70 3a 3a 6e 65 77 28 29 3b HashMap::new();
0450: 0a 09 09 66 6f 72 20 28 6e 61 6d 65 2c 20 76 61 ...for (name, va
0460: 6c 75 65 29 20 69 6e 20 73 65 74 74 69 6e 67 73 lue) in settings
0470: 2e 67 65 74 5f 74 61 62 6c 65 28 22 72 65 63 69 .get_table("reci
0480: 70 69 65 6e 74 73 22 29 0a 09 09 09 2e 65 78 70 pients").....exp
0490: 65 63 74 28 22 5b 73 6d 74 70 32 74 67 2e 74 6f ect("[smtp2tg.to
04a0: 6d 6c 5d 20 6d 69 73 73 69 6e 67 20 74 61 62 6c ml] missing tabl
04b0: 65 20 5c 22 72 65 63 69 70 69 65 6e 74 73 5c 22 e \"recipients\"
04c0: 2e 5c 6e 22 29 0a 09 09 7b 0a 09 09 09 6c 65 74 .\n")...{....let
04d0: 20 76 61 6c 75 65 20 3d 20 76 61 6c 75 65 2e 69 value = value.i
04e0: 6e 74 6f 5f 69 6e 74 28 29 0a 09 09 09 09 2e 63 nto_int()......c
04f0: 6f 6e 74 65 78 74 28 22 5b 73 6d 74 70 32 74 67 ontext("[smtp2tg
0500: 2e 74 6f 6d 6c 5d 20 5c 22 72 65 63 69 70 69 65 .toml] \"recipie
0510: 6e 74 5c 22 20 74 61 62 6c 65 20 76 61 6c 75 65 nt\" table value
0520: 73 20 73 68 6f 75 6c 64 20 62 65 20 69 6e 74 65 s should be inte
0530: 67 65 72 73 2e 5c 6e 22 29 3f 3b 0a 09 09 09 72 gers.\n")?;....r
0540: 65 63 69 70 69 65 6e 74 73 2e 69 6e 73 65 72 74 ecipients.insert
0550: 28 6e 61 6d 65 2c 20 76 61 6c 75 65 29 3b 0a 09 (name, value);..
0560: 09 7d 0a 09 09 6c 65 74 20 64 65 66 61 75 6c 74 .}...let default
0570: 20 3d 20 73 65 74 74 69 6e 67 73 2e 67 65 74 5f = settings.get_
0580: 69 6e 74 28 22 64 65 66 61 75 6c 74 22 29 0a 09 int("default")..
0590: 09 09 2e 63 6f 6e 74 65 78 74 28 22 5b 73 6d 74 ...context("[smt
05a0: 70 32 74 67 2e 74 6f 6d 6c 5d 20 6d 69 73 73 69 p2tg.toml] missi
05b0: 6e 67 20 5c 22 64 65 66 61 75 6c 74 5c 22 20 72 ng \"default\" r
05c0: 65 63 69 70 69 65 6e 74 2e 5c 6e 22 29 3f 3b 0a ecipient.\n")?;.
05d0: 0a 09 09 6c 65 74 20 74 67 20 3d 20 41 72 63 3a ...let tg = Arc:
05e0: 3a 6e 65 77 28 54 65 6c 65 67 72 61 6d 54 72 61 :new(TelegramTra
05f0: 6e 73 70 6f 72 74 3a 3a 6e 65 77 28 61 70 69 5f nsport::new(api_
0600: 6b 65 79 2c 20 72 65 63 69 70 69 65 6e 74 73 2c key, recipients,
0610: 20 64 65 66 61 75 6c 74 29 3f 29 3b 0a 09 09 6c default)?);...l
0620: 65 74 20 66 69 65 6c 64 73 20 3d 20 48 61 73 68 et fields = Hash
0630: 53 65 74 3a 3a 3c 53 74 72 69 6e 67 3e 3a 3a 66 Set::<String>::f
0640: 72 6f 6d 5f 69 74 65 72 28 73 65 74 74 69 6e 67 rom_iter(setting
0650: 73 2e 67 65 74 5f 61 72 72 61 79 28 22 66 69 65 s.get_array("fie
0660: 6c 64 73 22 29 0a 09 09 09 2e 65 78 70 65 63 74 lds").....expect
0670: 28 22 5b 73 6d 74 70 32 74 67 2e 74 6f 6d 6c 5d ("[smtp2tg.toml]
0680: 20 5c 22 66 69 65 6c 64 73 5c 22 20 73 68 6f 75 \"fields\" shou
0690: 6c 64 20 62 65 20 61 6e 20 61 72 72 61 79 22 29 ld be an array")
06a0: 0a 09 09 09 2e 69 74 65 72 28 29 2e 6d 61 70 28 .....iter().map(
06b0: 7c 78 7c 20 78 2e 63 6c 6f 6e 65 28 29 2e 69 6e |x| x.clone().in
06c0: 74 6f 5f 73 74 72 69 6e 67 28 29 2e 65 78 70 65 to_string().expe
06d0: 63 74 28 22 73 68 6f 75 6c 64 20 62 65 20 73 74 ct("should be st
06e0: 72 69 6e 67 73 22 29 29 29 3b 0a 09 09 6c 65 74 rings")));...let
06f0: 20 6d 75 74 20 64 6f 6d 61 69 6e 73 3a 20 48 61 mut domains: Ha
0700: 73 68 53 65 74 3c 53 74 72 69 6e 67 3e 20 3d 20 shSet<String> =
0710: 48 61 73 68 53 65 74 3a 3a 6e 65 77 28 29 3b 0a HashSet::new();.
0720: 09 09 6c 65 74 20 65 78 74 72 61 5f 64 6f 6d 61 ..let extra_doma
0730: 69 6e 73 20 3d 20 73 65 74 74 69 6e 67 73 2e 67 ins = settings.g
0740: 65 74 5f 61 72 72 61 79 28 22 64 6f 6d 61 69 6e et_array("domain
0750: 73 22 29 2e 73 74 61 63 6b 28 29 3f 3b 0a 09 09 s").stack()?;...
0760: 66 6f 72 20 64 6f 6d 61 69 6e 20 69 6e 20 65 78 for domain in ex
0770: 74 72 61 5f 64 6f 6d 61 69 6e 73 20 7b 0a 09 09 tra_domains {...
0780: 09 6c 65 74 20 64 6f 6d 61 69 6e 20 3d 20 64 6f .let domain = do
0790: 6d 61 69 6e 2e 74 6f 5f 73 74 72 69 6e 67 28 29 main.to_string()
07a0: 2e 74 6f 5f 6c 6f 77 65 72 63 61 73 65 28 29 3b .to_lowercase();
07b0: 0a 09 09 09 69 66 20 52 45 5f 44 4f 4d 41 49 4e ....if RE_DOMAIN
07c0: 2e 69 73 5f 6d 61 74 63 68 28 26 64 6f 6d 61 69 .is_match(&domai
07d0: 6e 29 20 7b 0a 09 09 09 09 64 6f 6d 61 69 6e 73 n) {.....domains
07e0: 2e 69 6e 73 65 72 74 28 64 6f 6d 61 69 6e 29 3b .insert(domain);
07f0: 0a 09 09 09 7d 20 65 6c 73 65 20 7b 0a 09 09 09 ....} else {....
0800: 09 70 61 6e 69 63 21 28 22 5b 73 6d 74 70 32 74 .panic!("[smtp2t
0810: 67 2e 74 6f 6d 6c 5d 20 63 61 6e 27 74 20 63 68 g.toml] can't ch
0820: 65 63 6b 20 6f 66 20 64 6f 6d 61 69 6e 73 20 69 eck of domains i
0830: 6e 20 5c 22 64 6f 6d 61 69 6e 73 5c 22 3a 20 7b n \"domains\": {
0840: 64 6f 6d 61 69 6e 7d 22 29 3b 0a 09 09 09 7d 0a domain}");....}.
0850: 09 09 7d 0a 09 09 6c 65 74 20 64 6f 6d 61 69 6e ..}...let domain
0860: 73 20 3d 20 64 6f 6d 61 69 6e 73 2e 69 6e 74 6f s = domains.into
0870: 5f 69 74 65 72 28 29 2e 6d 61 70 28 7c 73 7c 20 _iter().map(|s|
0880: 65 73 63 61 70 65 28 26 73 29 29 0a 09 09 09 2e escape(&s)).....
0890: 63 6f 6c 6c 65 63 74 3a 3a 3c 56 65 63 3c 53 74 collect::<Vec<St
08a0: 72 69 6e 67 3e 3e 28 29 2e 6a 6f 69 6e 28 22 7c ring>>().join("|
08b0: 22 29 3b 0a 09 09 6c 65 74 20 61 64 64 72 65 73 ");...let addres
08c0: 73 20 3d 20 52 65 67 65 78 3a 3a 6e 65 77 28 26 s = Regex::new(&
08d0: 66 6f 72 6d 61 74 21 28 22 5e 28 3f 50 3c 75 73 format!("^(?P<us
08e0: 65 72 3e 5b 61 2d 7a 30 2d 39 5d 5b 2d 61 2d 7a er>[a-z0-9][-a-z
08f0: 30 2d 39 5d 29 28 40 28 7b 64 6f 6d 61 69 6e 73 0-9])(@({domains
0900: 7d 29 29 24 22 29 29 2e 73 74 61 63 6b 28 29 3f }))$")).stack()?
0910: 3b 0a 09 09 6c 65 74 20 72 65 6c 61 79 20 3d 20 ;...let relay =
0920: 6d 61 74 63 68 20 73 65 74 74 69 6e 67 73 2e 67 match settings.g
0930: 65 74 5f 73 74 72 69 6e 67 28 22 75 6e 6b 6e 6f et_string("unkno
0940: 77 6e 22 29 0a 09 09 09 2e 63 6f 6e 74 65 78 74 wn").....context
0950: 28 22 5b 73 6d 74 70 32 74 67 2e 74 6f 6d 6c 5d ("[smtp2tg.toml]
0960: 20 63 61 6e 27 74 20 67 65 74 20 5c 22 75 6e 6b can't get \"unk
0970: 6e 6f 77 6e 5c 22 20 70 6f 6c 69 63 79 2e 5c 6e nown\" policy.\n
0980: 22 29 3f 2e 61 73 5f 73 74 72 28 29 0a 09 09 7b ")?.as_str()...{
0990: 0a 09 09 09 22 72 65 6c 61 79 22 20 3d 3e 20 74 ...."relay" => t
09a0: 72 75 65 2c 0a 09 09 09 22 64 65 6e 79 22 20 3d rue,...."deny" =
09b0: 3e 20 66 61 6c 73 65 2c 0a 09 09 09 5f 20 3d 3e > false,...._ =>
09c0: 20 7b 0a 09 09 09 09 62 61 69 6c 21 28 22 5b 73 {.....bail!("[s
09d0: 6d 74 70 32 74 67 2e 74 6f 6d 6c 5d 20 5c 22 75 mtp2tg.toml] \"u
09e0: 6e 6b 6e 6f 77 6e 5c 22 20 73 68 6f 75 6c 64 20 nknown\" should
09f0: 62 65 20 65 69 74 68 65 72 20 5c 22 72 65 6c 61 be either \"rela
0a00: 79 5c 22 20 6f 72 20 5c 22 64 65 6e 79 5c 22 2e y\" or \"deny\".
0a10: 5c 6e 22 29 3b 0a 09 09 09 7d 2c 0a 09 09 7d 3b \n");....},...};
0a20: 0a 0a 09 09 4f 6b 28 4d 61 69 6c 53 65 72 76 65 ....Ok(MailServe
0a30: 72 20 7b 0a 09 09 09 64 61 74 61 3a 20 76 65 63 r {....data: vec
0a40: 21 28 29 2c 0a 09 09 09 68 65 61 64 65 72 73 3a !(),....headers:
0a50: 20 4e 6f 6e 65 2c 0a 09 09 09 72 65 6c 61 79 2c None,....relay,
0a60: 0a 09 09 09 74 67 2c 0a 09 09 09 66 69 65 6c 64 ....tg,....field
0a70: 73 2c 0a 09 09 09 61 64 64 72 65 73 73 2c 0a 09 s,....address,..
0a80: 09 7d 29 0a 09 7d 0a 0a 09 2f 2f 2f 20 52 65 74 .})..}.../// Ret
0a90: 75 72 6e 73 20 69 64 20 66 6f 72 20 70 72 6f 76 urns id for prov
0aa0: 69 64 65 64 20 65 6d 61 69 6c 20 61 64 64 72 65 ided email addre
0ab0: 73 73 0a 09 66 6e 20 67 65 74 5f 69 64 20 28 26 ss..fn get_id (&
0ac0: 73 65 6c 66 2c 20 6e 61 6d 65 3a 20 26 73 74 72 self, name: &str
0ad0: 29 20 2d 3e 20 52 65 73 75 6c 74 3c 26 43 68 61 ) -> Result<&Cha
0ae0: 74 50 65 65 72 49 64 3e 20 7b 0a 09 09 2f 2f 20 tPeerId> {...//
0af0: 68 65 72 65 20 77 65 20 6e 65 65 64 20 74 6f 20 here we need to
0b00: 73 74 6f 72 65 20 53 74 72 69 6e 67 20 6c 6f 63 store String loc
0b10: 61 6c 6c 79 20 74 6f 20 62 6f 72 72 6f 77 20 69 ally to borrow i
0b20: 74 20 61 66 74 65 72 0a 09 09 6c 65 74 20 6d 75 t after...let mu
0b30: 74 20 6c 69 6e 6b 20 3d 20 6e 61 6d 65 3b 0a 09 t link = name;..
0b40: 09 6c 65 74 20 6e 61 6d 65 3a 20 53 74 72 69 6e .let name: Strin
0b50: 67 3b 0a 09 09 69 66 20 6c 65 74 20 53 6f 6d 65 g;...if let Some
0b60: 28 63 61 70 73 29 20 3d 20 73 65 6c 66 2e 61 64 (caps) = self.ad
0b70: 64 72 65 73 73 2e 63 61 70 74 75 72 65 73 28 6c dress.captures(l
0b80: 69 6e 6b 29 20 7b 0a 09 09 09 6e 61 6d 65 20 3d ink) {....name =
0b90: 20 63 61 70 73 5b 22 6e 61 6d 65 22 5d 2e 74 6f caps["name"].to
0ba0: 5f 73 74 72 69 6e 67 28 29 3b 0a 09 09 09 6c 69 _string();....li
0bb0: 6e 6b 20 3d 20 26 6e 61 6d 65 3b 0a 09 09 7d 0a nk = &name;...}.
0bc0: 09 09 6d 61 74 63 68 20 73 65 6c 66 2e 74 67 2e ..match self.tg.
0bd0: 67 65 74 28 6c 69 6e 6b 29 20 7b 0a 09 09 09 4f get(link) {....O
0be0: 6b 28 61 64 64 72 29 20 3d 3e 20 4f 6b 28 61 64 k(addr) => Ok(ad
0bf0: 64 72 29 2c 0a 09 09 09 45 72 72 28 5f 29 20 3d dr),....Err(_) =
0c00: 3e 20 4f 6b 28 26 73 65 6c 66 2e 74 67 2e 64 65 > Ok(&self.tg.de
0c10: 66 61 75 6c 74 29 2c 0a 09 09 7d 0a 09 7d 0a 0a fault),...}..}..
0c20: 09 2f 2f 2f 20 41 74 74 65 6d 70 74 20 74 6f 20 ./// Attempt to
0c30: 64 65 6c 69 76 65 72 20 6f 6e 65 20 6d 65 73 73 deliver one mess
0c40: 61 67 65 0a 09 61 73 79 6e 63 20 66 6e 20 72 65 age..async fn re
0c50: 6c 61 79 5f 6d 61 69 6c 20 28 26 73 65 6c 66 29 lay_mail (&self)
0c60: 20 2d 3e 20 52 65 73 75 6c 74 3c 28 29 3e 20 7b -> Result<()> {
0c70: 0a 09 09 69 66 20 6c 65 74 20 53 6f 6d 65 28 68 ...if let Some(h
0c80: 65 61 64 65 72 73 29 20 3d 20 26 73 65 6c 66 2e eaders) = &self.
0c90: 68 65 61 64 65 72 73 20 7b 0a 09 09 09 6c 65 74 headers {....let
0ca0: 20 6d 61 69 6c 20 3d 20 6d 61 69 6c 5f 70 61 72 mail = mail_par
0cb0: 73 65 72 3a 3a 4d 65 73 73 61 67 65 50 61 72 73 ser::MessagePars
0cc0: 65 72 3a 3a 6e 65 77 28 29 2e 70 61 72 73 65 28 er::new().parse(
0cd0: 26 73 65 6c 66 2e 64 61 74 61 29 0a 09 09 09 09 &self.data).....
0ce0: 2e 63 6f 6e 74 65 78 74 28 22 46 61 69 6c 65 64 .context("Failed
0cf0: 20 74 6f 20 70 61 72 73 65 20 6d 61 69 6c 2e 22 to parse mail."
0d00: 29 3f 3b 0a 0a 09 09 09 2f 2f 20 41 64 64 69 6e )?;.....// Addin
0d10: 67 20 61 6c 6c 20 6b 6e 6f 77 6e 20 61 64 64 72 g all known addr
0d20: 65 73 73 65 73 20 74 6f 20 72 65 63 69 70 69 65 esses to recipie
0d30: 6e 74 20 6c 69 73 74 2c 20 66 6f 72 20 61 6e 79 nt list, for any
0d40: 6f 6e 65 20 65 6c 73 65 20 61 64 64 69 6e 67 20 one else adding
0d50: 64 65 66 61 75 6c 74 0a 09 09 09 2f 2f 20 41 6c default....// Al
0d60: 73 6f 20 69 66 20 6c 69 73 74 20 69 73 20 65 6d so if list is em
0d70: 70 74 79 20 61 6c 73 6f 20 61 64 64 69 6e 67 20 pty also adding
0d80: 64 65 66 61 75 6c 74 0a 09 09 09 6c 65 74 20 6d default....let m
0d90: 75 74 20 72 63 70 74 3a 20 48 61 73 68 53 65 74 ut rcpt: HashSet
0da0: 3c 26 43 68 61 74 50 65 65 72 49 64 3e 20 3d 20 <&ChatPeerId> =
0db0: 48 61 73 68 53 65 74 3a 3a 6e 65 77 28 29 3b 0a HashSet::new();.
0dc0: 09 09 09 69 66 20 68 65 61 64 65 72 73 2e 74 6f ...if headers.to
0dd0: 2e 69 73 5f 65 6d 70 74 79 28 29 20 26 26 20 21 .is_empty() && !
0de0: 73 65 6c 66 2e 72 65 6c 61 79 20 7b 0a 09 09 09 self.relay {....
0df0: 09 62 61 69 6c 21 28 22 52 65 6c 61 79 69 6e 67 .bail!("Relaying
0e00: 20 69 73 20 64 69 73 61 62 6c 65 64 2c 20 61 6e is disabled, an
0e10: 64 20 74 68 65 72 65 27 73 20 6e 6f 20 64 65 73 d there's no des
0e20: 74 69 6e 61 74 69 6f 6e 20 61 64 64 72 65 73 73 tination address
0e30: 22 29 3b 0a 09 09 09 7d 0a 09 09 09 66 6f 72 20 ");....}....for
0e40: 69 74 65 6d 20 69 6e 20 26 68 65 61 64 65 72 73 item in &headers
0e50: 2e 74 6f 20 7b 0a 09 09 09 09 72 63 70 74 2e 69 .to {.....rcpt.i
0e60: 6e 73 65 72 74 28 73 65 6c 66 2e 67 65 74 5f 69 nsert(self.get_i
0e70: 64 28 69 74 65 6d 29 3f 29 3b 0a 09 09 09 7d 3b d(item)?);....};
0e80: 0a 09 09 09 69 66 20 72 63 70 74 2e 69 73 5f 65 ....if rcpt.is_e
0e90: 6d 70 74 79 28 29 20 7b 0a 09 09 09 09 73 65 6c mpty() {.....sel
0ea0: 66 2e 74 67 2e 64 65 62 75 67 28 22 4e 6f 20 72 f.tg.debug("No r
0eb0: 65 63 69 70 69 65 6e 74 20 6f 72 20 65 6e 76 65 ecipient or enve
0ec0: 6c 6f 70 65 20 61 64 64 72 65 73 73 2e 22 29 2e lope address.").
0ed0: 61 77 61 69 74 3f 3b 0a 09 09 09 09 72 63 70 74 await?;.....rcpt
0ee0: 2e 69 6e 73 65 72 74 28 26 73 65 6c 66 2e 74 67 .insert(&self.tg
0ef0: 2e 64 65 66 61 75 6c 74 29 3b 0a 09 09 09 7d 3b .default);....};
0f00: 0a 0a 09 09 09 2f 2f 20 70 72 65 70 61 74 69 6e .....// prepatin
0f10: 67 20 6d 65 73 73 61 67 65 20 68 65 61 64 65 72 g message header
0f20: 0a 09 09 09 6c 65 74 20 6d 75 74 20 72 65 70 6c ....let mut repl
0f30: 79 3a 20 56 65 63 3c 53 74 72 69 6e 67 3e 20 3d y: Vec<String> =
0f40: 20 76 65 63 21 5b 5d 3b 0a 09 09 09 69 66 20 73 vec![];....if s
0f50: 65 6c 66 2e 66 69 65 6c 64 73 2e 63 6f 6e 74 61 elf.fields.conta
0f60: 69 6e 73 28 22 73 75 62 6a 65 63 74 22 29 20 7b ins("subject") {
0f70: 0a 09 09 09 09 69 66 20 6c 65 74 20 53 6f 6d 65 .....if let Some
0f80: 28 73 75 62 6a 65 63 74 29 20 3d 20 6d 61 69 6c (subject) = mail
0f90: 2e 73 75 62 6a 65 63 74 28 29 20 7b 0a 09 09 09 .subject() {....
0fa0: 09 09 72 65 70 6c 79 2e 70 75 73 68 28 66 6f 72 ..reply.push(for
0fb0: 6d 61 74 21 28 22 5f 5f 2a 53 75 62 6a 65 63 74 mat!("__*Subject
0fc0: 3a 2a 5f 5f e2 80 87 60 7b 7d 60 22 2c 20 65 6e :*__ `{}`", en
0fd0: 63 6f 64 65 28 73 75 62 6a 65 63 74 29 29 29 3b code(subject)));
0fe0: 0a 09 09 09 09 7d 20 65 6c 73 65 20 69 66 20 6c .....} else if l
0ff0: 65 74 20 53 6f 6d 65 28 74 68 72 65 61 64 29 20 et Some(thread)
1000: 3d 20 6d 61 69 6c 2e 74 68 72 65 61 64 5f 6e 61 = mail.thread_na
1010: 6d 65 28 29 20 7b 0a 09 09 09 09 09 72 65 70 6c me() {......repl
1020: 79 2e 70 75 73 68 28 66 6f 72 6d 61 74 21 28 22 y.push(format!("
1030: 5f 5f 2a 54 68 72 65 61 64 3a 2a 5f 5f e2 80 87 __*Thread:*__
1040: 60 7b 7d 60 22 2c 20 65 6e 63 6f 64 65 28 74 68 `{}`", encode(th
1050: 72 65 61 64 29 29 29 3b 0a 09 09 09 09 7d 0a 09 read)));.....}..
1060: 09 09 7d 0a 09 09 09 6c 65 74 20 6d 75 74 20 73 ..}....let mut s
1070: 68 6f 72 74 5f 68 65 61 64 65 72 73 3a 20 56 65 hort_headers: Ve
1080: 63 3c 53 74 72 69 6e 67 3e 20 3d 20 76 65 63 21 c<String> = vec!
1090: 5b 5d 3b 0a 09 09 09 2f 2f 20 64 6f 20 77 65 20 [];....// do we
10a0: 6e 65 65 64 20 74 6f 20 72 65 70 6c 61 63 65 20 need to replace
10b0: 73 70 61 63 65 73 20 68 65 72 65 3f 0a 09 09 09 spaces here?....
10c0: 69 66 20 73 65 6c 66 2e 66 69 65 6c 64 73 2e 63 if self.fields.c
10d0: 6f 6e 74 61 69 6e 73 28 22 66 72 6f 6d 22 29 20 ontains("from")
10e0: 7b 0a 09 09 09 09 73 68 6f 72 74 5f 68 65 61 64 {.....short_head
10f0: 65 72 73 2e 70 75 73 68 28 66 6f 72 6d 61 74 21 ers.push(format!
1100: 28 22 5f 5f 2a 46 72 6f 6d 3a 2a 5f 5f e2 80 87 ("__*From:*__
1110: 60 7b 7d 60 22 2c 20 65 6e 63 6f 64 65 28 26 68 `{}`", encode(&h
1120: 65 61 64 65 72 73 2e 66 72 6f 6d 29 29 29 3b 0a eaders.from)));.
1130: 09 09 09 7d 0a 09 09 09 69 66 20 73 65 6c 66 2e ...}....if self.
1140: 66 69 65 6c 64 73 2e 63 6f 6e 74 61 69 6e 73 28 fields.contains(
1150: 22 64 61 74 65 22 29 20 7b 0a 09 09 09 09 69 66 "date") {.....if
1160: 20 6c 65 74 20 53 6f 6d 65 28 64 61 74 65 29 20 let Some(date)
1170: 3d 20 6d 61 69 6c 2e 64 61 74 65 28 29 20 7b 0a = mail.date() {.
1180: 09 09 09 09 09 73 68 6f 72 74 5f 68 65 61 64 65 .....short_heade
1190: 72 73 2e 70 75 73 68 28 66 6f 72 6d 61 74 21 28 rs.push(format!(
11a0: 22 5f 5f 2a 44 61 74 65 3a 2a 5f 5f e2 80 87 60 "__*Date:*__ `
11b0: 7b 64 61 74 65 7d 60 22 29 29 3b 0a 09 09 09 09 {date}`"));.....
11c0: 7d 0a 09 09 09 7d 0a 09 09 09 72 65 70 6c 79 2e }....}....reply.
11d0: 70 75 73 68 28 73 68 6f 72 74 5f 68 65 61 64 65 push(short_heade
11e0: 72 73 2e 6a 6f 69 6e 28 22 20 22 29 29 3b 0a 09 rs.join(" "));..
11f0: 09 09 6c 65 74 20 68 65 61 64 65 72 5f 73 69 7a ..let header_siz
1200: 65 20 3d 20 72 65 70 6c 79 2e 6a 6f 69 6e 28 22 e = reply.join("
1210: 20 22 29 2e 6c 65 6e 28 29 20 2b 20 31 3b 0a 0a ").len() + 1;..
1220: 09 09 09 6c 65 74 20 68 74 6d 6c 5f 70 61 72 74 ...let html_part
1230: 73 20 3d 20 6d 61 69 6c 2e 68 74 6d 6c 5f 62 6f s = mail.html_bo
1240: 64 79 5f 63 6f 75 6e 74 28 29 3b 0a 09 09 09 6c dy_count();....l
1250: 65 74 20 74 65 78 74 5f 70 61 72 74 73 20 3d 20 et text_parts =
1260: 6d 61 69 6c 2e 74 65 78 74 5f 62 6f 64 79 5f 63 mail.text_body_c
1270: 6f 75 6e 74 28 29 3b 0a 09 09 09 6c 65 74 20 61 ount();....let a
1280: 74 74 61 63 68 6d 65 6e 74 73 20 3d 20 6d 61 69 ttachments = mai
1290: 6c 2e 61 74 74 61 63 68 6d 65 6e 74 5f 63 6f 75 l.attachment_cou
12a0: 6e 74 28 29 3b 0a 09 09 09 69 66 20 68 74 6d 6c nt();....if html
12b0: 5f 70 61 72 74 73 20 21 3d 20 74 65 78 74 5f 70 _parts != text_p
12c0: 61 72 74 73 20 7b 0a 09 09 09 09 73 65 6c 66 2e arts {.....self.
12d0: 74 67 2e 64 65 62 75 67 28 26 66 6f 72 6d 61 74 tg.debug(&format
12e0: 21 28 22 48 6d 2c 20 77 65 20 68 61 76 65 20 7b !("Hm, we have {
12f0: 68 74 6d 6c 5f 70 61 72 74 73 7d 20 48 54 4d 4c html_parts} HTML
1300: 20 70 61 72 74 73 20 61 6e 64 20 7b 74 65 78 74 parts and {text
1310: 5f 70 61 72 74 73 7d 20 74 65 78 74 20 70 61 72 _parts} text par
1320: 74 73 2e 22 29 29 2e 61 77 61 69 74 3f 3b 0a 09 ts.")).await?;..
1330: 09 09 7d 0a 09 09 09 2f 2f 6c 65 74 20 6d 75 74 ..}....//let mut
1340: 20 68 74 6d 6c 5f 6e 75 6d 20 3d 20 30 3b 0a 09 html_num = 0;..
1350: 09 09 6c 65 74 20 6d 75 74 20 74 65 78 74 5f 6e ..let mut text_n
1360: 75 6d 20 3d 20 30 3b 0a 09 09 09 6c 65 74 20 6d um = 0;....let m
1370: 75 74 20 66 69 6c 65 5f 6e 75 6d 20 3d 20 30 3b ut file_num = 0;
1380: 0a 09 09 09 2f 2f 20 6c 65 74 27 73 20 64 69 73 ....// let's dis
1390: 70 6c 61 79 20 66 69 72 73 74 20 68 74 6d 6c 20 play first html
13a0: 6f 72 20 74 65 78 74 20 70 61 72 74 20 61 73 20 or text part as
13b0: 62 6f 64 79 0a 09 09 09 6c 65 74 20 6d 75 74 20 body....let mut
13c0: 62 6f 64 79 3a 20 43 6f 77 3c 27 5f 2c 20 73 74 body: Cow<'_, st
13d0: 72 3e 20 3d 20 22 22 2e 69 6e 74 6f 28 29 3b 0a r> = "".into();.
13e0: 09 09 09 2f 2a 0a 09 09 09 20 2a 20 61 63 74 75 .../*.... * actu
13f0: 61 6c 6c 79 20 49 20 64 6f 6e 27 74 20 77 61 6e ally I don't wan
1400: 6e 61 20 70 61 72 73 65 20 74 68 61 74 20 68 74 na parse that ht
1410: 6d 6c 20 73 74 75 66 66 0a 09 09 09 69 66 20 68 ml stuff....if h
1420: 74 6d 6c 5f 70 61 72 74 73 20 3e 20 30 20 7b 0a tml_parts > 0 {.
1430: 09 09 09 09 6c 65 74 20 74 65 78 74 20 3d 20 6d ....let text = m
1440: 61 69 6c 2e 62 6f 64 79 5f 68 74 6d 6c 28 30 29 ail.body_html(0)
1450: 2e 73 74 61 63 6b 28 29 3f 3b 0a 09 09 09 09 69 .stack()?;.....i
1460: 66 20 74 65 78 74 2e 6c 65 6e 28 29 20 3c 20 34 f text.len() < 4
1470: 30 39 36 20 2d 20 68 65 61 64 65 72 5f 73 69 7a 096 - header_siz
1480: 65 20 7b 0a 09 09 09 09 09 62 6f 64 79 20 3d 20 e {......body =
1490: 74 65 78 74 3b 0a 09 09 09 09 09 68 74 6d 6c 5f text;......html_
14a0: 6e 75 6d 20 3d 20 31 3b 0a 09 09 09 09 7d 0a 09 num = 1;.....}..
14b0: 09 09 7d 3b 0a 09 09 09 2a 2f 0a 09 09 09 69 66 ..};....*/....if
14c0: 20 62 6f 64 79 2e 69 73 5f 65 6d 70 74 79 28 29 body.is_empty()
14d0: 20 26 26 20 74 65 78 74 5f 70 61 72 74 73 20 3e && text_parts >
14e0: 20 30 20 7b 0a 09 09 09 09 6c 65 74 20 74 65 78 0 {.....let tex
14f0: 74 20 3d 20 6d 61 69 6c 2e 62 6f 64 79 5f 74 65 t = mail.body_te
1500: 78 74 28 30 29 0a 09 09 09 09 09 2e 63 6f 6e 74 xt(0).......cont
1510: 65 78 74 28 22 46 61 69 6c 65 64 20 74 6f 20 65 ext("Failed to e
1520: 78 74 72 61 63 74 20 74 65 78 74 20 66 72 6f 6d xtract text from
1530: 20 6d 65 73 73 61 67 65 22 29 3f 3b 0a 09 09 09 message")?;....
1540: 09 69 66 20 74 65 78 74 2e 6c 65 6e 28 29 20 3c .if text.len() <
1550: 20 34 30 39 36 20 2d 20 68 65 61 64 65 72 5f 73 4096 - header_s
1560: 69 7a 65 20 7b 0a 09 09 09 09 09 62 6f 64 79 20 ize {......body
1570: 3d 20 74 65 78 74 3b 0a 09 09 09 09 09 74 65 78 = text;......tex
1580: 74 5f 6e 75 6d 20 3d 20 31 3b 0a 09 09 09 09 7d t_num = 1;.....}
1590: 0a 09 09 09 7d 3b 0a 09 09 09 72 65 70 6c 79 2e ....};....reply.
15a0: 70 75 73 68 28 22 60 60 60 22 2e 69 6e 74 6f 28 push("```".into(
15b0: 29 29 3b 0a 09 09 09 72 65 70 6c 79 2e 65 78 74 ));....reply.ext
15c0: 65 6e 64 28 62 6f 64 79 2e 6c 69 6e 65 73 28 29 end(body.lines()
15d0: 2e 6d 61 70 28 7c 78 7c 20 78 2e 69 6e 74 6f 28 .map(|x| x.into(
15e0: 29 29 29 3b 0a 09 09 09 72 65 70 6c 79 2e 70 75 )));....reply.pu
15f0: 73 68 28 22 60 60 60 22 2e 69 6e 74 6f 28 29 29 sh("```".into())
1600: 3b 0a 0a 09 09 09 2f 2f 20 61 6e 64 20 6c 65 74 ;.....// and let
1610: 27 73 20 63 6f 6c 6c 65 63 74 20 61 6c 6c 20 6f 's collect all o
1620: 74 68 65 72 20 61 74 74 61 63 68 6d 65 6e 74 20 ther attachment
1630: 70 61 72 74 73 0a 09 09 09 6c 65 74 20 6d 75 74 parts....let mut
1640: 20 66 69 6c 65 73 5f 74 6f 5f 73 65 6e 64 20 3d files_to_send =
1650: 20 76 65 63 21 5b 5d 3b 0a 09 09 09 2f 2a 0a 09 vec![];..../*..
1660: 09 09 20 2a 20 6c 65 74 27 73 20 6a 75 73 74 20 .. * let's just
1670: 73 6b 69 70 20 68 74 6d 6c 20 70 61 72 74 73 20 skip html parts
1680: 66 6f 72 20 6e 6f 77 2c 20 74 68 65 79 20 6a 75 for now, they ju
1690: 73 74 20 64 75 70 6c 69 63 61 74 65 20 74 65 78 st duplicate tex
16a0: 74 3f 0a 09 09 09 77 68 69 6c 65 20 68 74 6d 6c t?....while html
16b0: 5f 6e 75 6d 20 3c 20 68 74 6d 6c 5f 70 61 72 74 _num < html_part
16c0: 73 20 7b 0a 09 09 09 09 66 69 6c 65 73 5f 74 6f s {.....files_to
16d0: 5f 73 65 6e 64 2e 70 75 73 68 28 6d 61 69 6c 2e _send.push(mail.
16e0: 68 74 6d 6c 5f 70 61 72 74 28 68 74 6d 6c 5f 6e html_part(html_n
16f0: 75 6d 29 2e 73 74 61 63 6b 28 29 3f 29 3b 0a 09 um).stack()?);..
1700: 09 09 09 68 74 6d 6c 5f 6e 75 6d 20 2b 3d 20 31 ...html_num += 1
1710: 3b 0a 09 09 09 7d 0a 09 09 09 2a 2f 0a 09 09 09 ;....}....*/....
1720: 77 68 69 6c 65 20 74 65 78 74 5f 6e 75 6d 20 3c while text_num <
1730: 20 74 65 78 74 5f 70 61 72 74 73 20 7b 0a 09 09 text_parts {...
1740: 09 09 66 69 6c 65 73 5f 74 6f 5f 73 65 6e 64 2e ..files_to_send.
1750: 70 75 73 68 28 6d 61 69 6c 2e 74 65 78 74 5f 70 push(mail.text_p
1760: 61 72 74 28 74 65 78 74 5f 6e 75 6d 2e 74 72 79 art(text_num.try
1770: 5f 69 6e 74 6f 28 29 2e 73 74 61 63 6b 28 29 3f _into().stack()?
1780: 29 0a 09 09 09 09 09 2e 63 6f 6e 74 65 78 74 28 ).......context(
1790: 22 46 61 69 6c 65 64 20 74 6f 20 67 65 74 20 74 "Failed to get t
17a0: 65 78 74 20 70 61 72 74 20 66 72 6f 6d 20 6d 65 ext part from me
17b0: 73 73 61 67 65 2e 22 29 3f 29 3b 0a 09 09 09 09 ssage.")?);.....
17c0: 74 65 78 74 5f 6e 75 6d 20 2b 3d 20 31 3b 0a 09 text_num += 1;..
17d0: 09 09 7d 0a 09 09 09 77 68 69 6c 65 20 66 69 6c ..}....while fil
17e0: 65 5f 6e 75 6d 20 3c 20 61 74 74 61 63 68 6d 65 e_num < attachme
17f0: 6e 74 73 20 7b 0a 09 09 09 09 66 69 6c 65 73 5f nts {.....files_
1800: 74 6f 5f 73 65 6e 64 2e 70 75 73 68 28 6d 61 69 to_send.push(mai
1810: 6c 2e 61 74 74 61 63 68 6d 65 6e 74 28 66 69 6c l.attachment(fil
1820: 65 5f 6e 75 6d 2e 74 72 79 5f 69 6e 74 6f 28 29 e_num.try_into()
1830: 2e 73 74 61 63 6b 28 29 3f 29 0a 09 09 09 09 09 .stack()?)......
1840: 2e 63 6f 6e 74 65 78 74 28 22 46 61 69 6c 65 64 .context("Failed
1850: 20 74 6f 20 67 65 74 20 66 69 6c 65 20 70 61 72 to get file par
1860: 74 20 66 72 6f 6d 20 6d 65 73 73 61 67 65 2e 22 t from message."
1870: 29 3f 29 3b 0a 09 09 09 09 66 69 6c 65 5f 6e 75 )?);.....file_nu
1880: 6d 20 2b 3d 20 31 3b 0a 09 09 09 7d 0a 0a 09 09 m += 1;....}....
1890: 09 6c 65 74 20 6d 73 67 20 3d 20 72 65 70 6c 79 .let msg = reply
18a0: 2e 6a 6f 69 6e 28 22 5c 6e 22 29 3b 0a 09 09 09 .join("\n");....
18b0: 66 6f 72 20 63 68 61 74 20 69 6e 20 72 63 70 74 for chat in rcpt
18c0: 20 7b 0a 09 09 09 09 69 66 20 21 66 69 6c 65 73 {.....if !files
18d0: 5f 74 6f 5f 73 65 6e 64 2e 69 73 5f 65 6d 70 74 _to_send.is_empt
18e0: 79 28 29 20 7b 0a 09 09 09 09 09 6c 65 74 20 6d y() {......let m
18f0: 75 74 20 66 69 6c 65 73 20 3d 20 76 65 63 21 5b ut files = vec![
1900: 5d 3b 0a 09 09 09 09 09 2f 2f 20 6c 65 74 20 6d ];......// let m
1910: 75 74 20 66 69 72 73 74 5f 6f 6e 65 20 3d 20 74 ut first_one = t
1920: 72 75 65 3b 0a 09 09 09 09 09 66 6f 72 20 63 68 rue;......for ch
1930: 75 6e 6b 20 69 6e 20 26 66 69 6c 65 73 5f 74 6f unk in &files_to
1940: 5f 73 65 6e 64 20 7b 0a 09 09 09 09 09 09 6c 65 _send {.......le
1950: 74 20 64 61 74 61 3a 20 56 65 63 3c 75 38 3e 20 t data: Vec<u8>
1960: 3d 20 63 68 75 6e 6b 2e 63 6f 6e 74 65 6e 74 73 = chunk.contents
1970: 28 29 2e 74 6f 5f 76 65 63 28 29 3b 0a 09 09 09 ().to_vec();....
1980: 09 09 09 6c 65 74 20 6d 75 74 20 66 69 6c 65 6e ...let mut filen
1990: 61 6d 65 3a 20 4f 70 74 69 6f 6e 3c 53 74 72 69 ame: Option<Stri
19a0: 6e 67 3e 20 3d 20 4e 6f 6e 65 3b 0a 09 09 09 09 ng> = None;.....
19b0: 09 09 66 6f 72 20 68 65 61 64 65 72 20 69 6e 20 ..for header in
19c0: 63 68 75 6e 6b 2e 68 65 61 64 65 72 73 28 29 20 chunk.headers()
19d0: 7b 0a 09 09 09 09 09 09 09 69 66 20 68 65 61 64 {........if head
19e0: 65 72 2e 6e 61 6d 65 28 29 20 3d 3d 20 22 43 6f er.name() == "Co
19f0: 6e 74 65 6e 74 2d 54 79 70 65 22 20 7b 0a 09 09 ntent-Type" {...
1a00: 09 09 09 09 09 09 6d 61 74 63 68 20 68 65 61 64 ......match head
1a10: 65 72 2e 76 61 6c 75 65 28 29 20 7b 0a 09 09 09 er.value() {....
1a20: 09 09 09 09 09 09 6d 61 69 6c 5f 70 61 72 73 65 ......mail_parse
1a30: 72 3a 3a 48 65 61 64 65 72 56 61 6c 75 65 3a 3a r::HeaderValue::
1a40: 43 6f 6e 74 65 6e 74 54 79 70 65 28 63 6f 6e 74 ContentType(cont
1a50: 65 6e 74 74 79 70 65 29 20 3d 3e 20 7b 0a 09 09 enttype) => {...
1a60: 09 09 09 09 09 09 09 09 69 66 20 6c 65 74 20 53 ........if let S
1a70: 6f 6d 65 28 66 6e 61 6d 65 29 20 3d 20 63 6f 6e ome(fname) = con
1a80: 74 65 6e 74 74 79 70 65 2e 61 74 74 72 69 62 75 tenttype.attribu
1a90: 74 65 28 22 6e 61 6d 65 22 29 20 7b 0a 09 09 09 te("name") {....
1aa0: 09 09 09 09 09 09 09 09 66 69 6c 65 6e 61 6d 65 ........filename
1ab0: 20 3d 20 53 6f 6d 65 28 66 6e 61 6d 65 2e 74 6f = Some(fname.to
1ac0: 5f 6f 77 6e 65 64 28 29 29 3b 0a 09 09 09 09 09 _owned());......
1ad0: 09 09 09 09 09 7d 0a 09 09 09 09 09 09 09 09 09 .....}..........
1ae0: 7d 2c 0a 09 09 09 09 09 09 09 09 09 5f 20 3d 3e },.........._ =>
1af0: 20 7b 0a 09 09 09 09 09 09 09 09 09 09 73 65 6c {...........sel
1b00: 66 2e 74 67 2e 64 65 62 75 67 28 22 41 74 74 61 f.tg.debug("Atta
1b10: 63 68 6d 65 6e 74 20 68 61 73 20 62 61 64 20 43 chment has bad C
1b20: 6f 6e 74 65 6e 74 54 79 70 65 20 68 65 61 64 65 ontentType heade
1b30: 72 2e 22 29 2e 61 77 61 69 74 3f 3b 0a 09 09 09 r.").await?;....
1b40: 09 09 09 09 09 09 7d 2c 0a 09 09 09 09 09 09 09 ......},........
1b50: 09 7d 3b 0a 09 09 09 09 09 09 09 7d 3b 0a 09 09 .};........};...
1b60: 09 09 09 09 7d 3b 0a 09 09 09 09 09 09 6c 65 74 ....};.......let
1b70: 20 66 69 6c 65 6e 61 6d 65 20 3d 20 69 66 20 6c filename = if l
1b80: 65 74 20 53 6f 6d 65 28 66 6e 61 6d 65 29 20 3d et Some(fname) =
1b90: 20 66 69 6c 65 6e 61 6d 65 20 7b 0a 09 09 09 09 filename {.....
1ba0: 09 09 09 66 6e 61 6d 65 0a 09 09 09 09 09 09 7d ...fname.......}
1bb0: 20 65 6c 73 65 20 7b 0a 09 09 09 09 09 09 09 22 else {........"
1bc0: 41 74 74 61 63 68 6d 65 6e 74 2e 74 78 74 22 2e Attachment.txt".
1bd0: 69 6e 74 6f 28 29 0a 09 09 09 09 09 09 7d 3b 0a into().......};.
1be0: 09 09 09 09 09 09 66 69 6c 65 73 2e 70 75 73 68 ......files.push
1bf0: 28 41 74 74 61 63 68 6d 65 6e 74 20 7b 0a 09 09 (Attachment {...
1c00: 09 09 09 09 09 64 61 74 61 3a 20 43 75 72 73 6f .....data: Curso
1c10: 72 3a 3a 6e 65 77 28 64 61 74 61 29 2c 0a 09 09 r::new(data),...
1c20: 09 09 09 09 09 6e 61 6d 65 3a 20 66 69 6c 65 6e .....name: filen
1c30: 61 6d 65 2c 0a 09 09 09 09 09 09 7d 29 3b 0a 09 ame,.......});..
1c40: 09 09 09 09 7d 0a 09 09 09 09 09 73 65 6c 66 2e ....}......self.
1c50: 74 67 2e 73 65 6e 64 67 72 6f 75 70 28 63 68 61 tg.sendgroup(cha
1c60: 74 2c 20 66 69 6c 65 73 2c 20 26 6d 73 67 29 2e t, files, &msg).
1c70: 61 77 61 69 74 3f 3b 0a 09 09 09 09 7d 20 65 6c await?;.....} el
1c80: 73 65 20 7b 0a 09 09 09 09 09 73 65 6c 66 2e 74 se {......self.t
1c90: 67 2e 73 65 6e 64 28 63 68 61 74 2c 20 26 6d 73 g.send(chat, &ms
1ca0: 67 29 2e 61 77 61 69 74 3f 3b 0a 09 09 09 09 7d g).await?;.....}
1cb0: 0a 09 09 09 7d 0a 09 09 7d 20 65 6c 73 65 20 7b ....}...} else {
1cc0: 0a 09 09 09 62 61 69 6c 21 28 22 52 65 71 75 69 ....bail!("Requi
1cd0: 72 65 64 20 68 65 61 64 65 72 73 20 77 65 72 65 red headers were
1ce0: 20 6e 6f 74 20 66 6f 75 6e 64 2e 22 29 3b 0a 09 not found.");..
1cf0: 09 7d 0a 09 09 4f 6b 28 28 29 29 0a 09 7d 0a 7d .}...Ok(())..}.}
1d00: 0a 0a 69 6d 70 6c 20 6d 61 69 6c 69 6e 5f 65 6d ..impl mailin_em
1d10: 62 65 64 64 65 64 3a 3a 48 61 6e 64 6c 65 72 20 bedded::Handler
1d20: 66 6f 72 20 4d 61 69 6c 53 65 72 76 65 72 20 7b for MailServer {
1d30: 0a 09 2f 2f 2f 20 4a 75 73 74 20 64 65 6e 79 20 ../// Just deny
1d40: 6c 6f 67 69 6e 20 61 75 74 68 0a 09 66 6e 20 61 login auth..fn a
1d50: 75 74 68 5f 6c 6f 67 69 6e 20 28 26 6d 75 74 20 uth_login (&mut
1d60: 73 65 6c 66 2c 20 5f 75 73 65 72 6e 61 6d 65 3a self, _username:
1d70: 20 26 73 74 72 2c 20 5f 70 61 73 73 77 6f 72 64 &str, _password
1d80: 3a 20 26 73 74 72 29 20 2d 3e 20 52 65 73 70 6f : &str) -> Respo
1d90: 6e 73 65 20 7b 0a 09 09 49 4e 56 41 4c 49 44 5f nse {...INVALID_
1da0: 43 52 45 44 45 4e 54 49 41 4c 53 0a 09 7d 0a 0a CREDENTIALS..}..
1db0: 09 2f 2f 2f 20 4a 75 73 74 20 64 65 6e 79 20 70 ./// Just deny p
1dc0: 6c 61 69 6e 20 61 75 74 68 0a 09 66 6e 20 61 75 lain auth..fn au
1dd0: 74 68 5f 70 6c 61 69 6e 20 28 26 6d 75 74 20 73 th_plain (&mut s
1de0: 65 6c 66 2c 20 5f 61 75 74 68 6f 72 69 7a 61 74 elf, _authorizat
1df0: 69 6f 6e 5f 69 64 3a 20 26 73 74 72 2c 20 5f 61 ion_id: &str, _a
1e00: 75 74 68 65 6e 74 69 63 61 74 69 6f 6e 5f 69 64 uthentication_id
1e10: 3a 20 26 73 74 72 2c 20 5f 70 61 73 73 77 6f 72 : &str, _passwor
1e20: 64 3a 20 26 73 74 72 29 20 2d 3e 20 52 65 73 70 d: &str) -> Resp
1e30: 6f 6e 73 65 20 7b 0a 09 09 49 4e 56 41 4c 49 44 onse {...INVALID
1e40: 5f 43 52 45 44 45 4e 54 49 41 4c 53 0a 09 7d 0a _CREDENTIALS..}.
1e50: 0a 09 2f 2f 2f 20 56 65 72 69 66 79 20 77 68 65 ../// Verify whe
1e60: 74 68 65 72 20 61 64 64 72 65 73 73 20 69 73 20 ther address is
1e70: 64 65 6c 69 76 65 72 61 62 6c 65 0a 09 66 6e 20 deliverable..fn
1e80: 72 63 70 74 20 28 26 6d 75 74 20 73 65 6c 66 2c rcpt (&mut self,
1e90: 20 74 6f 3a 20 26 73 74 72 29 20 2d 3e 20 52 65 to: &str) -> Re
1ea0: 73 70 6f 6e 73 65 20 7b 0a 09 09 69 66 20 73 65 sponse {...if se
1eb0: 6c 66 2e 72 65 6c 61 79 20 7b 0a 09 09 09 4f 4b lf.relay {....OK
1ec0: 0a 09 09 7d 20 65 6c 73 65 20 7b 0a 09 09 09 6d ...} else {....m
1ed0: 61 74 63 68 20 73 65 6c 66 2e 67 65 74 5f 69 64 atch self.get_id
1ee0: 28 74 6f 29 20 7b 0a 09 09 09 09 4f 6b 28 5f 29 (to) {.....Ok(_)
1ef0: 20 3d 3e 20 4f 4b 2c 0a 09 09 09 09 45 72 72 28 => OK,.....Err(
1f00: 5f 29 20 3d 3e 20 7b 0a 09 09 09 09 09 69 66 20 _) => {......if
1f10: 73 65 6c 66 2e 72 65 6c 61 79 20 7b 0a 09 09 09 self.relay {....
1f20: 09 09 09 4f 4b 0a 09 09 09 09 09 7d 20 65 6c 73 ...OK......} els
1f30: 65 20 7b 0a 09 09 09 09 09 09 4e 4f 5f 4d 41 49 e {.......NO_MAI
1f40: 4c 42 4f 58 0a 09 09 09 09 09 7d 0a 09 09 09 09 LBOX......}.....
1f50: 7d 0a 09 09 09 7d 0a 09 09 7d 0a 09 7d 0a 0a 09 }....}...}..}...
1f60: 2f 2f 2f 20 53 61 76 65 20 68 65 61 64 65 72 73 /// Save headers
1f70: 20 77 65 20 6e 65 65 64 0a 09 66 6e 20 64 61 74 we need..fn dat
1f80: 61 5f 73 74 61 72 74 20 28 26 6d 75 74 20 73 65 a_start (&mut se
1f90: 6c 66 2c 20 5f 64 6f 6d 61 69 6e 3a 20 26 73 74 lf, _domain: &st
1fa0: 72 2c 20 66 72 6f 6d 3a 20 26 73 74 72 2c 20 5f r, from: &str, _
1fb0: 69 73 38 62 69 74 3a 20 62 6f 6f 6c 2c 20 74 6f is8bit: bool, to
1fc0: 3a 20 26 5b 53 74 72 69 6e 67 5d 29 20 2d 3e 20 : &[String]) ->
1fd0: 52 65 73 70 6f 6e 73 65 20 7b 0a 09 09 73 65 6c Response {...sel
1fe0: 66 2e 68 65 61 64 65 72 73 20 3d 20 53 6f 6d 65 f.headers = Some
1ff0: 28 53 6f 6d 65 48 65 61 64 65 72 73 7b 0a 09 09 (SomeHeaders{...
2000: 09 66 72 6f 6d 3a 20 66 72 6f 6d 2e 74 6f 5f 73 .from: from.to_s
2010: 74 72 69 6e 67 28 29 2c 0a 09 09 09 74 6f 3a 20 tring(),....to:
2020: 74 6f 2e 74 6f 5f 76 65 63 28 29 2c 0a 09 09 7d to.to_vec(),...}
2030: 29 3b 0a 09 09 4f 4b 0a 09 7d 0a 0a 09 2f 2f 2f );...OK..}...///
2040: 20 53 61 76 65 20 63 68 75 6e 6b 28 3f 29 20 6f Save chunk(?) o
2050: 66 20 64 61 74 61 0a 09 66 6e 20 64 61 74 61 20 f data..fn data
2060: 28 26 6d 75 74 20 73 65 6c 66 2c 20 62 75 66 3a (&mut self, buf:
2070: 20 26 5b 75 38 5d 29 20 2d 3e 20 73 74 64 3a 3a &[u8]) -> std::
2080: 72 65 73 75 6c 74 3a 3a 52 65 73 75 6c 74 3c 28 result::Result<(
2090: 29 2c 20 45 72 72 6f 72 3e 20 7b 0a 09 09 73 65 ), Error> {...se
20a0: 6c 66 2e 64 61 74 61 2e 61 70 70 65 6e 64 28 62 lf.data.append(b
20b0: 75 66 2e 74 6f 5f 76 65 63 28 29 2e 61 73 5f 6d uf.to_vec().as_m
20c0: 75 74 28 29 29 3b 0a 09 09 4f 6b 28 28 29 29 0a ut());...Ok(()).
20d0: 09 7d 0a 0a 09 2f 2f 2f 20 41 74 74 65 6d 70 74 .}.../// Attempt
20e0: 20 74 6f 20 73 65 6e 64 20 65 6d 61 69 6c 2c 20 to send email,
20f0: 72 65 74 75 72 6e 20 74 65 6d 70 6f 72 61 72 79 return temporary
2100: 20 65 72 72 6f 72 20 69 66 20 74 68 61 74 20 66 error if that f
2110: 61 69 6c 73 0a 09 66 6e 20 64 61 74 61 5f 65 6e ails..fn data_en
2120: 64 20 28 26 6d 75 74 20 73 65 6c 66 29 20 2d 3e d (&mut self) ->
2130: 20 52 65 73 70 6f 6e 73 65 20 7b 0a 09 09 6c 65 Response {...le
2140: 74 20 6d 75 74 20 72 65 73 75 6c 74 20 3d 20 4f t mut result = O
2150: 4b 3b 0a 09 09 73 6d 6f 6c 3a 3a 62 6c 6f 63 6b K;...smol::block
2160: 5f 6f 6e 28 61 73 79 6e 63 20 7b 0a 09 09 09 2f _on(async {..../
2170: 2f 20 72 65 6c 61 79 20 6d 61 69 6c 0a 09 09 09 / relay mail....
2180: 69 66 20 6c 65 74 20 45 72 72 28 65 72 72 29 20 if let Err(err)
2190: 3d 20 73 65 6c 66 2e 72 65 6c 61 79 5f 6d 61 69 = self.relay_mai
21a0: 6c 28 29 2e 61 77 61 69 74 20 7b 0a 09 09 09 09 l().await {.....
21b0: 72 65 73 75 6c 74 20 3d 20 49 4e 54 45 52 4e 41 result = INTERNA
21c0: 4c 5f 45 52 52 4f 52 3b 0a 09 09 09 09 2f 2f 20 L_ERROR;.....//
21d0: 69 6e 20 63 61 73 65 20 74 68 61 74 20 66 61 69 in case that fai
21e0: 6c 73 20 2d 20 69 6e 66 6f 72 6d 20 64 65 66 61 ls - inform defa
21f0: 75 6c 74 20 72 65 63 69 70 69 65 6e 74 0a 09 09 ult recipient...
2200: 09 09 69 66 20 6c 65 74 20 45 72 72 28 65 72 72 ..if let Err(err
2210: 29 20 3d 20 73 65 6c 66 2e 74 67 2e 64 65 62 75 ) = self.tg.debu
2220: 67 28 26 66 6f 72 6d 61 74 21 28 22 53 65 6e 64 g(&format!("Send
2230: 69 6e 67 20 65 6d 61 69 6c 73 20 66 61 69 6c 65 ing emails faile
2240: 64 3a 5c 6e 7b 65 72 72 3a 3f 7d 22 29 29 2e 61 d:\n{err:?}")).a
2250: 77 61 69 74 20 7b 0a 09 09 09 09 09 2f 2f 20 69 wait {......// i
2260: 6e 20 63 61 73 65 20 74 68 61 74 20 61 6c 73 6f n case that also
2270: 20 66 61 69 6c 73 20 2d 20 77 72 69 74 65 20 73 fails - write s
2280: 6f 6d 65 20 6c 6f 67 73 20 61 6e 64 20 62 61 69 ome logs and bai
2290: 6c 0a 09 09 09 09 09 65 70 72 69 6e 74 6c 6e 21 l......eprintln!
22a0: 28 22 7b 65 72 72 3a 3f 7d 22 29 3b 0a 09 09 09 ("{err:?}");....
22b0: 09 7d 3b 0a 09 09 09 7d 3b 0a 09 09 7d 29 3b 0a .};....};...});.
22c0: 09 09 2f 2f 20 63 6c 65 61 72 20 2d 20 6a 75 73 ..// clear - jus
22d0: 74 20 69 6e 20 63 61 73 65 0a 09 09 73 65 6c 66 t in case...self
22e0: 2e 64 61 74 61 20 3d 20 76 65 63 21 5b 5d 3b 0a .data = vec![];.
22f0: 09 09 73 65 6c 66 2e 68 65 61 64 65 72 73 20 3d ..self.headers =
2300: 20 4e 6f 6e 65 3b 0a 09 09 72 65 73 75 6c 74 0a None;...result.
2310: 09 7d 0a 7d 0a .}.}.