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 54 65 6c 65 67 72 61 6d 54 72 61 6e 73 70 6f :TelegramTranspo
0030: 72 74 2c 0a 09 75 74 69 6c 73 3a 3a 7b 0a 09 09 rt,..utils::{...
0040: 41 74 74 61 63 68 6d 65 6e 74 2c 0a 09 09 52 45 Attachment,...RE
0050: 5f 44 4f 4d 41 49 4e 2c 0a 09 09 76 61 6c 69 64 _DOMAIN,...valid
0060: 61 74 65 2c 0a 09 7d 2c 0a 7d 3b 0a 0a 75 73 65 ate,..},.};..use
0070: 20 73 74 64 3a 3a 7b 0a 09 62 6f 72 72 6f 77 3a std::{..borrow:
0080: 3a 43 6f 77 2c 0a 09 63 6f 6c 6c 65 63 74 69 6f :Cow,..collectio
0090: 6e 73 3a 3a 7b 0a 09 09 48 61 73 68 4d 61 70 2c ns::{...HashMap,
00a0: 0a 09 09 48 61 73 68 53 65 74 2c 0a 09 7d 2c 0a ...HashSet,..},.
00b0: 09 69 6f 3a 3a 45 72 72 6f 72 2c 0a 09 73 79 6e .io::Error,..syn
00c0: 63 3a 3a 41 72 63 2c 0a 7d 3b 0a 0a 75 73 65 20 c::Arc,.};..use
00d0: 61 73 79 6e 63 5f 63 6f 6d 70 61 74 3a 3a 43 6f async_compat::Co
00e0: 6d 70 61 74 3b 0a 75 73 65 20 6d 61 69 6c 69 6e mpat;.use mailin
00f0: 5f 65 6d 62 65 64 64 65 64 3a 3a 7b 0a 09 52 65 _embedded::{..Re
0100: 73 70 6f 6e 73 65 2c 0a 09 72 65 73 70 6f 6e 73 sponse,..respons
0110: 65 3a 3a 7b 0a 09 09 49 4e 54 45 52 4e 41 4c 5f e::{...INTERNAL_
0120: 45 52 52 4f 52 2c 0a 09 09 49 4e 56 41 4c 49 44 ERROR,...INVALID
0130: 5f 43 52 45 44 45 4e 54 49 41 4c 53 2c 0a 09 09 _CREDENTIALS,...
0140: 4e 4f 5f 4d 41 49 4c 42 4f 58 2c 0a 09 09 4f 4b NO_MAILBOX,...OK
0150: 0a 09 7d 2c 0a 7d 3b 0a 75 73 65 20 72 65 67 65 ..},.};.use rege
0160: 78 3a 3a 7b 0a 09 52 65 67 65 78 2c 0a 09 65 73 x::{..Regex,..es
0170: 63 61 70 65 2c 0a 7d 3b 0a 75 73 65 20 73 74 61 cape,.};.use sta
0180: 63 6b 65 64 5f 65 72 72 6f 72 73 3a 3a 7b 0a 09 cked_errors::{..
0190: 52 65 73 75 6c 74 2c 0a 09 53 74 61 63 6b 61 62 Result,..Stackab
01a0: 6c 65 45 72 72 2c 0a 09 62 61 69 6c 2c 0a 7d 3b leErr,..bail,.};
01b0: 0a 75 73 65 20 74 67 62 6f 74 3a 3a 74 79 70 65 .use tgbot::type
01c0: 73 3a 3a 43 68 61 74 50 65 65 72 49 64 3b 0a 0a s::ChatPeerId;..
01d0: 2f 2f 2f 20 60 53 6f 6d 65 48 65 61 64 65 72 73 /// `SomeHeaders
01e0: 60 20 6f 62 6a 65 63 74 20 74 6f 20 73 74 6f 72 ` object to stor
01f0: 65 20 64 61 74 61 20 74 68 72 6f 75 67 68 20 53 e data through S
0200: 4d 54 50 20 73 65 73 73 69 6f 6e 0a 23 5b 64 65 MTP session.#[de
0210: 72 69 76 65 28 43 6c 6f 6e 65 2c 20 44 65 62 75 rive(Clone, Debu
0220: 67 29 5d 0a 73 74 72 75 63 74 20 53 6f 6d 65 48 g)].struct SomeH
0230: 65 61 64 65 72 73 20 7b 0a 09 66 72 6f 6d 3a 20 eaders {..from:
0240: 53 74 72 69 6e 67 2c 0a 09 74 6f 3a 20 56 65 63 String,..to: Vec
0250: 3c 53 74 72 69 6e 67 3e 2c 0a 7d 0a 0a 2f 2f 2f <String>,.}..///
0260: 20 60 4d 61 69 6c 53 65 72 76 65 72 60 20 43 65 `MailServer` Ce
0270: 6e 74 72 61 6c 20 6f 62 6a 65 63 74 20 77 69 74 ntral object wit
0280: 68 20 54 47 20 61 70 69 20 61 6e 64 20 63 6f 6e h TG api and con
0290: 66 69 67 75 72 61 74 69 6f 6e 0a 23 5b 64 65 72 figuration.#[der
02a0: 69 76 65 28 43 6c 6f 6e 65 2c 20 44 65 62 75 67 ive(Clone, Debug
02b0: 29 5d 0a 70 75 62 20 73 74 72 75 63 74 20 4d 61 )].pub struct Ma
02c0: 69 6c 53 65 72 76 65 72 20 7b 0a 09 64 61 74 61 ilServer {..data
02d0: 3a 20 56 65 63 3c 75 38 3e 2c 0a 09 68 65 61 64 : Vec<u8>,..head
02e0: 65 72 73 3a 20 4f 70 74 69 6f 6e 3c 53 6f 6d 65 ers: Option<Some
02f0: 48 65 61 64 65 72 73 3e 2c 0a 09 72 65 6c 61 79 Headers>,..relay
0300: 3a 20 62 6f 6f 6c 2c 0a 09 74 67 3a 20 41 72 63 : bool,..tg: Arc
0310: 3c 54 65 6c 65 67 72 61 6d 54 72 61 6e 73 70 6f <TelegramTranspo
0320: 72 74 3e 2c 0a 09 66 69 65 6c 64 73 3a 20 48 61 rt>,..fields: Ha
0330: 73 68 53 65 74 3c 53 74 72 69 6e 67 3e 2c 0a 09 shSet<String>,..
0340: 61 64 64 72 65 73 73 3a 20 52 65 67 65 78 2c 0a address: Regex,.
0350: 7d 0a 0a 69 6d 70 6c 20 4d 61 69 6c 53 65 72 76 }..impl MailServ
0360: 65 72 20 7b 0a 09 2f 2f 2f 20 49 6e 69 74 69 61 er {../// Initia
0370: 6c 69 7a 65 20 41 50 49 20 61 6e 64 20 72 65 61 lize API and rea
0380: 64 20 63 6f 6e 66 69 67 75 72 61 74 69 6f 6e 0a d configuration.
0390: 09 70 75 62 20 66 6e 20 6e 65 77 28 73 65 74 74 .pub fn new(sett
03a0: 69 6e 67 73 3a 20 63 6f 6e 66 69 67 3a 3a 43 6f ings: config::Co
03b0: 6e 66 69 67 29 20 2d 3e 20 52 65 73 75 6c 74 3c nfig) -> Result<
03c0: 4d 61 69 6c 53 65 72 76 65 72 3e 20 7b 0a 09 09 MailServer> {...
03d0: 6c 65 74 20 61 70 69 5f 6b 65 79 20 3d 20 73 65 let api_key = se
03e0: 74 74 69 6e 67 73 2e 67 65 74 5f 73 74 72 69 6e ttings.get_strin
03f0: 67 28 22 61 70 69 5f 6b 65 79 22 29 0a 09 09 09 g("api_key")....
0400: 2e 63 6f 6e 74 65 78 74 28 22 5b 73 6d 74 70 32 .context("[smtp2
0410: 74 67 2e 74 6f 6d 6c 5d 20 6d 69 73 73 69 6e 67 tg.toml] missing
0420: 20 5c 22 61 70 69 5f 6b 65 79 5c 22 20 70 61 72 \"api_key\" par
0430: 61 6d 65 74 65 72 2e 5c 6e 22 29 3f 3b 0a 09 09 ameter.\n")?;...
0440: 6c 65 74 20 6d 75 74 20 72 65 63 69 70 69 65 6e let mut recipien
0450: 74 73 20 3d 20 48 61 73 68 4d 61 70 3a 3a 6e 65 ts = HashMap::ne
0460: 77 28 29 3b 0a 09 09 66 6f 72 20 28 6e 61 6d 65 w();...for (name
0470: 2c 20 76 61 6c 75 65 29 20 69 6e 20 73 65 74 74 , value) in sett
0480: 69 6e 67 73 2e 67 65 74 5f 74 61 62 6c 65 28 22 ings.get_table("
0490: 72 65 63 69 70 69 65 6e 74 73 22 29 0a 09 09 09 recipients")....
04a0: 2e 65 78 70 65 63 74 28 22 5b 73 6d 74 70 32 74 .expect("[smtp2t
04b0: 67 2e 74 6f 6d 6c 5d 20 6d 69 73 73 69 6e 67 20 g.toml] missing
04c0: 74 61 62 6c 65 20 5c 22 72 65 63 69 70 69 65 6e table \"recipien
04d0: 74 73 5c 22 2e 5c 6e 22 29 0a 09 09 7b 0a 09 09 ts\".\n")...{...
04e0: 09 6c 65 74 20 76 61 6c 75 65 20 3d 20 76 61 6c .let value = val
04f0: 75 65 2e 69 6e 74 6f 5f 69 6e 74 28 29 0a 09 09 ue.into_int()...
0500: 09 09 2e 63 6f 6e 74 65 78 74 28 22 5b 73 6d 74 ...context("[smt
0510: 70 32 74 67 2e 74 6f 6d 6c 5d 20 5c 22 72 65 63 p2tg.toml] \"rec
0520: 69 70 69 65 6e 74 5c 22 20 74 61 62 6c 65 20 76 ipient\" table v
0530: 61 6c 75 65 73 20 73 68 6f 75 6c 64 20 62 65 20 alues should be
0540: 69 6e 74 65 67 65 72 73 2e 5c 6e 22 29 3f 3b 0a integers.\n")?;.
0550: 09 09 09 72 65 63 69 70 69 65 6e 74 73 2e 69 6e ...recipients.in
0560: 73 65 72 74 28 6e 61 6d 65 2c 20 76 61 6c 75 65 sert(name, value
0570: 29 3b 0a 09 09 7d 0a 0a 09 09 6c 65 74 20 74 67 );...}....let tg
0580: 20 3d 20 41 72 63 3a 3a 6e 65 77 28 54 65 6c 65 = Arc::new(Tele
0590: 67 72 61 6d 54 72 61 6e 73 70 6f 72 74 3a 3a 6e gramTransport::n
05a0: 65 77 28 61 70 69 5f 6b 65 79 2c 20 72 65 63 69 ew(api_key, reci
05b0: 70 69 65 6e 74 73 2c 20 26 73 65 74 74 69 6e 67 pients, &setting
05c0: 73 29 3f 29 3b 0a 09 09 6c 65 74 20 66 69 65 6c s)?);...let fiel
05d0: 64 73 20 3d 20 48 61 73 68 53 65 74 3a 3a 3c 53 ds = HashSet::<S
05e0: 74 72 69 6e 67 3e 3a 3a 66 72 6f 6d 5f 69 74 65 tring>::from_ite
05f0: 72 28 73 65 74 74 69 6e 67 73 2e 67 65 74 5f 61 r(settings.get_a
0600: 72 72 61 79 28 22 66 69 65 6c 64 73 22 29 0a 09 rray("fields")..
0610: 09 09 2e 65 78 70 65 63 74 28 22 5b 73 6d 74 70 ...expect("[smtp
0620: 32 74 67 2e 74 6f 6d 6c 5d 20 5c 22 66 69 65 6c 2tg.toml] \"fiel
0630: 64 73 5c 22 20 73 68 6f 75 6c 64 20 62 65 20 61 ds\" should be a
0640: 6e 20 61 72 72 61 79 22 29 0a 09 09 09 2e 69 74 n array").....it
0650: 65 72 28 29 2e 6d 61 70 28 7c 78 7c 20 78 2e 63 er().map(|x| x.c
0660: 6c 6f 6e 65 28 29 2e 69 6e 74 6f 5f 73 74 72 69 lone().into_stri
0670: 6e 67 28 29 2e 65 78 70 65 63 74 28 22 73 68 6f ng().expect("sho
0680: 75 6c 64 20 62 65 20 73 74 72 69 6e 67 73 22 29 uld be strings")
0690: 29 29 3b 0a 09 09 6c 65 74 20 6d 75 74 20 64 6f ));...let mut do
06a0: 6d 61 69 6e 73 3a 20 48 61 73 68 53 65 74 3c 53 mains: HashSet<S
06b0: 74 72 69 6e 67 3e 20 3d 20 48 61 73 68 53 65 74 tring> = HashSet
06c0: 3a 3a 6e 65 77 28 29 3b 0a 09 09 6c 65 74 20 65 ::new();...let e
06d0: 78 74 72 61 5f 64 6f 6d 61 69 6e 73 20 3d 20 73 xtra_domains = s
06e0: 65 74 74 69 6e 67 73 2e 67 65 74 5f 61 72 72 61 ettings.get_arra
06f0: 79 28 22 64 6f 6d 61 69 6e 73 22 29 2e 73 74 61 y("domains").sta
0700: 63 6b 28 29 3f 3b 0a 09 09 66 6f 72 20 64 6f 6d ck()?;...for dom
0710: 61 69 6e 20 69 6e 20 65 78 74 72 61 5f 64 6f 6d ain in extra_dom
0720: 61 69 6e 73 20 7b 0a 09 09 09 6c 65 74 20 64 6f ains {....let do
0730: 6d 61 69 6e 20 3d 20 64 6f 6d 61 69 6e 2e 74 6f main = domain.to
0740: 5f 73 74 72 69 6e 67 28 29 2e 74 6f 5f 6c 6f 77 _string().to_low
0750: 65 72 63 61 73 65 28 29 3b 0a 09 09 09 69 66 20 ercase();....if
0760: 52 45 5f 44 4f 4d 41 49 4e 2e 69 73 5f 6d 61 74 RE_DOMAIN.is_mat
0770: 63 68 28 26 64 6f 6d 61 69 6e 29 20 7b 0a 09 09 ch(&domain) {...
0780: 09 09 64 6f 6d 61 69 6e 73 2e 69 6e 73 65 72 74 ..domains.insert
0790: 28 64 6f 6d 61 69 6e 29 3b 0a 09 09 09 7d 20 65 (domain);....} e
07a0: 6c 73 65 20 7b 0a 09 09 09 09 70 61 6e 69 63 21 lse {.....panic!
07b0: 28 22 5b 73 6d 74 70 32 74 67 2e 74 6f 6d 6c 5d ("[smtp2tg.toml]
07c0: 20 63 61 6e 27 74 20 63 68 65 63 6b 20 6f 66 20 can't check of
07d0: 64 6f 6d 61 69 6e 73 20 69 6e 20 5c 22 64 6f 6d domains in \"dom
07e0: 61 69 6e 73 5c 22 3a 20 7b 64 6f 6d 61 69 6e 7d ains\": {domain}
07f0: 22 29 3b 0a 09 09 09 7d 0a 09 09 7d 0a 09 09 6c ");....}...}...l
0800: 65 74 20 64 6f 6d 61 69 6e 73 20 3d 20 64 6f 6d et domains = dom
0810: 61 69 6e 73 2e 69 6e 74 6f 5f 69 74 65 72 28 29 ains.into_iter()
0820: 2e 6d 61 70 28 7c 73 7c 20 65 73 63 61 70 65 28 .map(|s| escape(
0830: 26 73 29 29 0a 09 09 09 2e 63 6f 6c 6c 65 63 74 &s)).....collect
0840: 3a 3a 3c 56 65 63 3c 53 74 72 69 6e 67 3e 3e 28 ::<Vec<String>>(
0850: 29 2e 6a 6f 69 6e 28 22 7c 22 29 3b 0a 09 09 6c ).join("|");...l
0860: 65 74 20 61 64 64 72 65 73 73 20 3d 20 52 65 67 et address = Reg
0870: 65 78 3a 3a 6e 65 77 28 26 66 6f 72 6d 61 74 21 ex::new(&format!
0880: 28 22 5e 28 3f 50 3c 75 73 65 72 3e 5b 61 2d 7a ("^(?P<user>[a-z
0890: 30 2d 39 5d 5b 2d 61 2d 7a 30 2d 39 5d 29 28 40 0-9][-a-z0-9])(@
08a0: 28 7b 64 6f 6d 61 69 6e 73 7d 29 29 24 22 29 29 ({domains}))$"))
08b0: 2e 73 74 61 63 6b 28 29 3f 3b 0a 09 09 6c 65 74 .stack()?;...let
08c0: 20 72 65 6c 61 79 20 3d 20 6d 61 74 63 68 20 73 relay = match s
08d0: 65 74 74 69 6e 67 73 2e 67 65 74 5f 73 74 72 69 ettings.get_stri
08e0: 6e 67 28 22 75 6e 6b 6e 6f 77 6e 22 29 0a 09 09 ng("unknown")...
08f0: 09 2e 63 6f 6e 74 65 78 74 28 22 5b 73 6d 74 70 ..context("[smtp
0900: 32 74 67 2e 74 6f 6d 6c 5d 20 63 61 6e 27 74 20 2tg.toml] can't
0910: 67 65 74 20 5c 22 75 6e 6b 6e 6f 77 6e 5c 22 20 get \"unknown\"
0920: 70 6f 6c 69 63 79 2e 5c 6e 22 29 3f 2e 61 73 5f policy.\n")?.as_
0930: 73 74 72 28 29 0a 09 09 7b 0a 09 09 09 22 72 65 str()...{...."re
0940: 6c 61 79 22 20 3d 3e 20 74 72 75 65 2c 0a 09 09 lay" => true,...
0950: 09 22 64 65 6e 79 22 20 3d 3e 20 66 61 6c 73 65 ."deny" => false
0960: 2c 0a 09 09 09 5f 20 3d 3e 20 7b 0a 09 09 09 09 ,...._ => {.....
0970: 62 61 69 6c 21 28 22 5b 73 6d 74 70 32 74 67 2e bail!("[smtp2tg.
0980: 74 6f 6d 6c 5d 20 5c 22 75 6e 6b 6e 6f 77 6e 5c toml] \"unknown\
0990: 22 20 73 68 6f 75 6c 64 20 62 65 20 65 69 74 68 " should be eith
09a0: 65 72 20 5c 22 72 65 6c 61 79 5c 22 20 6f 72 20 er \"relay\" or
09b0: 5c 22 64 65 6e 79 5c 22 2e 5c 6e 22 29 3b 0a 09 \"deny\".\n");..
09c0: 09 09 7d 2c 0a 09 09 7d 3b 0a 0a 09 09 4f 6b 28 ..},...};....Ok(
09d0: 4d 61 69 6c 53 65 72 76 65 72 20 7b 0a 09 09 09 MailServer {....
09e0: 64 61 74 61 3a 20 76 65 63 21 28 29 2c 0a 09 09 data: vec!(),...
09f0: 09 68 65 61 64 65 72 73 3a 20 4e 6f 6e 65 2c 0a .headers: None,.
0a00: 09 09 09 72 65 6c 61 79 2c 0a 09 09 09 74 67 2c ...relay,....tg,
0a10: 0a 09 09 09 66 69 65 6c 64 73 2c 0a 09 09 09 61 ....fields,....a
0a20: 64 64 72 65 73 73 2c 0a 09 09 7d 29 0a 09 7d 0a ddress,...})..}.
0a30: 0a 09 2f 2f 2f 20 52 65 74 75 72 6e 73 20 69 64 ../// Returns id
0a40: 20 66 6f 72 20 70 72 6f 76 69 64 65 64 20 65 6d for provided em
0a50: 61 69 6c 20 61 64 64 72 65 73 73 0a 09 66 6e 20 ail address..fn
0a60: 67 65 74 5f 69 64 20 28 26 73 65 6c 66 2c 20 6e get_id (&self, n
0a70: 61 6d 65 3a 20 26 73 74 72 29 20 2d 3e 20 52 65 ame: &str) -> Re
0a80: 73 75 6c 74 3c 26 43 68 61 74 50 65 65 72 49 64 sult<&ChatPeerId
0a90: 3e 20 7b 0a 09 09 2f 2f 20 68 65 72 65 20 77 65 > {...// here we
0aa0: 20 6e 65 65 64 20 74 6f 20 73 74 6f 72 65 20 53 need to store S
0ab0: 74 72 69 6e 67 20 6c 6f 63 61 6c 6c 79 20 74 6f tring locally to
0ac0: 20 62 6f 72 72 6f 77 20 69 74 20 61 66 74 65 72 borrow it after
0ad0: 0a 09 09 6c 65 74 20 6d 75 74 20 6c 69 6e 6b 20 ...let mut link
0ae0: 3d 20 6e 61 6d 65 3b 0a 09 09 6c 65 74 20 6e 61 = name;...let na
0af0: 6d 65 3a 20 53 74 72 69 6e 67 3b 0a 09 09 69 66 me: String;...if
0b00: 20 6c 65 74 20 53 6f 6d 65 28 63 61 70 73 29 20 let Some(caps)
0b10: 3d 20 73 65 6c 66 2e 61 64 64 72 65 73 73 2e 63 = self.address.c
0b20: 61 70 74 75 72 65 73 28 6c 69 6e 6b 29 20 7b 0a aptures(link) {.
0b30: 09 09 09 6e 61 6d 65 20 3d 20 63 61 70 73 5b 22 ...name = caps["
0b40: 6e 61 6d 65 22 5d 2e 74 6f 5f 73 74 72 69 6e 67 name"].to_string
0b50: 28 29 3b 0a 09 09 09 6c 69 6e 6b 20 3d 20 26 6e ();....link = &n
0b60: 61 6d 65 3b 0a 09 09 7d 0a 09 09 6d 61 74 63 68 ame;...}...match
0b70: 20 73 65 6c 66 2e 74 67 2e 67 65 74 28 6c 69 6e self.tg.get(lin
0b80: 6b 29 20 7b 0a 09 09 09 4f 6b 28 61 64 64 72 29 k) {....Ok(addr)
0b90: 20 3d 3e 20 4f 6b 28 61 64 64 72 29 2c 0a 09 09 => Ok(addr),...
0ba0: 09 45 72 72 28 5f 29 20 3d 3e 20 4f 6b 28 26 73 .Err(_) => Ok(&s
0bb0: 65 6c 66 2e 74 67 2e 64 65 66 61 75 6c 74 29 2c elf.tg.default),
0bc0: 0a 09 09 7d 0a 09 7d 0a 0a 09 2f 2f 2f 20 41 74 ...}..}.../// At
0bd0: 74 65 6d 70 74 20 74 6f 20 64 65 6c 69 76 65 72 tempt to deliver
0be0: 20 6f 6e 65 20 6d 65 73 73 61 67 65 0a 09 61 73 one message..as
0bf0: 79 6e 63 20 66 6e 20 72 65 6c 61 79 5f 6d 61 69 ync fn relay_mai
0c00: 6c 20 28 26 73 65 6c 66 29 20 2d 3e 20 52 65 73 l (&self) -> Res
0c10: 75 6c 74 3c 28 29 3e 20 7b 0a 09 09 69 66 20 6c ult<()> {...if l
0c20: 65 74 20 53 6f 6d 65 28 68 65 61 64 65 72 73 29 et Some(headers)
0c30: 20 3d 20 26 73 65 6c 66 2e 68 65 61 64 65 72 73 = &self.headers
0c40: 20 7b 0a 09 09 09 6c 65 74 20 6d 61 69 6c 20 3d {....let mail =
0c50: 20 6d 61 69 6c 5f 70 61 72 73 65 72 3a 3a 4d 65 mail_parser::Me
0c60: 73 73 61 67 65 50 61 72 73 65 72 3a 3a 6e 65 77 ssageParser::new
0c70: 28 29 2e 70 61 72 73 65 28 26 73 65 6c 66 2e 64 ().parse(&self.d
0c80: 61 74 61 29 0a 09 09 09 09 2e 63 6f 6e 74 65 78 ata)......contex
0c90: 74 28 22 46 61 69 6c 65 64 20 74 6f 20 70 61 72 t("Failed to par
0ca0: 73 65 20 6d 61 69 6c 2e 22 29 3f 3b 0a 0a 09 09 se mail.")?;....
0cb0: 09 2f 2f 20 41 64 64 69 6e 67 20 61 6c 6c 20 6b .// Adding all k
0cc0: 6e 6f 77 6e 20 61 64 64 72 65 73 73 65 73 20 74 nown addresses t
0cd0: 6f 20 72 65 63 69 70 69 65 6e 74 20 6c 69 73 74 o recipient list
0ce0: 2c 20 66 6f 72 20 61 6e 79 6f 6e 65 20 65 6c 73 , for anyone els
0cf0: 65 20 61 64 64 69 6e 67 20 64 65 66 61 75 6c 74 e adding default
0d00: 0a 09 09 09 2f 2f 20 41 6c 73 6f 20 69 66 20 6c ....// Also if l
0d10: 69 73 74 20 69 73 20 65 6d 70 74 79 20 61 6c 73 ist is empty als
0d20: 6f 20 61 64 64 69 6e 67 20 64 65 66 61 75 6c 74 o adding default
0d30: 0a 09 09 09 6c 65 74 20 6d 75 74 20 72 63 70 74 ....let mut rcpt
0d40: 3a 20 48 61 73 68 53 65 74 3c 26 43 68 61 74 50 : HashSet<&ChatP
0d50: 65 65 72 49 64 3e 20 3d 20 48 61 73 68 53 65 74 eerId> = HashSet
0d60: 3a 3a 6e 65 77 28 29 3b 0a 09 09 09 69 66 20 68 ::new();....if h
0d70: 65 61 64 65 72 73 2e 74 6f 2e 69 73 5f 65 6d 70 eaders.to.is_emp
0d80: 74 79 28 29 20 26 26 20 21 73 65 6c 66 2e 72 65 ty() && !self.re
0d90: 6c 61 79 20 7b 0a 09 09 09 09 62 61 69 6c 21 28 lay {.....bail!(
0da0: 22 52 65 6c 61 79 69 6e 67 20 69 73 20 64 69 73 "Relaying is dis
0db0: 61 62 6c 65 64 2c 20 61 6e 64 20 74 68 65 72 65 abled, and there
0dc0: 27 73 20 6e 6f 20 64 65 73 74 69 6e 61 74 69 6f 's no destinatio
0dd0: 6e 20 61 64 64 72 65 73 73 22 29 3b 0a 09 09 09 n address");....
0de0: 7d 0a 09 09 09 66 6f 72 20 69 74 65 6d 20 69 6e }....for item in
0df0: 20 26 68 65 61 64 65 72 73 2e 74 6f 20 7b 0a 09 &headers.to {..
0e00: 09 09 09 72 63 70 74 2e 69 6e 73 65 72 74 28 73 ...rcpt.insert(s
0e10: 65 6c 66 2e 67 65 74 5f 69 64 28 69 74 65 6d 29 elf.get_id(item)
0e20: 3f 29 3b 0a 09 09 09 7d 3b 0a 09 09 09 69 66 20 ?);....};....if
0e30: 72 63 70 74 2e 69 73 5f 65 6d 70 74 79 28 29 20 rcpt.is_empty()
0e40: 7b 0a 09 09 09 09 73 65 6c 66 2e 74 67 2e 64 65 {.....self.tg.de
0e50: 62 75 67 28 22 4e 6f 20 72 65 63 69 70 69 65 6e bug("No recipien
0e60: 74 20 6f 72 20 65 6e 76 65 6c 6f 70 65 20 61 64 t or envelope ad
0e70: 64 72 65 73 73 2e 22 29 2e 61 77 61 69 74 3f 3b dress.").await?;
0e80: 0a 09 09 09 09 72 63 70 74 2e 69 6e 73 65 72 74 .....rcpt.insert
0e90: 28 26 73 65 6c 66 2e 74 67 2e 64 65 66 61 75 6c (&self.tg.defaul
0ea0: 74 29 3b 0a 09 09 09 7d 3b 0a 0a 09 09 09 2f 2f t);....};.....//
0eb0: 20 70 72 65 70 61 72 69 6e 67 20 6d 65 73 73 61 preparing messa
0ec0: 67 65 20 68 65 61 64 65 72 0a 09 09 09 6c 65 74 ge header....let
0ed0: 20 6d 75 74 20 72 65 70 6c 79 3a 20 56 65 63 3c mut reply: Vec<
0ee0: 53 74 72 69 6e 67 3e 20 3d 20 76 65 63 21 5b 22 String> = vec!["
0ef0: 3c 62 6c 6f 63 6b 71 75 6f 74 65 20 65 78 70 61 <blockquote expa
0f00: 6e 64 61 62 6c 65 3e 22 2e 69 6e 74 6f 28 29 5d ndable>".into()]
0f10: 3b 0a 09 09 09 69 66 20 73 65 6c 66 2e 66 69 65 ;....if self.fie
0f20: 6c 64 73 2e 63 6f 6e 74 61 69 6e 73 28 22 73 75 lds.contains("su
0f30: 62 6a 65 63 74 22 29 20 7b 0a 09 09 09 09 69 66 bject") {.....if
0f40: 20 6c 65 74 20 53 6f 6d 65 28 73 75 62 6a 65 63 let Some(subjec
0f50: 74 29 20 3d 20 6d 61 69 6c 2e 73 75 62 6a 65 63 t) = mail.subjec
0f60: 74 28 29 20 7b 0a 09 09 09 09 09 72 65 70 6c 79 t() {......reply
0f70: 2e 70 75 73 68 28 66 6f 72 6d 61 74 21 28 22 3c .push(format!("<
0f80: 75 3e 3c 69 3e 53 75 62 6a 65 63 74 3a 3c 2f 69 u><i>Subject:</i
0f90: 3e 3c 2f 75 3e e2 80 87 3c 63 6f 64 65 3e 7b 7d ></u> <code>{}
0fa0: 3c 2f 63 6f 64 65 3e 22 2c 20 76 61 6c 69 64 61 </code>", valida
0fb0: 74 65 28 73 75 62 6a 65 63 74 29 2e 73 74 61 63 te(subject).stac
0fc0: 6b 28 29 3f 29 29 3b 0a 09 09 09 09 7d 20 65 6c k()?));.....} el
0fd0: 73 65 20 69 66 20 6c 65 74 20 53 6f 6d 65 28 74 se if let Some(t
0fe0: 68 72 65 61 64 29 20 3d 20 6d 61 69 6c 2e 74 68 hread) = mail.th
0ff0: 72 65 61 64 5f 6e 61 6d 65 28 29 20 7b 0a 09 09 read_name() {...
1000: 09 09 09 72 65 70 6c 79 2e 70 75 73 68 28 66 6f ...reply.push(fo
1010: 72 6d 61 74 21 28 22 3c 75 3e 3c 69 3e 54 68 72 rmat!("<u><i>Thr
1020: 65 61 64 3a 3c 2f 69 3e 3c 2f 75 3e e2 80 87 3c ead:</i></u> <
1030: 63 6f 64 65 3e 7b 7d 3c 2f 63 6f 64 65 3e 22 2c code>{}</code>",
1040: 20 76 61 6c 69 64 61 74 65 28 74 68 72 65 61 64 validate(thread
1050: 29 2e 73 74 61 63 6b 28 29 3f 29 29 3b 0a 09 09 ).stack()?));...
1060: 09 09 7d 0a 09 09 09 7d 0a 09 09 09 2f 2f 20 64 ..}....}....// d
1070: 6f 20 77 65 20 6e 65 65 64 20 74 6f 20 72 65 70 o we need to rep
1080: 6c 61 63 65 20 73 70 61 63 65 73 20 68 65 72 65 lace spaces here
1090: 3f 0a 09 09 09 69 66 20 73 65 6c 66 2e 66 69 65 ?....if self.fie
10a0: 6c 64 73 2e 63 6f 6e 74 61 69 6e 73 28 22 66 72 lds.contains("fr
10b0: 6f 6d 22 29 20 7b 0a 09 09 09 09 72 65 70 6c 79 om") {.....reply
10c0: 2e 70 75 73 68 28 66 6f 72 6d 61 74 21 28 22 3c .push(format!("<
10d0: 75 3e 3c 69 3e 46 72 6f 6d 3a 3c 2f 69 3e 3c 2f u><i>From:</i></
10e0: 75 3e e2 80 87 3c 63 6f 64 65 3e 7b 7d 3c 2f 63 u> <code>{}</c
10f0: 6f 64 65 3e 22 2c 20 76 61 6c 69 64 61 74 65 28 ode>", validate(
1100: 26 68 65 61 64 65 72 73 2e 66 72 6f 6d 29 2e 73 &headers.from).s
1110: 74 61 63 6b 28 29 3f 29 29 3b 0a 09 09 09 7d 0a tack()?));....}.
1120: 09 09 09 69 66 20 73 65 6c 66 2e 66 69 65 6c 64 ...if self.field
1130: 73 2e 63 6f 6e 74 61 69 6e 73 28 22 64 61 74 65 s.contains("date
1140: 22 29 0a 09 09 09 09 26 26 20 6c 65 74 20 53 6f ").....&& let So
1150: 6d 65 28 64 61 74 65 29 20 3d 20 6d 61 69 6c 2e me(date) = mail.
1160: 64 61 74 65 28 29 0a 09 09 09 7b 0a 09 09 09 09 date()....{.....
1170: 72 65 70 6c 79 2e 70 75 73 68 28 66 6f 72 6d 61 reply.push(forma
1180: 74 21 28 22 3c 75 3e 3c 69 3e 44 61 74 65 3a 3c t!("<u><i>Date:<
1190: 2f 69 3e 3c 2f 75 3e e2 80 87 3c 63 6f 64 65 3e /i></u> <code>
11a0: 7b 64 61 74 65 7d 3c 2f 63 6f 64 65 3e 22 29 29 {date}</code>"))
11b0: 3b 0a 09 09 09 7d 0a 09 09 09 72 65 70 6c 79 2e ;....}....reply.
11c0: 70 75 73 68 28 22 3c 2f 62 6c 6f 63 6b 71 75 6f push("</blockquo
11d0: 74 65 3e 3c 70 72 65 3e 22 2e 69 6e 74 6f 28 29 te><pre>".into()
11e0: 29 3b 0a 09 09 09 2f 2f 6c 65 74 20 68 65 61 64 );....//let head
11f0: 65 72 5f 73 69 7a 65 20 3d 20 72 65 70 6c 79 2e er_size = reply.
1200: 6a 6f 69 6e 28 22 20 22 29 2e 6c 65 6e 28 29 3b join(" ").len();
1210: 0a 09 09 09 6c 65 74 20 6d 75 74 20 68 65 61 64 ....let mut head
1220: 65 72 5f 73 69 7a 65 20 3d 20 30 3b 0a 09 09 09 er_size = 0;....
1230: 66 6f 72 20 69 20 69 6e 20 72 65 70 6c 79 2e 69 for i in reply.i
1240: 74 65 72 28 29 20 7b 0a 09 09 09 09 68 65 61 64 ter() {.....head
1250: 65 72 5f 73 69 7a 65 20 2b 3d 20 69 2e 6c 65 6e er_size += i.len
1260: 28 29 20 2b 20 31 3b 0a 09 09 09 7d 0a 0a 09 09 () + 1;....}....
1270: 09 6c 65 74 20 68 74 6d 6c 5f 70 61 72 74 73 20 .let html_parts
1280: 3d 20 6d 61 69 6c 2e 68 74 6d 6c 5f 62 6f 64 79 = mail.html_body
1290: 5f 63 6f 75 6e 74 28 29 3b 0a 09 09 09 6c 65 74 _count();....let
12a0: 20 74 65 78 74 5f 70 61 72 74 73 20 3d 20 6d 61 text_parts = ma
12b0: 69 6c 2e 74 65 78 74 5f 62 6f 64 79 5f 63 6f 75 il.text_body_cou
12c0: 6e 74 28 29 3b 0a 09 09 09 6c 65 74 20 61 74 74 nt();....let att
12d0: 61 63 68 6d 65 6e 74 73 20 3d 20 6d 61 69 6c 2e achments = mail.
12e0: 61 74 74 61 63 68 6d 65 6e 74 5f 63 6f 75 6e 74 attachment_count
12f0: 28 29 3b 0a 09 09 09 69 66 20 68 74 6d 6c 5f 70 ();....if html_p
1300: 61 72 74 73 20 21 3d 20 74 65 78 74 5f 70 61 72 arts != text_par
1310: 74 73 20 7b 0a 09 09 09 09 73 65 6c 66 2e 74 67 ts {.....self.tg
1320: 2e 64 65 62 75 67 28 26 66 6f 72 6d 61 74 21 28 .debug(&format!(
1330: 22 48 6d 2c 20 77 65 20 68 61 76 65 20 7b 68 74 "Hm, we have {ht
1340: 6d 6c 5f 70 61 72 74 73 7d 20 48 54 4d 4c 20 70 ml_parts} HTML p
1350: 61 72 74 73 20 61 6e 64 20 7b 74 65 78 74 5f 70 arts and {text_p
1360: 61 72 74 73 7d 20 74 65 78 74 20 70 61 72 74 73 arts} text parts
1370: 2e 22 29 29 2e 61 77 61 69 74 3f 3b 0a 09 09 09 .")).await?;....
1380: 7d 0a 09 09 09 2f 2f 6c 65 74 20 6d 75 74 20 68 }....//let mut h
1390: 74 6d 6c 5f 6e 75 6d 20 3d 20 30 3b 0a 09 09 09 tml_num = 0;....
13a0: 6c 65 74 20 6d 75 74 20 74 65 78 74 5f 6e 75 6d let mut text_num
13b0: 20 3d 20 30 3b 0a 09 09 09 6c 65 74 20 6d 75 74 = 0;....let mut
13c0: 20 66 69 6c 65 5f 6e 75 6d 20 3d 20 30 3b 0a 09 file_num = 0;..
13d0: 09 09 2f 2f 20 6c 65 74 27 73 20 64 69 73 70 6c ..// let's displ
13e0: 61 79 20 66 69 72 73 74 20 68 74 6d 6c 20 6f 72 ay first html or
13f0: 20 74 65 78 74 20 70 61 72 74 20 61 73 20 62 6f text part as bo
1400: 64 79 0a 09 09 09 6c 65 74 20 6d 75 74 20 62 6f dy....let mut bo
1410: 64 79 3a 20 43 6f 77 3c 27 5f 2c 20 73 74 72 3e dy: Cow<'_, str>
1420: 20 3d 20 22 22 2e 69 6e 74 6f 28 29 3b 0a 09 09 = "".into();...
1430: 09 2f 2a 0a 09 09 09 20 2a 20 61 63 74 75 61 6c ./*.... * actual
1440: 6c 79 20 49 20 64 6f 6e 27 74 20 77 61 6e 6e 61 ly I don't wanna
1450: 20 70 61 72 73 65 20 74 68 61 74 20 68 74 6d 6c parse that html
1460: 20 73 74 75 66 66 0a 09 09 09 69 66 20 68 74 6d stuff....if htm
1470: 6c 5f 70 61 72 74 73 20 3e 20 30 20 7b 0a 09 09 l_parts > 0 {...
1480: 09 09 6c 65 74 20 74 65 78 74 20 3d 20 6d 61 69 ..let text = mai
1490: 6c 2e 62 6f 64 79 5f 68 74 6d 6c 28 30 29 2e 73 l.body_html(0).s
14a0: 74 61 63 6b 28 29 3f 3b 0a 09 09 09 09 69 66 20 tack()?;.....if
14b0: 74 65 78 74 2e 6c 65 6e 28 29 20 3c 20 34 30 39 text.len() < 409
14c0: 36 20 2d 20 68 65 61 64 65 72 5f 73 69 7a 65 20 6 - header_size
14d0: 7b 0a 09 09 09 09 09 62 6f 64 79 20 3d 20 74 65 {......body = te
14e0: 78 74 3b 0a 09 09 09 09 09 68 74 6d 6c 5f 6e 75 xt;......html_nu
14f0: 6d 20 3d 20 31 3b 0a 09 09 09 09 7d 0a 09 09 09 m = 1;.....}....
1500: 7d 3b 0a 09 09 09 2a 2f 0a 09 09 09 69 66 20 62 };....*/....if b
1510: 6f 64 79 2e 69 73 5f 65 6d 70 74 79 28 29 20 26 ody.is_empty() &
1520: 26 20 74 65 78 74 5f 70 61 72 74 73 20 3e 20 30 & text_parts > 0
1530: 20 7b 0a 09 09 09 09 6c 65 74 20 74 65 78 74 20 {.....let text
1540: 3d 20 6d 61 69 6c 2e 62 6f 64 79 5f 74 65 78 74 = mail.body_text
1550: 28 30 29 0a 09 09 09 09 09 2e 63 6f 6e 74 65 78 (0).......contex
1560: 74 28 22 46 61 69 6c 65 64 20 74 6f 20 65 78 74 t("Failed to ext
1570: 72 61 63 74 20 74 65 78 74 20 66 72 6f 6d 20 6d ract text from m
1580: 65 73 73 61 67 65 22 29 3f 3b 0a 09 09 09 09 2f essage")?;...../
1590: 2f 20 37 3a 0a 09 09 09 09 2f 2f 20 2d 20 28 6d / 7:.....// - (m
15a0: 61 69 6c 20 74 65 78 74 29 0a 09 09 09 09 2f 2f ail text).....//
15b0: 20 2d 20 31 20 74 72 61 69 6c 69 6e 67 20 6e 65 - 1 trailing ne
15c0: 77 6c 69 6e 65 0a 09 09 09 09 2f 2f 20 2d 20 36 wline.....// - 6
15d0: 3a 20 3c 2f 70 72 65 3e 0a 09 09 09 09 69 66 20 : </pre>.....if
15e0: 74 65 78 74 2e 6c 65 6e 28 29 20 3c 20 34 30 39 text.len() < 409
15f0: 36 20 2d 20 28 20 68 65 61 64 65 72 5f 73 69 7a 6 - ( header_siz
1600: 65 20 2b 20 37 20 29 20 7b 0a 09 09 09 09 09 62 e + 7 ) {......b
1610: 6f 64 79 20 3d 20 74 65 78 74 3b 0a 09 09 09 09 ody = text;.....
1620: 09 74 65 78 74 5f 6e 75 6d 20 3d 20 31 3b 0a 09 .text_num = 1;..
1630: 09 09 09 7d 0a 09 09 09 7d 3b 0a 09 09 09 72 65 ...}....};....re
1640: 70 6c 79 2e 65 78 74 65 6e 64 28 62 6f 64 79 2e ply.extend(body.
1650: 6c 69 6e 65 73 28 29 2e 6d 61 70 28 7c 78 7c 20 lines().map(|x|
1660: 78 2e 69 6e 74 6f 28 29 29 29 3b 0a 09 09 09 72 x.into()));....r
1670: 65 70 6c 79 2e 70 75 73 68 28 22 3c 2f 70 72 65 eply.push("</pre
1680: 3e 22 2e 69 6e 74 6f 28 29 29 3b 0a 0a 09 09 09 >".into());.....
1690: 2f 2f 20 61 6e 64 20 6c 65 74 27 73 20 63 6f 6c // and let's col
16a0: 6c 65 63 74 20 61 6c 6c 20 6f 74 68 65 72 20 61 lect all other a
16b0: 74 74 61 63 68 6d 65 6e 74 20 70 61 72 74 73 0a ttachment parts.
16c0: 09 09 09 6c 65 74 20 6d 75 74 20 66 69 6c 65 73 ...let mut files
16d0: 5f 74 6f 5f 73 65 6e 64 20 3d 20 76 65 63 21 5b _to_send = vec![
16e0: 5d 3b 0a 09 09 09 2f 2a 0a 09 09 09 20 2a 20 6c ];..../*.... * l
16f0: 65 74 27 73 20 6a 75 73 74 20 73 6b 69 70 20 68 et's just skip h
1700: 74 6d 6c 20 70 61 72 74 73 20 66 6f 72 20 6e 6f tml parts for no
1710: 77 2c 20 74 68 65 79 20 6a 75 73 74 20 64 75 70 w, they just dup
1720: 6c 69 63 61 74 65 20 74 65 78 74 3f 0a 09 09 09 licate text?....
1730: 77 68 69 6c 65 20 68 74 6d 6c 5f 6e 75 6d 20 3c while html_num <
1740: 20 68 74 6d 6c 5f 70 61 72 74 73 20 7b 0a 09 09 html_parts {...
1750: 09 09 66 69 6c 65 73 5f 74 6f 5f 73 65 6e 64 2e ..files_to_send.
1760: 70 75 73 68 28 6d 61 69 6c 2e 68 74 6d 6c 5f 70 push(mail.html_p
1770: 61 72 74 28 68 74 6d 6c 5f 6e 75 6d 29 2e 73 74 art(html_num).st
1780: 61 63 6b 28 29 3f 29 3b 0a 09 09 09 09 68 74 6d ack()?);.....htm
1790: 6c 5f 6e 75 6d 20 2b 3d 20 31 3b 0a 09 09 09 7d l_num += 1;....}
17a0: 0a 09 09 09 2a 2f 0a 09 09 09 77 68 69 6c 65 20 ....*/....while
17b0: 74 65 78 74 5f 6e 75 6d 20 3c 20 74 65 78 74 5f text_num < text_
17c0: 70 61 72 74 73 20 7b 0a 09 09 09 09 66 69 6c 65 parts {.....file
17d0: 73 5f 74 6f 5f 73 65 6e 64 2e 70 75 73 68 28 6d s_to_send.push(m
17e0: 61 69 6c 2e 74 65 78 74 5f 70 61 72 74 28 74 65 ail.text_part(te
17f0: 78 74 5f 6e 75 6d 2e 74 72 79 5f 69 6e 74 6f 28 xt_num.try_into(
1800: 29 2e 73 74 61 63 6b 28 29 3f 29 0a 09 09 09 09 ).stack()?).....
1810: 09 2e 63 6f 6e 74 65 78 74 28 22 46 61 69 6c 65 ..context("Faile
1820: 64 20 74 6f 20 67 65 74 20 74 65 78 74 20 70 61 d to get text pa
1830: 72 74 20 66 72 6f 6d 20 6d 65 73 73 61 67 65 2e rt from message.
1840: 22 29 3f 29 3b 0a 09 09 09 09 74 65 78 74 5f 6e ")?);.....text_n
1850: 75 6d 20 2b 3d 20 31 3b 0a 09 09 09 7d 0a 09 09 um += 1;....}...
1860: 09 77 68 69 6c 65 20 66 69 6c 65 5f 6e 75 6d 20 .while file_num
1870: 3c 20 61 74 74 61 63 68 6d 65 6e 74 73 20 7b 0a < attachments {.
1880: 09 09 09 09 66 69 6c 65 73 5f 74 6f 5f 73 65 6e ....files_to_sen
1890: 64 2e 70 75 73 68 28 6d 61 69 6c 2e 61 74 74 61 d.push(mail.atta
18a0: 63 68 6d 65 6e 74 28 66 69 6c 65 5f 6e 75 6d 2e chment(file_num.
18b0: 74 72 79 5f 69 6e 74 6f 28 29 2e 73 74 61 63 6b try_into().stack
18c0: 28 29 3f 29 0a 09 09 09 09 09 2e 63 6f 6e 74 65 ()?).......conte
18d0: 78 74 28 22 46 61 69 6c 65 64 20 74 6f 20 67 65 xt("Failed to ge
18e0: 74 20 66 69 6c 65 20 70 61 72 74 20 66 72 6f 6d t file part from
18f0: 20 6d 65 73 73 61 67 65 2e 22 29 3f 29 3b 0a 09 message.")?);..
1900: 09 09 09 66 69 6c 65 5f 6e 75 6d 20 2b 3d 20 31 ...file_num += 1
1910: 3b 0a 09 09 09 7d 0a 0a 09 09 09 6c 65 74 20 6d ;....}.....let m
1920: 73 67 20 3d 20 72 65 70 6c 79 2e 6a 6f 69 6e 28 sg = reply.join(
1930: 22 5c 6e 22 29 3b 0a 09 09 09 66 6f 72 20 63 68 "\n");....for ch
1940: 61 74 20 69 6e 20 72 63 70 74 20 7b 0a 09 09 09 at in rcpt {....
1950: 09 69 66 20 21 66 69 6c 65 73 5f 74 6f 5f 73 65 .if !files_to_se
1960: 6e 64 2e 69 73 5f 65 6d 70 74 79 28 29 20 7b 0a nd.is_empty() {.
1970: 09 09 09 09 09 6c 65 74 20 6d 75 74 20 66 69 6c .....let mut fil
1980: 65 73 20 3d 20 76 65 63 21 5b 5d 3b 0a 09 09 09 es = vec![];....
1990: 09 09 2f 2f 20 6c 65 74 20 6d 75 74 20 66 69 72 ..// let mut fir
19a0: 73 74 5f 6f 6e 65 20 3d 20 74 72 75 65 3b 0a 09 st_one = true;..
19b0: 09 09 09 09 66 6f 72 20 63 68 75 6e 6b 20 69 6e ....for chunk in
19c0: 20 26 66 69 6c 65 73 5f 74 6f 5f 73 65 6e 64 20 &files_to_send
19d0: 7b 0a 09 09 09 09 09 09 6c 65 74 20 64 61 74 61 {.......let data
19e0: 3a 20 56 65 63 3c 75 38 3e 20 3d 20 63 68 75 6e : Vec<u8> = chun
19f0: 6b 2e 63 6f 6e 74 65 6e 74 73 28 29 2e 74 6f 5f k.contents().to_
1a00: 76 65 63 28 29 3b 0a 09 09 09 09 09 09 6c 65 74 vec();.......let
1a10: 20 6d 75 74 20 66 69 6c 65 6e 61 6d 65 3a 20 4f mut filename: O
1a20: 70 74 69 6f 6e 3c 53 74 72 69 6e 67 3e 20 3d 20 ption<String> =
1a30: 4e 6f 6e 65 3b 0a 09 09 09 09 09 09 66 6f 72 20 None;.......for
1a40: 68 65 61 64 65 72 20 69 6e 20 63 68 75 6e 6b 2e header in chunk.
1a50: 68 65 61 64 65 72 73 28 29 20 7b 0a 09 09 09 09 headers() {.....
1a60: 09 09 09 69 66 20 68 65 61 64 65 72 2e 6e 61 6d ...if header.nam
1a70: 65 28 29 20 3d 3d 20 22 43 6f 6e 74 65 6e 74 2d e() == "Content-
1a80: 54 79 70 65 22 20 7b 0a 09 09 09 09 09 09 09 09 Type" {.........
1a90: 6d 61 74 63 68 20 68 65 61 64 65 72 2e 76 61 6c match header.val
1aa0: 75 65 28 29 20 7b 0a 09 09 09 09 09 09 09 09 09 ue() {..........
1ab0: 6d 61 69 6c 5f 70 61 72 73 65 72 3a 3a 48 65 61 mail_parser::Hea
1ac0: 64 65 72 56 61 6c 75 65 3a 3a 43 6f 6e 74 65 6e derValue::Conten
1ad0: 74 54 79 70 65 28 63 6f 6e 74 65 6e 74 74 79 70 tType(contenttyp
1ae0: 65 29 20 3d 3e 20 7b 0a 09 09 09 09 09 09 09 09 e) => {.........
1af0: 09 09 69 66 20 6c 65 74 20 53 6f 6d 65 28 66 6e ..if let Some(fn
1b00: 61 6d 65 29 20 3d 20 63 6f 6e 74 65 6e 74 74 79 ame) = contentty
1b10: 70 65 2e 61 74 74 72 69 62 75 74 65 28 22 6e 61 pe.attribute("na
1b20: 6d 65 22 29 20 7b 0a 09 09 09 09 09 09 09 09 09 me") {..........
1b30: 09 09 66 69 6c 65 6e 61 6d 65 20 3d 20 53 6f 6d ..filename = Som
1b40: 65 28 66 6e 61 6d 65 2e 74 6f 5f 6f 77 6e 65 64 e(fname.to_owned
1b50: 28 29 29 3b 0a 09 09 09 09 09 09 09 09 09 09 7d ());...........}
1b60: 0a 09 09 09 09 09 09 09 09 09 7d 2c 0a 09 09 09 ..........},....
1b70: 09 09 09 09 09 09 5f 20 3d 3e 20 7b 0a 09 09 09 ......_ => {....
1b80: 09 09 09 09 09 09 09 73 65 6c 66 2e 74 67 2e 64 .......self.tg.d
1b90: 65 62 75 67 28 22 41 74 74 61 63 68 6d 65 6e 74 ebug("Attachment
1ba0: 20 68 61 73 20 62 61 64 20 43 6f 6e 74 65 6e 74 has bad Content
1bb0: 54 79 70 65 20 68 65 61 64 65 72 2e 22 29 2e 61 Type header.").a
1bc0: 77 61 69 74 3f 3b 0a 09 09 09 09 09 09 09 09 09 wait?;..........
1bd0: 7d 2c 0a 09 09 09 09 09 09 09 09 7d 3b 0a 09 09 },.........};...
1be0: 09 09 09 09 09 7d 3b 0a 09 09 09 09 09 09 7d 3b .....};.......};
1bf0: 0a 09 09 09 09 09 09 6c 65 74 20 66 69 6c 65 6e .......let filen
1c00: 61 6d 65 20 3d 20 69 66 20 6c 65 74 20 53 6f 6d ame = if let Som
1c10: 65 28 66 6e 61 6d 65 29 20 3d 20 66 69 6c 65 6e e(fname) = filen
1c20: 61 6d 65 20 7b 0a 09 09 09 09 09 09 09 66 6e 61 ame {........fna
1c30: 6d 65 0a 09 09 09 09 09 09 7d 20 65 6c 73 65 20 me.......} else
1c40: 7b 0a 09 09 09 09 09 09 09 22 41 74 74 61 63 68 {........"Attach
1c50: 6d 65 6e 74 2e 74 78 74 22 2e 69 6e 74 6f 28 29 ment.txt".into()
1c60: 0a 09 09 09 09 09 09 7d 3b 0a 09 09 09 09 09 09 .......};.......
1c70: 66 69 6c 65 73 2e 70 75 73 68 28 41 74 74 61 63 files.push(Attac
1c80: 68 6d 65 6e 74 20 7b 0a 09 09 09 09 09 09 09 64 hment {........d
1c90: 61 74 61 3a 20 43 75 72 73 6f 72 3a 3a 6e 65 77 ata: Cursor::new
1ca0: 28 64 61 74 61 29 2c 0a 09 09 09 09 09 09 09 6e (data),........n
1cb0: 61 6d 65 3a 20 66 69 6c 65 6e 61 6d 65 2c 0a 09 ame: filename,..
1cc0: 09 09 09 09 09 7d 29 3b 0a 09 09 09 09 09 7d 0a .....});......}.
1cd0: 09 09 09 09 09 73 65 6c 66 2e 74 67 2e 73 65 6e .....self.tg.sen
1ce0: 64 67 72 6f 75 70 28 63 68 61 74 2c 20 66 69 6c dgroup(chat, fil
1cf0: 65 73 2c 20 26 6d 73 67 29 2e 61 77 61 69 74 3f es, &msg).await?
1d00: 3b 0a 09 09 09 09 7d 20 65 6c 73 65 20 7b 0a 09 ;.....} else {..
1d10: 09 09 09 09 73 65 6c 66 2e 74 67 2e 73 65 6e 64 ....self.tg.send
1d20: 28 63 68 61 74 2c 20 26 6d 73 67 29 2e 61 77 61 (chat, &msg).awa
1d30: 69 74 3f 3b 0a 09 09 09 09 7d 0a 09 09 09 7d 0a it?;.....}....}.
1d40: 09 09 7d 20 65 6c 73 65 20 7b 0a 09 09 09 62 61 ..} else {....ba
1d50: 69 6c 21 28 22 52 65 71 75 69 72 65 64 20 68 65 il!("Required he
1d60: 61 64 65 72 73 20 77 65 72 65 20 6e 6f 74 20 66 aders were not f
1d70: 6f 75 6e 64 2e 22 29 3b 0a 09 09 7d 0a 09 09 4f ound.");...}...O
1d80: 6b 28 28 29 29 0a 09 7d 0a 7d 0a 0a 69 6d 70 6c k(())..}.}..impl
1d90: 20 6d 61 69 6c 69 6e 5f 65 6d 62 65 64 64 65 64 mailin_embedded
1da0: 3a 3a 48 61 6e 64 6c 65 72 20 66 6f 72 20 4d 61 ::Handler for Ma
1db0: 69 6c 53 65 72 76 65 72 20 7b 0a 09 2f 2f 2f 20 ilServer {..///
1dc0: 4a 75 73 74 20 64 65 6e 79 20 6c 6f 67 69 6e 20 Just deny login
1dd0: 61 75 74 68 0a 09 66 6e 20 61 75 74 68 5f 6c 6f auth..fn auth_lo
1de0: 67 69 6e 20 28 26 6d 75 74 20 73 65 6c 66 2c 20 gin (&mut self,
1df0: 5f 75 73 65 72 6e 61 6d 65 3a 20 26 73 74 72 2c _username: &str,
1e00: 20 5f 70 61 73 73 77 6f 72 64 3a 20 26 73 74 72 _password: &str
1e10: 29 20 2d 3e 20 52 65 73 70 6f 6e 73 65 20 7b 0a ) -> Response {.
1e20: 09 09 49 4e 56 41 4c 49 44 5f 43 52 45 44 45 4e ..INVALID_CREDEN
1e30: 54 49 41 4c 53 0a 09 7d 0a 0a 09 2f 2f 2f 20 4a TIALS..}.../// J
1e40: 75 73 74 20 64 65 6e 79 20 70 6c 61 69 6e 20 61 ust deny plain a
1e50: 75 74 68 0a 09 66 6e 20 61 75 74 68 5f 70 6c 61 uth..fn auth_pla
1e60: 69 6e 20 28 26 6d 75 74 20 73 65 6c 66 2c 20 5f in (&mut self, _
1e70: 61 75 74 68 6f 72 69 7a 61 74 69 6f 6e 5f 69 64 authorization_id
1e80: 3a 20 26 73 74 72 2c 20 5f 61 75 74 68 65 6e 74 : &str, _authent
1e90: 69 63 61 74 69 6f 6e 5f 69 64 3a 20 26 73 74 72 ication_id: &str
1ea0: 2c 20 5f 70 61 73 73 77 6f 72 64 3a 20 26 73 74 , _password: &st
1eb0: 72 29 20 2d 3e 20 52 65 73 70 6f 6e 73 65 20 7b r) -> Response {
1ec0: 0a 09 09 49 4e 56 41 4c 49 44 5f 43 52 45 44 45 ...INVALID_CREDE
1ed0: 4e 54 49 41 4c 53 0a 09 7d 0a 0a 09 2f 2f 2f 20 NTIALS..}...///
1ee0: 56 65 72 69 66 79 20 77 68 65 74 68 65 72 20 61 Verify whether a
1ef0: 64 64 72 65 73 73 20 69 73 20 64 65 6c 69 76 65 ddress is delive
1f00: 72 61 62 6c 65 0a 09 66 6e 20 72 63 70 74 20 28 rable..fn rcpt (
1f10: 26 6d 75 74 20 73 65 6c 66 2c 20 74 6f 3a 20 26 &mut self, to: &
1f20: 73 74 72 29 20 2d 3e 20 52 65 73 70 6f 6e 73 65 str) -> Response
1f30: 20 7b 0a 09 09 69 66 20 73 65 6c 66 2e 72 65 6c {...if self.rel
1f40: 61 79 20 7b 0a 09 09 09 4f 4b 0a 09 09 7d 20 65 ay {....OK...} e
1f50: 6c 73 65 20 7b 0a 09 09 09 6d 61 74 63 68 20 73 lse {....match s
1f60: 65 6c 66 2e 67 65 74 5f 69 64 28 74 6f 29 20 7b elf.get_id(to) {
1f70: 0a 09 09 09 09 4f 6b 28 5f 29 20 3d 3e 20 4f 4b .....Ok(_) => OK
1f80: 2c 0a 09 09 09 09 45 72 72 28 5f 29 20 3d 3e 20 ,.....Err(_) =>
1f90: 7b 0a 09 09 09 09 09 69 66 20 73 65 6c 66 2e 72 {......if self.r
1fa0: 65 6c 61 79 20 7b 0a 09 09 09 09 09 09 4f 4b 0a elay {.......OK.
1fb0: 09 09 09 09 09 7d 20 65 6c 73 65 20 7b 0a 09 09 .....} else {...
1fc0: 09 09 09 09 4e 4f 5f 4d 41 49 4c 42 4f 58 0a 09 ....NO_MAILBOX..
1fd0: 09 09 09 09 7d 0a 09 09 09 09 7d 0a 09 09 09 7d ....}.....}....}
1fe0: 0a 09 09 7d 0a 09 7d 0a 0a 09 2f 2f 2f 20 53 61 ...}..}.../// Sa
1ff0: 76 65 20 68 65 61 64 65 72 73 20 77 65 20 6e 65 ve headers we ne
2000: 65 64 0a 09 66 6e 20 64 61 74 61 5f 73 74 61 72 ed..fn data_star
2010: 74 20 28 26 6d 75 74 20 73 65 6c 66 2c 20 5f 64 t (&mut self, _d
2020: 6f 6d 61 69 6e 3a 20 26 73 74 72 2c 20 66 72 6f omain: &str, fro
2030: 6d 3a 20 26 73 74 72 2c 20 5f 69 73 38 62 69 74 m: &str, _is8bit
2040: 3a 20 62 6f 6f 6c 2c 20 74 6f 3a 20 26 5b 53 74 : bool, to: &[St
2050: 72 69 6e 67 5d 29 20 2d 3e 20 52 65 73 70 6f 6e ring]) -> Respon
2060: 73 65 20 7b 0a 09 09 73 65 6c 66 2e 68 65 61 64 se {...self.head
2070: 65 72 73 20 3d 20 53 6f 6d 65 28 53 6f 6d 65 48 ers = Some(SomeH
2080: 65 61 64 65 72 73 7b 0a 09 09 09 66 72 6f 6d 3a eaders{....from:
2090: 20 66 72 6f 6d 2e 74 6f 5f 73 74 72 69 6e 67 28 from.to_string(
20a0: 29 2c 0a 09 09 09 74 6f 3a 20 74 6f 2e 74 6f 5f ),....to: to.to_
20b0: 76 65 63 28 29 2c 0a 09 09 7d 29 3b 0a 09 09 4f vec(),...});...O
20c0: 4b 0a 09 7d 0a 0a 09 2f 2f 2f 20 53 61 76 65 20 K..}.../// Save
20d0: 63 68 75 6e 6b 28 3f 29 20 6f 66 20 64 61 74 61 chunk(?) of data
20e0: 0a 09 66 6e 20 64 61 74 61 20 28 26 6d 75 74 20 ..fn data (&mut
20f0: 73 65 6c 66 2c 20 62 75 66 3a 20 26 5b 75 38 5d self, buf: &[u8]
2100: 29 20 2d 3e 20 73 74 64 3a 3a 72 65 73 75 6c 74 ) -> std::result
2110: 3a 3a 52 65 73 75 6c 74 3c 28 29 2c 20 45 72 72 ::Result<(), Err
2120: 6f 72 3e 20 7b 0a 09 09 73 65 6c 66 2e 64 61 74 or> {...self.dat
2130: 61 2e 61 70 70 65 6e 64 28 62 75 66 2e 74 6f 5f a.append(buf.to_
2140: 76 65 63 28 29 2e 61 73 5f 6d 75 74 28 29 29 3b vec().as_mut());
2150: 0a 09 09 4f 6b 28 28 29 29 0a 09 7d 0a 0a 09 2f ...Ok(())..}.../
2160: 2f 2f 20 41 74 74 65 6d 70 74 20 74 6f 20 73 65 // Attempt to se
2170: 6e 64 20 65 6d 61 69 6c 2c 20 72 65 74 75 72 6e nd email, return
2180: 20 74 65 6d 70 6f 72 61 72 79 20 65 72 72 6f 72 temporary error
2190: 20 69 66 20 74 68 61 74 20 66 61 69 6c 73 0a 09 if that fails..
21a0: 66 6e 20 64 61 74 61 5f 65 6e 64 20 28 26 6d 75 fn data_end (&mu
21b0: 74 20 73 65 6c 66 29 20 2d 3e 20 52 65 73 70 6f t self) -> Respo
21c0: 6e 73 65 20 7b 0a 09 09 6c 65 74 20 6d 75 74 20 nse {...let mut
21d0: 72 65 73 75 6c 74 20 3d 20 4f 4b 3b 0a 09 09 73 result = OK;...s
21e0: 6d 6f 6c 3a 3a 62 6c 6f 63 6b 5f 6f 6e 28 43 6f mol::block_on(Co
21f0: 6d 70 61 74 3a 3a 6e 65 77 28 61 73 79 6e 63 20 mpat::new(async
2200: 7b 0a 09 09 09 2f 2f 20 72 65 6c 61 79 20 6d 61 {....// relay ma
2210: 69 6c 0a 09 09 09 69 66 20 6c 65 74 20 45 72 72 il....if let Err
2220: 28 65 72 72 29 20 3d 20 73 65 6c 66 2e 72 65 6c (err) = self.rel
2230: 61 79 5f 6d 61 69 6c 28 29 2e 61 77 61 69 74 20 ay_mail().await
2240: 7b 0a 09 09 09 09 72 65 73 75 6c 74 20 3d 20 49 {.....result = I
2250: 4e 54 45 52 4e 41 4c 5f 45 52 52 4f 52 3b 0a 09 NTERNAL_ERROR;..
2260: 09 09 09 2f 2f 20 69 6e 20 63 61 73 65 20 74 68 ...// in case th
2270: 61 74 20 66 61 69 6c 73 20 2d 20 69 6e 66 6f 72 at fails - infor
2280: 6d 20 64 65 66 61 75 6c 74 20 72 65 63 69 70 69 m default recipi
2290: 65 6e 74 0a 09 09 09 09 69 66 20 6c 65 74 20 45 ent.....if let E
22a0: 72 72 28 65 72 72 29 20 3d 20 73 65 6c 66 2e 74 rr(err) = self.t
22b0: 67 2e 64 65 62 75 67 28 26 66 6f 72 6d 61 74 21 g.debug(&format!
22c0: 28 22 53 65 6e 64 69 6e 67 20 65 6d 61 69 6c 73 ("Sending emails
22d0: 20 66 61 69 6c 65 64 3a 5c 6e 7b 65 72 72 3a 3f failed:\n{err:?
22e0: 7d 22 29 29 2e 61 77 61 69 74 20 7b 0a 09 09 09 }")).await {....
22f0: 09 09 2f 2f 20 69 6e 20 63 61 73 65 20 74 68 61 ..// in case tha
2300: 74 20 61 6c 73 6f 20 66 61 69 6c 73 20 2d 20 77 t also fails - w
2310: 72 69 74 65 20 73 6f 6d 65 20 6c 6f 67 73 20 61 rite some logs a
2320: 6e 64 20 62 61 69 6c 0a 09 09 09 09 09 65 70 72 nd bail......epr
2330: 69 6e 74 6c 6e 21 28 22 7b 65 72 72 3a 3f 7d 22 intln!("{err:?}"
2340: 29 3b 0a 09 09 09 09 7d 3b 0a 09 09 09 7d 3b 0a );.....};....};.
2350: 09 09 7d 29 29 3b 0a 09 09 2f 2f 20 63 6c 65 61 ..}));...// clea
2360: 72 20 2d 20 6a 75 73 74 20 69 6e 20 63 61 73 65 r - just in case
2370: 0a 09 09 73 65 6c 66 2e 64 61 74 61 20 3d 20 76 ...self.data = v
2380: 65 63 21 5b 5d 3b 0a 09 09 73 65 6c 66 2e 68 65 ec![];...self.he
2390: 61 64 65 72 73 20 3d 20 4e 6f 6e 65 3b 0a 09 09 aders = None;...
23a0: 72 65 73 75 6c 74 0a 09 7d 0a 7d 0a result..}.}.